aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2006-04-29 01:11:23 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2006-04-29 01:11:23 -0400
commit7b7e394185014e0f3bd8989cac937003f20ef9ce (patch)
tree3beda5f979bba0aa9822534e239cf1b45f3be69c
parentInput: move input_device_id to mod_devicetable.h (diff)
parent[PATCH] slab: fix crash on __drain_alien_cahce() during CPU Hotplug (diff)
downloadlinux-dev-7b7e394185014e0f3bd8989cac937003f20ef9ce.tar.xz
linux-dev-7b7e394185014e0f3bd8989cac937003f20ef9ce.zip
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
-rw-r--r--CREDITS6
-rw-r--r--Documentation/DMA-API.txt49
-rw-r--r--Documentation/DMA-mapping.txt26
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/kernel-api.tmpl1
-rw-r--r--Documentation/DocBook/libata.tmpl2
-rw-r--r--Documentation/HOWTO3
-rw-r--r--Documentation/acpi-hotkey.txt2
-rw-r--r--Documentation/block/switching-sched.txt22
-rw-r--r--Documentation/cpu-freq/index.txt2
-rw-r--r--Documentation/feature-removal-schedule.txt13
-rw-r--r--Documentation/filesystems/sysfs.txt5
-rw-r--r--Documentation/filesystems/vfs.txt12
-rw-r--r--Documentation/fujitsu/frv/kernel-ABI.txt192
-rw-r--r--Documentation/i2c/busses/i2c-parport16
-rw-r--r--Documentation/isdn/README.gigaset286
-rw-r--r--Documentation/kbuild/modules.txt2
-rw-r--r--Documentation/kernel-parameters.txt34
-rw-r--r--Documentation/laptop-mode.txt10
-rw-r--r--Documentation/memory-barriers.txt68
-rw-r--r--Documentation/mtrr.txt23
-rw-r--r--Documentation/networking/packet_mmap.txt2
-rw-r--r--Documentation/networking/tuntap.txt2
-rw-r--r--Documentation/networking/xfrm_sync.txt166
-rw-r--r--Documentation/pci.txt12
-rw-r--r--Documentation/pcmcia/driver-changes.txt6
-rw-r--r--Documentation/power/video.txt2
-rw-r--r--Documentation/scsi/scsi_eh.txt14
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt19
-rw-r--r--Documentation/serial/driver22
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt69
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl16
-rw-r--r--Documentation/video4linux/CARDLIST.saa71345
-rw-r--r--Documentation/video4linux/et61x251.txt (renamed from Documentation/usb/et61x251.txt)0
-rw-r--r--Documentation/video4linux/ibmcam.txt (renamed from Documentation/usb/ibmcam.txt)2
-rw-r--r--Documentation/video4linux/ov511.txt (renamed from Documentation/usb/ov511.txt)11
-rw-r--r--Documentation/video4linux/se401.txt (renamed from Documentation/usb/se401.txt)0
-rw-r--r--Documentation/video4linux/sn9c102.txt (renamed from Documentation/usb/sn9c102.txt)16
-rw-r--r--Documentation/video4linux/stv680.txt (renamed from Documentation/usb/stv680.txt)26
-rw-r--r--Documentation/video4linux/w9968cf.txt (renamed from Documentation/usb/w9968cf.txt)36
-rw-r--r--Documentation/video4linux/zc0301.txt (renamed from Documentation/usb/zc0301.txt)0
-rw-r--r--Documentation/vm/hugetlbpage.txt31
-rw-r--r--Documentation/x86_64/boot-options.txt5
-rw-r--r--Kbuild2
-rw-r--r--MAINTAINERS37
-rw-r--r--Makefile58
-rw-r--r--README23
-rw-r--r--arch/alpha/Kconfig5
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c1
-rw-r--r--arch/alpha/kernel/setup.c17
-rw-r--r--arch/alpha/kernel/smp.c8
-rw-r--r--arch/alpha/lib/strncpy.S8
-rw-r--r--arch/arm/Kconfig6
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.in1
-rw-r--r--arch/arm/common/scoop.c12
-rw-r--r--arch/arm/configs/at91rm9200dk_defconfig2
-rw-r--r--arch/arm/configs/at91rm9200ek_defconfig2
-rw-r--r--arch/arm/configs/ep93xx_defconfig79
-rw-r--r--arch/arm/configs/ixp2000_defconfig59
-rw-r--r--arch/arm/configs/ixp23xx_defconfig58
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/armksyms.c14
-rw-r--r--arch/arm/kernel/head-nommu.S4
-rw-r--r--arch/arm/kernel/setup.c17
-rw-r--r--arch/arm/mach-at91rm9200/Makefile9
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c10
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c10
-rw-r--r--arch/arm/mach-at91rm9200/devices.c166
-rw-r--r--arch/arm/mach-at91rm9200/leds.c100
-rw-r--r--arch/arm/mach-ep93xx/core.c10
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c39
-rw-r--r--arch/arm/mach-imx/dma.c511
-rw-r--r--arch/arm/mach-imx/generic.c13
-rw-r--r--arch/arm/mach-imx/mx1ads.c18
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c9
-rw-r--r--arch/arm/mach-ixp23xx/pci.c18
-rw-r--r--arch/arm/mach-ixp4xx/common.c2
-rw-r--r--arch/arm/mach-omap1/Kconfig20
-rw-r--r--arch/arm/mach-omap1/Makefile11
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c116
-rw-r--r--arch/arm/mach-omap1/board-generic.c2
-rw-r--r--arch/arm/mach-omap1/board-h2.c200
-rw-r--r--arch/arm/mach-omap1/board-h3.c277
-rw-r--r--arch/arm/mach-omap1/board-innovator.c56
-rw-r--r--arch/arm/mach-omap1/board-netstar.c160
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c268
-rw-r--r--arch/arm/mach-omap1/board-osk.c95
-rw-r--r--arch/arm/mach-omap1/board-palmte.c12
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c123
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c8
-rw-r--r--arch/arm/mach-omap1/clock.c9
-rw-r--r--arch/arm/mach-omap1/clock.h91
-rw-r--r--arch/arm/mach-omap1/devices.c45
-rw-r--r--arch/arm/mach-omap1/io.c4
-rw-r--r--arch/arm/mach-omap1/irq.c18
-rw-r--r--arch/arm/mach-omap1/mux.c30
-rw-r--r--arch/arm/mach-omap1/pm.c770
-rw-r--r--arch/arm/mach-omap1/serial.c6
-rw-r--r--arch/arm/mach-omap1/sleep.S (renamed from arch/arm/plat-omap/sleep.S)111
-rw-r--r--arch/arm/mach-omap1/time.c197
-rw-r--r--arch/arm/mach-omap2/Kconfig3
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/board-apollon.c285
-rw-r--r--arch/arm/mach-omap2/board-h4.c174
-rw-r--r--arch/arm/mach-omap2/clock.c79
-rw-r--r--arch/arm/mach-omap2/clock.h37
-rw-r--r--arch/arm/mach-omap2/devices.c46
-rw-r--r--arch/arm/mach-omap2/io.c21
-rw-r--r--arch/arm/mach-omap2/memory.c102
-rw-r--r--arch/arm/mach-omap2/memory.h34
-rw-r--r--arch/arm/mach-omap2/mux.c45
-rw-r--r--arch/arm/mach-omap2/pm.c149
-rw-r--r--arch/arm/mach-omap2/prcm-regs.h (renamed from arch/arm/mach-omap2/prcm.h)188
-rw-r--r--arch/arm/mach-omap2/prcm.c40
-rw-r--r--arch/arm/mach-omap2/sleep.S144
-rw-r--r--arch/arm/mach-omap2/sram-fn.S4
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c9
-rw-r--r--arch/arm/mach-pxa/poodle.c4
-rw-r--r--arch/arm/mach-s3c2410/Kconfig7
-rw-r--r--arch/arm/mach-s3c2410/Makefile2
-rw-r--r--arch/arm/mach-s3c2410/clock.c6
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.c135
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.h15
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c35
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c13
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c17
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c2
-rw-r--r--arch/arm/mach-sa1100/collie.c72
-rw-r--r--arch/arm/mm/cache-v4wb.S26
-rw-r--r--arch/arm/mm/consistent.c17
-rw-r--r--arch/arm/mm/init.c7
-rw-r--r--arch/arm/mm/mm-armv.c11
-rw-r--r--arch/arm/mm/proc-sa110.S25
-rw-r--r--arch/arm/mm/proc-sa1100.S37
-rw-r--r--arch/arm/mm/proc-xsc3.S2
-rw-r--r--arch/arm/plat-omap/Kconfig4
-rw-r--r--arch/arm/plat-omap/Makefile6
-rw-r--r--arch/arm/plat-omap/clock.c68
-rw-r--r--arch/arm/plat-omap/devices.c159
-rw-r--r--arch/arm/plat-omap/dma.c6
-rw-r--r--arch/arm/plat-omap/dmtimer.c26
-rw-r--r--arch/arm/plat-omap/fb.c80
-rw-r--r--arch/arm/plat-omap/gpio.c86
-rw-r--r--arch/arm/plat-omap/mcbsp.c345
-rw-r--r--arch/arm/plat-omap/ocpi.c3
-rw-r--r--arch/arm/plat-omap/pm.c1
-rw-r--r--arch/arm/plat-omap/sram.c143
-rw-r--r--arch/arm/plat-omap/timer32k.c325
-rw-r--r--arch/arm/vfp/vfpdouble.c31
-rw-r--r--arch/arm/vfp/vfphw.S6
-rw-r--r--arch/arm/vfp/vfpmodule.c2
-rw-r--r--arch/arm/vfp/vfpsingle.c11
-rw-r--r--arch/arm26/kernel/armksyms.c1
-rw-r--r--arch/cris/kernel/crisksyms.c1
-rw-r--r--arch/frv/kernel/entry.S26
-rw-r--r--arch/frv/kernel/frv_ksyms.c1
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c1
-rw-r--r--arch/i386/Kconfig77
-rw-r--r--arch/i386/Kconfig.cpu2
-rw-r--r--arch/i386/Kconfig.debug9
-rw-r--r--arch/i386/boot/video.S5
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/acpi/boot.c11
-rw-r--r--arch/i386/kernel/apic.c23
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/kernel/cpu/amd.c4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c22
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c2
-rw-r--r--arch/i386/kernel/cpuid.c2
-rw-r--r--arch/i386/kernel/crash.c2
-rw-r--r--arch/i386/kernel/i386_ksyms.c1
-rw-r--r--arch/i386/kernel/kprobes.c39
-rw-r--r--arch/i386/kernel/mpparse.c43
-rw-r--r--arch/i386/kernel/msr.c2
-rw-r--r--arch/i386/kernel/reboot_fixups.c2
-rw-r--r--arch/i386/kernel/setup.c36
-rw-r--r--arch/i386/kernel/smpboot.c4
-rw-r--r--arch/i386/kernel/syscall_table.S1
-rw-r--r--arch/i386/kernel/traps.c16
-rw-r--r--arch/i386/mach-voyager/voyager_cat.c11
-rw-r--r--arch/i386/mm/init.c2
-rw-r--r--arch/i386/pci/direct.c13
-rw-r--r--arch/i386/pci/irq.c2
-rw-r--r--arch/i386/pci/mmconfig.c67
-rw-r--r--arch/ia64/Kconfig21
-rw-r--r--arch/ia64/configs/sn2_defconfig76
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c3
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/kernel/Makefile3
-rw-r--r--arch/ia64/kernel/acpi-ext.c143
-rw-r--r--arch/ia64/kernel/entry.S5
-rw-r--r--arch/ia64/kernel/kprobes.c10
-rw-r--r--arch/ia64/kernel/mca.c43
-rw-r--r--arch/ia64/kernel/mca_asm.S10
-rw-r--r--arch/ia64/kernel/mca_drv.c54
-rw-r--r--arch/ia64/kernel/module.c2
-rw-r--r--arch/ia64/kernel/palinfo.c2
-rw-r--r--arch/ia64/kernel/salinfo.c2
-rw-r--r--arch/ia64/kernel/topology.c9
-rw-r--r--arch/ia64/mm/discontig.c66
-rw-r--r--arch/ia64/mm/fault.c3
-rw-r--r--arch/ia64/pci/pci.c3
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c8
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c2
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c8
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c6
-rw-r--r--arch/m32r/Kconfig5
-rw-r--r--arch/m32r/kernel/entry.S55
-rw-r--r--arch/m32r/kernel/m32r_ksyms.c29
-rw-r--r--arch/m32r/kernel/process.c4
-rw-r--r--arch/m32r/kernel/setup.c12
-rw-r--r--arch/m32r/kernel/signal.c4
-rw-r--r--arch/m32r/kernel/smpboot.c19
-rw-r--r--arch/m32r/lib/Makefile4
-rw-r--r--arch/m32r/lib/getuser.S88
-rw-r--r--arch/m32r/lib/putuser.S84
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c1
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c1
-rw-r--r--arch/mips/Kconfig80
-rw-r--r--arch/mips/Kconfig.debug8
-rw-r--r--arch/mips/Makefile17
-rw-r--r--arch/mips/au1000/common/Makefile2
-rw-r--r--arch/mips/au1000/common/int-handler.S68
-rw-r--r--arch/mips/au1000/common/irq.c20
-rw-r--r--arch/mips/cobalt/Makefile2
-rw-r--r--arch/mips/cobalt/int-handler.S25
-rw-r--r--arch/mips/cobalt/irq.c6
-rw-r--r--arch/mips/configs/atlas_defconfig83
-rw-r--r--arch/mips/configs/bigsur_defconfig64
-rw-r--r--arch/mips/configs/capcella_defconfig143
-rw-r--r--arch/mips/configs/cobalt_defconfig68
-rw-r--r--arch/mips/configs/db1000_defconfig70
-rw-r--r--arch/mips/configs/db1100_defconfig71
-rw-r--r--arch/mips/configs/db1200_defconfig68
-rw-r--r--arch/mips/configs/db1500_defconfig105
-rw-r--r--arch/mips/configs/db1550_defconfig73
-rw-r--r--arch/mips/configs/ddb5476_defconfig69
-rw-r--r--arch/mips/configs/ddb5477_defconfig67
-rw-r--r--arch/mips/configs/decstation_defconfig69
-rw-r--r--arch/mips/configs/e55_defconfig288
-rw-r--r--arch/mips/configs/ev64120_defconfig67
-rw-r--r--arch/mips/configs/ev96100_defconfig64
-rw-r--r--arch/mips/configs/ip22_defconfig77
-rw-r--r--arch/mips/configs/ip27_defconfig54
-rw-r--r--arch/mips/configs/ip32_defconfig67
-rw-r--r--arch/mips/configs/it8172_defconfig66
-rw-r--r--arch/mips/configs/ivr_defconfig67
-rw-r--r--arch/mips/configs/jaguar-atx_defconfig56
-rw-r--r--arch/mips/configs/jmr3927_defconfig72
-rw-r--r--arch/mips/configs/lasat200_defconfig69
-rw-r--r--arch/mips/configs/malta_defconfig86
-rw-r--r--arch/mips/configs/mipssim_defconfig64
-rw-r--r--arch/mips/configs/mpc30x_defconfig95
-rw-r--r--arch/mips/configs/ocelot_3_defconfig72
-rw-r--r--arch/mips/configs/ocelot_c_defconfig66
-rw-r--r--arch/mips/configs/ocelot_defconfig64
-rw-r--r--arch/mips/configs/ocelot_g_defconfig66
-rw-r--r--arch/mips/configs/pb1100_defconfig70
-rw-r--r--arch/mips/configs/pb1500_defconfig73
-rw-r--r--arch/mips/configs/pb1550_defconfig73
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig76
-rw-r--r--arch/mips/configs/pnx8550-v2pci_defconfig85
-rw-r--r--arch/mips/configs/qemu_defconfig48
-rw-r--r--arch/mips/configs/rbhma4500_defconfig95
-rw-r--r--arch/mips/configs/rm200_defconfig121
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig63
-rw-r--r--arch/mips/configs/sead_defconfig50
-rw-r--r--arch/mips/configs/tb0226_defconfig218
-rw-r--r--arch/mips/configs/tb0229_defconfig282
-rw-r--r--arch/mips/configs/tb0287_defconfig1132
-rw-r--r--arch/mips/configs/workpad_defconfig185
-rw-r--r--arch/mips/configs/yosemite_defconfig54
-rw-r--r--arch/mips/ddb5xxx/ddb5074/Makefile2
-rw-r--r--arch/mips/ddb5xxx/ddb5074/int-handler.S120
-rw-r--r--arch/mips/ddb5xxx/ddb5074/irq.c26
-rw-r--r--arch/mips/ddb5xxx/ddb5476/Makefile2
-rw-r--r--arch/mips/ddb5xxx/ddb5476/int-handler.S112
-rw-r--r--arch/mips/ddb5xxx/ddb5476/irq.c30
-rw-r--r--arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c6
-rw-r--r--arch/mips/ddb5xxx/ddb5477/Makefile2
-rw-r--r--arch/mips/ddb5xxx/ddb5477/int-handler.S75
-rw-r--r--arch/mips/ddb5xxx/ddb5477/irq.c24
-rw-r--r--arch/mips/dec/boot/decstation.c3
-rw-r--r--arch/mips/dec/int-handler.S14
-rw-r--r--arch/mips/dec/setup.c3
-rw-r--r--arch/mips/defconfig77
-rw-r--r--arch/mips/galileo-boards/ev96100/Makefile2
-rw-r--r--arch/mips/galileo-boards/ev96100/int-handler.S33
-rw-r--r--arch/mips/galileo-boards/ev96100/irq.c19
-rw-r--r--arch/mips/gt64120/ev64120/Makefile2
-rw-r--r--arch/mips/gt64120/ev64120/int-handler.S113
-rw-r--r--arch/mips/gt64120/ev64120/irq.c27
-rw-r--r--arch/mips/gt64120/momenco_ocelot/Makefile2
-rw-r--r--arch/mips/gt64120/momenco_ocelot/int-handler.S131
-rw-r--r--arch/mips/gt64120/momenco_ocelot/irq.c36
-rw-r--r--arch/mips/ite-boards/generic/Makefile2
-rw-r--r--arch/mips/ite-boards/generic/int-handler.S63
-rw-r--r--arch/mips/ite-boards/generic/irq.c18
-rw-r--r--arch/mips/ite-boards/generic/time.c1
-rw-r--r--arch/mips/ite-boards/ivr/init.c2
-rw-r--r--arch/mips/ite-boards/qed-4n-s01b/init.c2
-rw-r--r--arch/mips/jazz/Makefile2
-rw-r--r--arch/mips/jazz/int-handler.S282
-rw-r--r--arch/mips/jazz/irq.c78
-rw-r--r--arch/mips/jmr3927/common/rtc_ds1742.c60
-rw-r--r--arch/mips/jmr3927/rbhma3100/Makefile2
-rw-r--r--arch/mips/jmr3927/rbhma3100/int-handler.S74
-rw-r--r--arch/mips/jmr3927/rbhma3100/irq.c6
-rw-r--r--arch/mips/kernel/Makefile5
-rw-r--r--arch/mips/kernel/asm-offsets.c3
-rw-r--r--arch/mips/kernel/branch.c2
-rw-r--r--arch/mips/kernel/entry.S69
-rw-r--r--arch/mips/kernel/gdb-low.S24
-rw-r--r--arch/mips/kernel/gdb-stub.c61
-rw-r--r--arch/mips/kernel/genex.S43
-rw-r--r--arch/mips/kernel/head.S57
-rw-r--r--arch/mips/kernel/i8259.c4
-rw-r--r--arch/mips/kernel/irq-msc01.c9
-rw-r--r--arch/mips/kernel/irq.c18
-rw-r--r--arch/mips/kernel/kspd.c398
-rw-r--r--arch/mips/kernel/linux32.c74
-rw-r--r--arch/mips/kernel/mips-mt.c449
-rw-r--r--arch/mips/kernel/mips_ksyms.c16
-rw-r--r--arch/mips/kernel/process.c21
-rw-r--r--arch/mips/kernel/ptrace.c14
-rw-r--r--arch/mips/kernel/ptrace32.c14
-rw-r--r--arch/mips/kernel/r4k_switch.S34
-rw-r--r--arch/mips/kernel/rtlx.c518
-rw-r--r--arch/mips/kernel/scall32-o32.S13
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c5
-rw-r--r--arch/mips/kernel/smp-mt.c (renamed from arch/mips/kernel/smp_mt.c)44
-rw-r--r--arch/mips/kernel/smp.c12
-rw-r--r--arch/mips/kernel/smtc-asm.S130
-rw-r--r--arch/mips/kernel/smtc-proc.c93
-rw-r--r--arch/mips/kernel/smtc.c1322
-rw-r--r--arch/mips/kernel/time.c3
-rw-r--r--arch/mips/kernel/traps.c212
-rw-r--r--arch/mips/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/kernel/vpe.c665
-rw-r--r--arch/mips/lasat/Makefile2
-rw-r--r--arch/mips/lasat/interrupt.c14
-rw-r--r--arch/mips/lasat/lasatIRQ.S69
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c92
-rw-r--r--arch/mips/mips-boards/generic/Makefile4
-rw-r--r--arch/mips/mips-boards/generic/gdb_hook.c2
-rw-r--r--arch/mips/mips-boards/generic/init.c2
-rw-r--r--arch/mips/mips-boards/generic/memory.c9
-rw-r--r--arch/mips/mips-boards/generic/mipsIRQ.S155
-rw-r--r--arch/mips/mips-boards/generic/pci.c1
-rw-r--r--arch/mips/mips-boards/generic/time.c68
-rw-r--r--arch/mips/mips-boards/malta/Makefile1
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c105
-rw-r--r--arch/mips/mips-boards/malta/malta_smp.c128
-rw-r--r--arch/mips/mips-boards/sead/sead_int.c86
-rw-r--r--arch/mips/mips-boards/sim/cmdline.c59
-rw-r--r--arch/mips/mips-boards/sim/sim_cmdline.c6
-rw-r--r--arch/mips/mips-boards/sim/sim_int.c64
-rw-r--r--arch/mips/mips-boards/sim/sim_irq.S4
-rw-r--r--arch/mips/mips-boards/sim/sim_mem.c9
-rw-r--r--arch/mips/mips-boards/sim/sim_smp.c14
-rw-r--r--arch/mips/mm/c-r3k.c5
-rw-r--r--arch/mips/mm/c-r4k.c20
-rw-r--r--arch/mips/mm/c-sb1.c1
-rw-r--r--arch/mips/mm/c-tx39.c7
-rw-r--r--arch/mips/mm/cache.c1
-rw-r--r--arch/mips/mm/fault.c13
-rw-r--r--arch/mips/mm/highmem.c2
-rw-r--r--arch/mips/mm/init.c48
-rw-r--r--arch/mips/mm/sc-rm7k.c2
-rw-r--r--arch/mips/mm/tlb-r4k.c85
-rw-r--r--arch/mips/mm/tlbex.c87
-rw-r--r--arch/mips/momentum/jaguar_atx/Makefile2
-rw-r--r--arch/mips/momentum/jaguar_atx/int-handler.S128
-rw-r--r--arch/mips/momentum/jaguar_atx/irq.c35
-rw-r--r--arch/mips/momentum/jaguar_atx/setup.c36
-rw-r--r--arch/mips/momentum/ocelot_3/Makefile2
-rw-r--r--arch/mips/momentum/ocelot_3/int-handler.S137
-rw-r--r--arch/mips/momentum/ocelot_3/irq.c38
-rw-r--r--arch/mips/momentum/ocelot_3/setup.c24
-rw-r--r--arch/mips/momentum/ocelot_c/Makefile2
-rw-r--r--arch/mips/momentum/ocelot_c/int-handler.S102
-rw-r--r--arch/mips/momentum/ocelot_c/irq.c30
-rw-r--r--arch/mips/momentum/ocelot_g/Makefile2
-rw-r--r--arch/mips/momentum/ocelot_g/int-handler.S131
-rw-r--r--arch/mips/momentum/ocelot_g/irq.c38
-rw-r--r--arch/mips/oprofile/common.c5
-rw-r--r--arch/mips/philips/pnx8550/common/Makefile2
-rw-r--r--arch/mips/philips/pnx8550/common/int.c23
-rw-r--r--arch/mips/philips/pnx8550/common/mipsIRQ.S76
-rw-r--r--arch/mips/philips/pnx8550/common/platform.c1
-rw-r--r--arch/mips/pmc-sierra/yosemite/Makefile2
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq-handler.S93
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq.c33
-rw-r--r--arch/mips/qemu/Makefile2
-rw-r--r--arch/mips/qemu/q-int.S17
-rw-r--r--arch/mips/qemu/q-irq.c3
-rw-r--r--arch/mips/sgi-ip22/Makefile2
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c59
-rw-r--r--arch/mips/sgi-ip22/ip22-irq.S118
-rw-r--r--arch/mips/sgi-ip27/Makefile2
-rw-r--r--arch/mips/sgi-ip27/TODO4
-rw-r--r--arch/mips/sgi-ip27/ip27-irq-glue.S45
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c27
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c2
-rw-r--r--arch/mips/sgi-ip32/Makefile2
-rw-r--r--arch/mips/sgi-ip32/ip32-irq-glue.S86
-rw-r--r--arch/mips/sgi-ip32/ip32-irq.c40
-rw-r--r--arch/mips/sibyte/bcm1480/Makefile2
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c77
-rw-r--r--arch/mips/sibyte/bcm1480/irq_handler.S165
-rw-r--r--arch/mips/sibyte/sb1250/Makefile2
-rw-r--r--arch/mips/sibyte/sb1250/irq.c78
-rw-r--r--arch/mips/sibyte/sb1250/irq_handler.S147
-rw-r--r--arch/mips/sni/Makefile2
-rw-r--r--arch/mips/sni/int-handler.S106
-rw-r--r--arch/mips/sni/irq.c37
-rw-r--r--arch/mips/tx4927/common/Makefile2
-rw-r--r--arch/mips/tx4927/common/tx4927_irq.c30
-rw-r--r--arch/mips/tx4927/common/tx4927_irq_handler.S103
-rw-r--r--arch/mips/tx4938/common/Makefile2
-rw-r--r--arch/mips/tx4938/common/irq.c21
-rw-r--r--arch/mips/tx4938/common/irq_handler.S84
-rw-r--r--arch/mips/vr41xx/Kconfig13
-rw-r--r--arch/mips/vr41xx/common/Makefile2
-rw-r--r--arch/mips/vr41xx/common/int-handler.S114
-rw-r--r--arch/mips/vr41xx/common/irq.c29
-rw-r--r--arch/parisc/Kconfig36
-rw-r--r--arch/parisc/defconfig494
-rw-r--r--arch/parisc/kernel/asm-offsets.c3
-rw-r--r--arch/parisc/kernel/cache.c4
-rw-r--r--arch/parisc/kernel/entry.S36
-rw-r--r--arch/parisc/kernel/head.S15
-rw-r--r--arch/parisc/kernel/init_task.c10
-rw-r--r--arch/parisc/kernel/pacache.S25
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c1
-rw-r--r--arch/parisc/kernel/sys_parisc.c8
-rw-r--r--arch/parisc/kernel/syscall.S10
-rw-r--r--arch/parisc/kernel/syscall_table.S8
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S54
-rw-r--r--arch/parisc/mm/fault.c2
-rw-r--r--arch/parisc/mm/init.c28
-rw-r--r--arch/parisc/mm/ioremap.c3
-rw-r--r--arch/powerpc/Kconfig11
-rw-r--r--arch/powerpc/Makefile4
-rw-r--r--arch/powerpc/configs/g5_defconfig58
-rw-r--r--arch/powerpc/configs/iseries_defconfig43
-rw-r--r--arch/powerpc/configs/pseries_defconfig54
-rw-r--r--arch/powerpc/kernel/Makefile2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/entry_32.S35
-rw-r--r--arch/powerpc/kernel/head_64.S49
-rw-r--r--arch/powerpc/kernel/idle.c4
-rw-r--r--arch/powerpc/kernel/idle_6xx.S63
-rw-r--r--arch/powerpc/kernel/idle_power4.S10
-rw-r--r--arch/powerpc/kernel/iommu.c36
-rw-r--r--arch/powerpc/kernel/irq.c36
-rw-r--r--arch/powerpc/kernel/kprobes.c14
-rw-r--r--arch/powerpc/kernel/lparcfg.c31
-rw-r--r--arch/powerpc/kernel/pci_iommu.c40
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/prom.c2
-rw-r--r--arch/powerpc/kernel/prom_init.c5
-rw-r--r--arch/powerpc/kernel/rtas-proc.c4
-rw-r--r--arch/powerpc/kernel/rtas.c12
-rw-r--r--arch/powerpc/kernel/setup_32.c6
-rw-r--r--arch/powerpc/kernel/setup_64.c10
-rw-r--r--arch/powerpc/kernel/sysfs.c4
-rw-r--r--arch/powerpc/kernel/systbl.S8
-rw-r--r--arch/powerpc/kernel/traps.c9
-rw-r--r--arch/powerpc/kernel/vio.c6
-rw-r--r--arch/powerpc/mm/fault.c6
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c40
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c40
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c7
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c2
-rw-r--r--arch/powerpc/platforms/chrp/chrp.h1
-rw-r--r--arch/powerpc/platforms/chrp/pci.c6
-rw-r--r--arch/powerpc/platforms/chrp/setup.c44
-rw-r--r--arch/powerpc/platforms/iseries/setup.c7
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c78
-rw-r--r--arch/powerpc/platforms/powermac/pci.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c68
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c19
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c30
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S100
-rw-r--r--arch/powerpc/platforms/pseries/hvconsole.c6
-rw-r--r--arch/powerpc/platforms/pseries/hvcserver.c22
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c31
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/vio.c4
-rw-r--r--arch/powerpc/platforms/pseries/xics.c8
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c12
-rw-r--r--arch/ppc/boot/lib/Makefile2
-rw-r--r--arch/ppc/kernel/asm-offsets.c1
-rw-r--r--arch/ppc/kernel/entry.S33
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c1
-rw-r--r--arch/ppc/syslib/ppc_sys.c9
-rw-r--r--arch/s390/Makefile1
-rw-r--r--arch/s390/appldata/appldata_base.c2
-rw-r--r--arch/s390/defconfig48
-rw-r--r--arch/s390/kernel/compat_signal.c2
-rw-r--r--arch/s390/kernel/compat_wrapper.S42
-rw-r--r--arch/s390/kernel/syscalls.S5
-rw-r--r--arch/s390/kernel/vmlinux.lds.S4
-rw-r--r--arch/s390/mm/extmem.c19
-rw-r--r--arch/sh/Kconfig5
-rw-r--r--arch/sh/kernel/sh_ksyms.c1
-rw-r--r--arch/sh64/kernel/sh_ksyms.c1
-rw-r--r--arch/sparc/kernel/smp.c2
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c1
-rw-r--r--arch/sparc/kernel/systbls.S6
-rw-r--r--arch/sparc/math-emu/Makefile2
-rw-r--r--arch/sparc64/Kconfig5
-rw-r--r--arch/sparc64/defconfig22
-rw-r--r--arch/sparc64/kernel/kprobes.c12
-rw-r--r--arch/sparc64/kernel/pci.c1
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c2
-rw-r--r--arch/sparc64/kernel/ptrace.c23
-rw-r--r--arch/sparc64/kernel/setup.c2
-rw-r--r--arch/sparc64/kernel/smp.c50
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c1
-rw-r--r--arch/sparc64/kernel/sys32.S3
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c8
-rw-r--r--arch/sparc64/kernel/systbls.S12
-rw-r--r--arch/sparc64/kernel/traps.c4
-rw-r--r--arch/sparc64/mm/fault.c6
-rw-r--r--arch/sparc64/mm/hugetlbpage.c7
-rw-r--r--arch/um/Makefile3
-rw-r--r--arch/um/drivers/cow.h2
-rw-r--r--arch/um/drivers/cow_sys.h2
-rw-r--r--arch/um/drivers/cow_user.c96
-rw-r--r--arch/um/drivers/mconsole_kern.c8
-rw-r--r--arch/um/drivers/net_user.c4
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/include/kern_util.h4
-rw-r--r--arch/um/include/longjmp.h4
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h2
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h2
-rw-r--r--arch/um/include/tt/tt.h3
-rw-r--r--arch/um/include/user.h6
-rw-r--r--arch/um/include/user_util.h3
-rw-r--r--arch/um/kernel/ksyms.c5
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/helper.c10
-rw-r--r--arch/um/os-Linux/mem.c141
-rw-r--r--arch/um/os-Linux/process.c8
-rw-r--r--arch/um/os-Linux/sigio.c2
-rw-r--r--arch/um/os-Linux/skas/mem.c4
-rw-r--r--arch/um/os-Linux/skas/process.c40
-rw-r--r--arch/um/os-Linux/start_up.c24
-rw-r--r--arch/um/os-Linux/sys-i386/tls.c1
-rw-r--r--arch/um/os-Linux/trap.c4
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/umid.c15
-rw-r--r--arch/um/os-Linux/user_syms.c9
-rw-r--r--arch/um/os-Linux/util.c2
-rw-r--r--arch/um/scripts/Makefile.rules6
-rw-r--r--arch/um/sys-i386/ksyms.c4
-rw-r--r--arch/um/sys-i386/ptrace_user.c2
-rw-r--r--arch/um/sys-i386/signal.c8
-rw-r--r--arch/um/sys-i386/stub_segv.c4
-rw-r--r--arch/um/sys-i386/tls.c2
-rw-r--r--arch/um/sys-x86_64/signal.c2
-rw-r--r--arch/um/sys-x86_64/stub_segv.c10
-rw-r--r--arch/v850/kernel/v850_ksyms.c1
-rw-r--r--arch/x86_64/Kconfig10
-rw-r--r--arch/x86_64/Makefile24
-rw-r--r--arch/x86_64/boot/video.S5
-rw-r--r--arch/x86_64/defconfig57
-rw-r--r--arch/x86_64/ia32/Makefile4
-rw-r--r--arch/x86_64/ia32/ia32entry.S24
-rw-r--r--arch/x86_64/kernel/Makefile4
-rw-r--r--arch/x86_64/kernel/aperture.c2
-rw-r--r--arch/x86_64/kernel/e820.c36
-rw-r--r--arch/x86_64/kernel/entry.S28
-rw-r--r--arch/x86_64/kernel/kprobes.c10
-rw-r--r--arch/x86_64/kernel/mce.c10
-rw-r--r--arch/x86_64/kernel/mce_amd.c2
-rw-r--r--arch/x86_64/kernel/nmi.c7
-rw-r--r--arch/x86_64/kernel/pci-dma.c2
-rw-r--r--arch/x86_64/kernel/pci-gart.c4
-rw-r--r--arch/x86_64/kernel/process.c14
-rw-r--r--arch/x86_64/kernel/ptrace.c5
-rw-r--r--arch/x86_64/kernel/setup.c8
-rw-r--r--arch/x86_64/kernel/time.c4
-rw-r--r--arch/x86_64/kernel/traps.c5
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S2
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c3
-rw-r--r--arch/x86_64/mm/init.c37
-rw-r--r--arch/x86_64/mm/numa.c48
-rw-r--r--arch/x86_64/mm/srat.c170
-rw-r--r--arch/x86_64/pci/mmconfig.c53
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c1
-rw-r--r--block/as-iosched.c5
-rw-r--r--block/cfq-iosched.c53
-rw-r--r--block/elevator.c2
-rw-r--r--block/ll_rw_blk.c8
-rw-r--r--block/scsi_ioctl.c101
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/base/bus.c5
-rw-r--r--drivers/base/class.c13
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/node.c2
-rw-r--r--drivers/base/power/suspend.c12
-rw-r--r--drivers/base/topology.c2
-rw-r--r--drivers/block/cciss.c96
-rw-r--r--drivers/bluetooth/bluecard_cs.c119
-rw-r--r--drivers/bluetooth/bt3c_cs.c130
-rw-r--r--drivers/bluetooth/btuart_cs.c130
-rw-r--r--drivers/bluetooth/dtl1_cs.c120
-rw-r--r--drivers/cdrom/aztcd.c2
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/efficeon-agp.c8
-rw-r--r--drivers/char/applicom.c2
-rw-r--r--drivers/char/cs5535_gpio.c5
-rw-r--r--drivers/char/drm/drmP.h5
-rw-r--r--drivers/char/drm/drm_agpsupport.c2
-rw-r--r--drivers/char/drm/drm_bufs.c5
-rw-r--r--drivers/char/drm/drm_drv.c4
-rw-r--r--drivers/char/drm/drm_memory.c134
-rw-r--r--drivers/char/drm/drm_memory.h128
-rw-r--r--drivers/char/drm/drm_memory_debug.h2
-rw-r--r--drivers/char/drm/drm_pci.c1
-rw-r--r--drivers/char/drm/drm_stub.c2
-rw-r--r--drivers/char/drm/r300_cmdbuf.c2
-rw-r--r--drivers/char/drm/via_irq.c12
-rw-r--r--drivers/char/dtlk.c2
-rw-r--r--drivers/char/hvcs.c2
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c2
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c4
-rw-r--r--drivers/char/mem.c14
-rw-r--r--drivers/char/mwave/mwavedd.c2
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c121
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c133
-rw-r--r--drivers/char/pcmcia/synclink_cs.c116
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/char/snsc.c3
-rw-r--r--drivers/char/sonypi.c3
-rw-r--r--drivers/char/tipar.c2
-rw-r--r--drivers/char/tlclk.c36
-rw-r--r--drivers/char/tpm/Kconfig11
-rw-r--r--drivers/char/tpm/Makefile1
-rw-r--r--drivers/char/tpm/tpm.c786
-rw-r--r--drivers/char/tpm/tpm.h37
-rw-r--r--drivers/char/tpm/tpm_atmel.c58
-rw-r--r--drivers/char/tpm/tpm_atmel.h25
-rw-r--r--drivers/char/tpm/tpm_bios.c52
-rw-r--r--drivers/char/tpm/tpm_infineon.c61
-rw-r--r--drivers/char/tpm/tpm_nsc.c49
-rw-r--r--drivers/char/tpm/tpm_tis.c669
-rw-r--r--drivers/char/tty_io.c36
-rw-r--r--drivers/char/watchdog/Kconfig7
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/at91_wdt.c228
-rw-r--r--drivers/char/watchdog/pcwd.c137
-rw-r--r--drivers/char/watchdog/pcwd_usb.c3
-rw-r--r--drivers/cpufreq/Kconfig2
-rw-r--r--drivers/cpufreq/cpufreq.c27
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c6
-rw-r--r--drivers/firmware/Makefile3
-rw-r--r--drivers/firmware/dmi_scan.c (renamed from arch/i386/kernel/dmi_scan.c)12
-rw-r--r--drivers/hwmon/hdaps.c51
-rw-r--r--drivers/hwmon/w83792d.c5
-rw-r--r--drivers/i2c/busses/Kconfig5
-rw-r--r--drivers/i2c/busses/i2c-i801.c5
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.h2
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c8
-rw-r--r--drivers/i2c/chips/ds1374.c16
-rw-r--r--drivers/i2c/chips/m41t00.c24
-rw-r--r--drivers/ide/legacy/ide-cs.c127
-rw-r--r--drivers/ide/pci/alim15x3.c2
-rw-r--r--drivers/ide/pci/atiixp.c1
-rw-r--r--drivers/ide/pci/pdc202xx_old.c2
-rw-r--r--drivers/ide/setup-pci.c13
-rw-r--r--drivers/ieee1394/sbp2.c32
-rw-r--r--drivers/infiniband/Kconfig1
-rw-r--r--drivers/infiniband/Makefile1
-rw-r--r--drivers/infiniband/core/cache.c2
-rw-r--r--drivers/infiniband/core/mad.c7
-rw-r--r--drivers/infiniband/core/verbs.c34
-rw-r--r--drivers/infiniband/hw/ipath/Kconfig16
-rw-r--r--drivers/infiniband/hw/ipath/Makefile36
-rw-r--r--drivers/infiniband/hw/ipath/ipath_common.h616
-rw-r--r--drivers/infiniband/hw/ipath/ipath_cq.c295
-rw-r--r--drivers/infiniband/hw/ipath/ipath_debug.h96
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c367
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c1983
-rw-r--r--drivers/infiniband/hw/ipath/ipath_eeprom.c613
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c1910
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c605
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ht400.c1586
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c951
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c841
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h883
-rw-r--r--drivers/infiniband/hw/ipath/ipath_keys.c236
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.c1515
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.h181
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c1352
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mr.c383
-rw-r--r--drivers/infiniband/hw/ipath/ipath_pe800.c1247
-rw-r--r--drivers/infiniband/hw/ipath/ipath_qp.c913
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c1857
-rw-r--r--drivers/infiniband/hw/ipath/ipath_registers.h446
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c552
-rw-r--r--drivers/infiniband/hw/ipath/ipath_srq.c273
-rw-r--r--drivers/infiniband/hw/ipath/ipath_stats.c303
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sysfs.c778
-rw-r--r--drivers/infiniband/hw/ipath/ipath_uc.c645
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ud.c621
-rw-r--r--drivers/infiniband/hw/ipath/ipath_user_pages.c207
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c1222
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.h692
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs_mcast.c333
-rw-r--r--drivers/infiniband/hw/ipath/ipath_wc_x86_64.c157
-rw-r--r--drivers/infiniband/hw/ipath/ips_common.h263
-rw-r--r--drivers/infiniband/hw/ipath/verbs_debug.h107
-rw-r--r--drivers/infiniband/hw/mthca/Kconfig11
-rw-r--r--drivers/infiniband/hw/mthca/Makefile4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c100
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h23
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c42
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c28
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c46
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c27
-rw-r--r--drivers/infiniband/ulp/ipoib/Kconfig3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c22
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c88
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c58
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c6
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c19
-rw-r--r--drivers/input/keyboard/hil_kbd.c2
-rw-r--r--drivers/isdn/gigaset/Kconfig4
-rw-r--r--drivers/isdn/gigaset/asyncdata.c132
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c1321
-rw-r--r--drivers/isdn/gigaset/common.c504
-rw-r--r--drivers/isdn/gigaset/ev-layer.c670
-rw-r--r--drivers/isdn/gigaset/gigaset.h601
-rw-r--r--drivers/isdn/gigaset/i4l.c229
-rw-r--r--drivers/isdn/gigaset/interface.c235
-rw-r--r--drivers/isdn/gigaset/isocdata.c139
-rw-r--r--drivers/isdn/gigaset/proc.c51
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c455
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c185
-rw-r--r--drivers/isdn/hisax/avma1_cs.c182
-rw-r--r--drivers/isdn/hisax/elsa_cs.c112
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c143
-rw-r--r--drivers/isdn/hisax/teles_cs.c121
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c20
-rw-r--r--drivers/leds/Kconfig27
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-s3c24xx.c163
-rw-r--r--drivers/macintosh/therm_adt746x.c4
-rw-r--r--drivers/md/Kconfig11
-rw-r--r--drivers/md/dm-target.c3
-rw-r--r--drivers/md/md.c25
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c6
-rw-r--r--drivers/md/raid5.c34
-rw-r--r--drivers/md/raid6main.c29
-rw-r--r--drivers/media/Kconfig24
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig1
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c18
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h2
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c54
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c47
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h2
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c5
-rw-r--r--drivers/media/dvb/frontends/Kconfig12
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c12
-rw-r--r--drivers/media/dvb/ttpci/av7110.c8
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c2
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c13
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c78
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c24
-rw-r--r--drivers/media/dvb/ttpci/budget.h13
-rw-r--r--drivers/media/video/Kconfig233
-rw-r--r--drivers/media/video/Makefile8
-rw-r--r--drivers/media/video/bt8xx/Makefile2
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c170
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c2
-rw-r--r--drivers/media/video/cpia.c13
-rw-r--r--drivers/media/video/cpia2/cpia2.h2
-rw-r--r--drivers/media/video/cx25840/Makefile2
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c3
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c24
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h (renamed from drivers/media/video/cx25840/cx25840.h)46
-rw-r--r--drivers/media/video/cx25840/cx25840-firmware.c15
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c9
-rw-r--r--drivers/media/video/cx88/Kconfig15
-rw-r--r--drivers/media/video/cx88/Makefile6
-rw-r--r--drivers/media/video/em28xx/Makefile2
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c33
-rw-r--r--drivers/media/video/et61x251/Kconfig14
-rw-r--r--drivers/media/video/ir-kbd-i2c.c3
-rw-r--r--drivers/media/video/msp3400-driver.c91
-rw-r--r--drivers/media/video/msp3400-driver.h6
-rw-r--r--drivers/media/video/msp3400-kthreads.c121
-rw-r--r--drivers/media/video/pwc/Kconfig28
-rw-r--r--drivers/media/video/saa7115.c65
-rw-r--r--drivers/media/video/saa7127.c43
-rw-r--r--drivers/media/video/saa7134/Kconfig1
-rw-r--r--drivers/media/video/saa7134/Makefile6
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c66
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c3
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c4
-rw-r--r--drivers/media/video/saa7134/saa7134.h1
-rw-r--r--drivers/media/video/sn9c102/Kconfig11
-rw-r--r--drivers/media/video/tuner-core.c12
-rw-r--r--drivers/media/video/tvaudio.c15
-rw-r--r--drivers/media/video/tveeprom.c6
-rw-r--r--drivers/media/video/tvp5150.c140
-rw-r--r--drivers/media/video/upd64031a.c286
-rw-r--r--drivers/media/video/upd64083.c262
-rw-r--r--drivers/media/video/usbvideo/Kconfig38
-rw-r--r--drivers/media/video/usbvideo/Makefile8
-rw-r--r--drivers/media/video/v4l2-common.c8
-rw-r--r--drivers/media/video/video-buf.c14
-rw-r--r--drivers/media/video/wm8739.c355
-rw-r--r--drivers/media/video/zc0301/Kconfig11
-rw-r--r--drivers/message/fusion/mptsas.c10
-rw-r--r--drivers/mmc/Kconfig18
-rw-r--r--drivers/mmc/Makefile2
-rw-r--r--drivers/mmc/at91_mci.c988
-rw-r--r--drivers/mmc/imxmmc.c1096
-rw-r--r--drivers/mmc/imxmmc.h67
-rw-r--r--drivers/mmc/pxamci.c10
-rw-r--r--drivers/mtd/chips/Kconfig21
-rw-r--r--drivers/mtd/devices/Kconfig13
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/blkmtd.c819
-rw-r--r--drivers/mtd/maps/pcmciamtd.c115
-rw-r--r--drivers/net/8139cp.c12
-rw-r--r--drivers/net/arcnet/arcnet.c3
-rw-r--r--drivers/net/arcnet/com90xx.c4
-rw-r--r--drivers/net/b44.c67
-rw-r--r--drivers/net/bnx2.c2
-rw-r--r--drivers/net/chelsio/Makefile2
-rw-r--r--drivers/net/chelsio/sge.c3
-rw-r--r--drivers/net/e1000/e1000_main.c4
-rw-r--r--drivers/net/eql.c3
-rw-r--r--drivers/net/forcedeth.c79
-rw-r--r--drivers/net/gianfar.c56
-rw-r--r--drivers/net/gianfar.h67
-rw-r--r--drivers/net/gianfar_ethtool.c20
-rw-r--r--drivers/net/gianfar_sysfs.c24
-rw-r--r--drivers/net/hydra.h177
-rw-r--r--drivers/net/ibmveth.c30
-rw-r--r--drivers/net/irda/irda-usb.c365
-rw-r--r--drivers/net/irda/irda-usb.h43
-rw-r--r--drivers/net/irda/sa1100_ir.c3
-rw-r--r--drivers/net/irda/smsc-ircc2.c523
-rw-r--r--drivers/net/ixgb/ixgb_main.c13
-rw-r--r--drivers/net/mv643xx_eth.c19
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/ne.c2
-rw-r--r--drivers/net/ne2k-pci.c4
-rw-r--r--drivers/net/netconsole.c1
-rw-r--r--drivers/net/ns83820.c3
-rw-r--r--drivers/net/pcmcia/3c574_cs.c115
-rw-r--r--drivers/net/pcmcia/3c589_cs.c122
-rw-r--r--drivers/net/pcmcia/axnet_cs.c128
-rw-r--r--drivers/net/pcmcia/com20020_cs.c127
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c166
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c121
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c126
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c162
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c235
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c185
-rw-r--r--drivers/net/skge.c2
-rw-r--r--drivers/net/sky2.c58
-rw-r--r--drivers/net/sky2.h4
-rw-r--r--drivers/net/starfire.c5
-rw-r--r--drivers/net/sungem_phy.c11
-rw-r--r--drivers/net/tg3.c94
-rw-r--r--drivers/net/tg3.h3
-rw-r--r--drivers/net/tokenring/abyss.c3
-rw-r--r--drivers/net/tokenring/madgemc.c3
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--drivers/net/via-rhine.c7
-rw-r--r--drivers/net/wan/Kconfig97
-rw-r--r--drivers/net/wan/Makefile13
-rw-r--r--drivers/net/wan/sdla_chdlc.c4428
-rw-r--r--drivers/net/wan/sdla_fr.c5061
-rw-r--r--drivers/net/wan/sdla_ft1.c345
-rw-r--r--drivers/net/wan/sdla_ppp.c3430
-rw-r--r--drivers/net/wan/sdla_x25.c5497
-rw-r--r--drivers/net/wan/sdladrv.c2314
-rw-r--r--drivers/net/wan/sdlamain.c1346
-rw-r--r--drivers/net/wan/wanpipe_multppp.c2358
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/airo.c46
-rw-r--r--drivers/net/wireless/airo_cs.c158
-rw-r--r--drivers/net/wireless/atmel.c11
-rw-r--r--drivers/net/wireless/atmel_cs.c162
-rw-r--r--drivers/net/wireless/bcm43xx/Kconfig3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h17
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c13
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c92
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.h16
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.c115
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.h9
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c115
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h16
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c8
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c198
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c4
-rw-r--r--drivers/net/wireless/ipw2200.c9
-rw-r--r--drivers/net/wireless/netwave_cs.c127
-rw-r--r--drivers/net/wireless/orinoco.c2
-rw-r--r--drivers/net/wireless/orinoco_cs.c187
-rw-r--r--drivers/net/wireless/ray_cs.c279
-rw-r--r--drivers/net/wireless/ray_cs.h2
-rw-r--r--drivers/net/wireless/spectrum_cs.c173
-rw-r--r--drivers/net/wireless/wavelan_cs.c189
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h6
-rw-r--r--drivers/net/wireless/wl3501.h1
-rw-r--r--drivers/net/wireless/wl3501_cs.c178
-rw-r--r--drivers/net/yellowfin.c3
-rw-r--r--drivers/parisc/pdc_stable.c2
-rw-r--r--drivers/parisc/sba_iommu.c45
-rw-r--r--drivers/parisc/superio.c4
-rw-r--r--drivers/parport/parport_cs.c129
-rw-r--r--drivers/parport/parport_pc.c20
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c3
-rw-r--r--drivers/pci/msi.c231
-rw-r--r--drivers/pci/pci-driver.c6
-rw-r--r--drivers/pci/pci.c12
-rw-r--r--drivers/pci/pci.h11
-rw-r--r--drivers/pci/quirks.c39
-rw-r--r--drivers/pcmcia/Kconfig9
-rw-r--r--drivers/pcmcia/Makefile3
-rw-r--r--drivers/pcmcia/at91_cf.c376
-rw-r--r--drivers/pcmcia/cistpl.c1
-rw-r--r--drivers/pcmcia/cs.c43
-rw-r--r--drivers/pcmcia/cs_internal.h19
-rw-r--r--drivers/pcmcia/ds.c261
-rw-r--r--drivers/pcmcia/ds_internal.h4
-rw-r--r--drivers/pcmcia/i82092.c1
-rw-r--r--drivers/pcmcia/i82365.c8
-rw-r--r--drivers/pcmcia/pcmcia_compat.c65
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c81
-rw-r--r--drivers/pcmcia/pcmcia_resource.c232
-rw-r--r--drivers/pcmcia/pd6729.c1
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c8
-rw-r--r--drivers/pcmcia/rsrc_mgr.c5
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c41
-rw-r--r--drivers/pcmcia/sa1100_cerf.c1
-rw-r--r--drivers/pcmcia/socket_sysfs.c10
-rw-r--r--drivers/pcmcia/ti113x.h1
-rw-r--r--drivers/pnp/manager.c4
-rw-r--r--drivers/rtc/Kconfig10
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/class.c2
-rw-r--r--drivers/rtc/rtc-ds1672.c72
-rw-r--r--drivers/rtc/rtc-ep93xx.c2
-rw-r--r--drivers/rtc/rtc-m48t86.c9
-rw-r--r--drivers/rtc/rtc-pcf8563.c11
-rw-r--r--drivers/rtc/rtc-proc.c2
-rw-r--r--drivers/rtc/rtc-rs5c372.c28
-rw-r--r--drivers/rtc/rtc-sa1100.c14
-rw-r--r--drivers/rtc/rtc-test.c3
-rw-r--r--drivers/rtc/rtc-vr41xx.c (renamed from drivers/char/vr41xx_rtc.c)404
-rw-r--r--drivers/rtc/rtc-x1205.c29
-rw-r--r--drivers/s390/block/dasd.c50
-rw-r--r--drivers/s390/block/dasd_devmap.c102
-rw-r--r--drivers/s390/block/dasd_eckd.c51
-rw-r--r--drivers/s390/block/dasd_eckd.h46
-rw-r--r--drivers/s390/block/dasd_erp.c8
-rw-r--r--drivers/s390/block/dasd_int.h12
-rw-r--r--drivers/s390/block/dasd_proc.c17
-rw-r--r--drivers/s390/char/keyboard.c2
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/tape_3590.c22
-rw-r--r--drivers/s390/char/tape_block.c17
-rw-r--r--drivers/s390/char/tape_core.c10
-rw-r--r--drivers/s390/char/tape_std.h1
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/cio/chsc.c30
-rw-r--r--drivers/s390/cio/cio.c2
-rw-r--r--drivers/s390/cio/cio_debug.h22
-rw-r--r--drivers/s390/cio/qdio.c36
-rw-r--r--drivers/s390/net/lcs.c13
-rw-r--r--drivers/s390/s390mach.c33
-rw-r--r--drivers/scsi/3w-9xxx.c9
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/Kconfig24
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/aacraid/aachba.c94
-rw-r--r--drivers/scsi/aacraid/aacraid.h11
-rw-r--r--drivers/scsi/aacraid/commctrl.c12
-rw-r--r--drivers/scsi/aacraid/commsup.c41
-rw-r--r--drivers/scsi/aacraid/linit.c64
-rw-r--r--drivers/scsi/aacraid/rkt.c4
-rw-r--r--drivers/scsi/aacraid/rx.c4
-rw-r--r--drivers/scsi/aacraid/sa.c2
-rw-r--r--drivers/scsi/ahci.c1
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c166
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4
-rw-r--r--drivers/scsi/ata_piix.c1
-rw-r--r--drivers/scsi/hosts.c12
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c251
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c11
-rw-r--r--drivers/scsi/ibmvscsi/srp.h227
-rw-r--r--drivers/scsi/ibmvscsi/viosrp.h17
-rw-r--r--drivers/scsi/ipr.c122
-rw-r--r--drivers/scsi/ipr.h46
-rw-r--r--drivers/scsi/libata-core.c1
-rw-r--r--drivers/scsi/libata-scsi.c8
-rw-r--r--drivers/scsi/libata.h1
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c112
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c155
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c136
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h8
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c127
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c124
-rw-r--r--drivers/scsi/pdc_adma.c1
-rw-r--r--drivers/scsi/qlogicfc.c2228
-rw-r--r--drivers/scsi/qlogicfc_asm.c9751
-rw-r--r--drivers/scsi/sata_mv.c3
-rw-r--r--drivers/scsi/sata_nv.c1
-rw-r--r--drivers/scsi/sata_promise.c1
-rw-r--r--drivers/scsi/sata_qstor.c1
-rw-r--r--drivers/scsi/sata_sil.c1
-rw-r--r--drivers/scsi/sata_sil24.c1
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c1
-rw-r--r--drivers/scsi/sata_sx4.c1
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c1
-rw-r--r--drivers/scsi/scsi.c5
-rw-r--r--drivers/scsi/scsi_devinfo.c4
-rw-r--r--drivers/scsi/scsi_error.c4
-rw-r--r--drivers/scsi/scsi_ioctl.c176
-rw-r--r--drivers/scsi/scsi_lib.c15
-rw-r--r--drivers/scsi/scsi_sas_internal.h38
-rw-r--r--drivers/scsi/scsi_scan.c19
-rw-r--r--drivers/scsi/scsi_transport_fc.c466
-rw-r--r--drivers/scsi/scsi_transport_sas.c67
-rw-r--r--drivers/scsi/sg.c7
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c205
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c113
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h2
-rw-r--r--drivers/serial/jsm/jsm.h2
-rw-r--r--drivers/serial/jsm/jsm_driver.c2
-rw-r--r--drivers/serial/jsm/jsm_neo.c2
-rw-r--r--drivers/serial/m32r_sio.c1
-rw-r--r--drivers/serial/serial_cs.c229
-rw-r--r--drivers/sn/ioc3.c5
-rw-r--r--drivers/telephony/ixj_pcmcia.c119
-rw-r--r--drivers/usb/atm/ueagle-atm.c52
-rw-r--r--drivers/usb/core/Kconfig7
-rw-r--r--drivers/usb/core/hcd-pci.c7
-rw-r--r--drivers/usb/core/hub.c8
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/gadget/Kconfig4
-rw-r--r--drivers/usb/gadget/at91_udc.c4
-rw-r--r--drivers/usb/gadget/ether.c6
-rw-r--r--drivers/usb/gadget/file_storage.c38
-rw-r--r--drivers/usb/gadget/gadget_chips.h6
-rw-r--r--drivers/usb/gadget/inode.c25
-rw-r--r--drivers/usb/gadget/net2280.c108
-rw-r--r--drivers/usb/gadget/net2280.h415
-rw-r--r--drivers/usb/gadget/zero.c7
-rw-r--r--drivers/usb/host/ehci-pci.c2
-rw-r--r--drivers/usb/host/ohci-at91.c35
-rw-r--r--drivers/usb/host/ohci-pci.c2
-rw-r--r--drivers/usb/host/ohci-s3c2410.c41
-rw-r--r--drivers/usb/host/pci-quirks.c1
-rw-r--r--drivers/usb/host/pci-quirks.h7
-rw-r--r--drivers/usb/host/sl811_cs.c119
-rw-r--r--drivers/usb/host/uhci-hcd.c9
-rw-r--r--drivers/usb/host/uhci-hcd.h1
-rw-r--r--drivers/usb/host/uhci-hub.c18
-rw-r--r--drivers/usb/input/Kconfig56
-rw-r--r--drivers/usb/input/Makefile1
-rw-r--r--drivers/usb/input/hid-core.c14
-rw-r--r--drivers/usb/input/hid-ff.c6
-rw-r--r--drivers/usb/input/hid.h5
-rw-r--r--drivers/usb/input/keyspan_remote.c2
-rw-r--r--drivers/usb/input/usbtouchscreen.c605
-rw-r--r--drivers/usb/input/wacom.c136
-rw-r--r--drivers/usb/misc/usbtest.c13
-rw-r--r--drivers/usb/net/asix.c327
-rw-r--r--drivers/usb/net/pegasus.c2
-rw-r--r--drivers/usb/net/rndis_host.c28
-rw-r--r--drivers/usb/serial/Kconfig9
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/console.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c5
-rw-r--r--drivers/usb/serial/ftdi_sio.h28
-rw-r--r--drivers/usb/serial/funsoft.c65
-rw-r--r--drivers/usb/serial/option.c5
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/pl2303.h5
-rw-r--r--drivers/usb/serial/usb-serial.c16
-rw-r--r--drivers/usb/serial/usb-serial.h6
-rw-r--r--drivers/usb/serial/whiteheat.c1
-rw-r--r--drivers/usb/storage/Kconfig3
-rw-r--r--drivers/usb/storage/unusual_devs.h9
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/aty/atyfb_base.c2
-rw-r--r--drivers/video/aty/radeon_base.c2
-rw-r--r--drivers/video/fbmem.c19
-rw-r--r--drivers/video/fbsysfs.c92
-rw-r--r--drivers/video/pm2fb.c4
-rw-r--r--drivers/video/savage/savagefb_driver.c8
-rw-r--r--drivers/video/vesafb.c27
-rw-r--r--fs/9p/vfs_super.c13
-rw-r--r--fs/Kconfig9
-rw-r--r--fs/cifs/CHANGES6
-rw-r--r--fs/cifs/README8
-rw-r--r--fs/cifs/cifsfs.c99
-rw-r--r--fs/cifs/cifssmb.c2
-rw-r--r--fs/cifs/connect.c6
-rw-r--r--fs/cifs/dir.c18
-rw-r--r--fs/cifs/fcntl.c2
-rw-r--r--fs/cifs/file.c34
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/link.c6
-rw-r--r--fs/cifs/ntlmssp.c14
-rw-r--r--fs/cifs/readdir.c45
-rw-r--r--fs/cifs/xattr.c8
-rw-r--r--fs/compat.c4
-rw-r--r--fs/configfs/dir.c2
-rw-r--r--fs/direct-io.c3
-rw-r--r--fs/dquot.c6
-rw-r--r--fs/eventpoll.c4
-rw-r--r--fs/exec.c48
-rw-r--r--fs/ext3/ioctl.c18
-rw-r--r--fs/ext3/resize.c4
-rw-r--r--fs/fcntl.c3
-rw-r--r--fs/fifo.c65
-rw-r--r--fs/freevxfs/vxfs_olt.c9
-rw-r--r--fs/fuse/dev.c279
-rw-r--r--fs/fuse/dir.c118
-rw-r--r--fs/fuse/file.c66
-rw-r--r--fs/fuse/fuse_i.h64
-rw-r--r--fs/fuse/inode.c138
-rw-r--r--fs/hfsplus/bnode.c6
-rw-r--r--fs/hfsplus/btree.c3
-rw-r--r--fs/inode.c15
-rw-r--r--fs/inotify.c2
-rw-r--r--fs/jffs2/background.c3
-rw-r--r--fs/lockd/svclock.c2
-rw-r--r--fs/locks.c9
-rw-r--r--fs/namespace.c7
-rw-r--r--fs/nfs/dir.c5
-rw-r--r--fs/nfs/direct.c8
-rw-r--r--fs/nfs/file.c5
-rw-r--r--fs/nfs/inode.c5
-rw-r--r--fs/nfs/nfs4proc.c10
-rw-r--r--fs/nfsd/auth.c46
-rw-r--r--fs/nfsd/export.c3
-rw-r--r--fs/nfsd/nfs3proc.c2
-rw-r--r--fs/nfsd/nfs4acl.c8
-rw-r--r--fs/nfsd/nfs4callback.c6
-rw-r--r--fs/nfsd/nfs4proc.c4
-rw-r--r--fs/nfsd/nfs4state.c150
-rw-r--r--fs/nfsd/nfs4xdr.c62
-rw-r--r--fs/nfsd/nfsproc.c2
-rw-r--r--fs/nfsd/vfs.c6
-rw-r--r--fs/ocfs2/cluster/heartbeat.c40
-rw-r--r--fs/ocfs2/dlm/userdlm.c74
-rw-r--r--fs/ocfs2/file.c19
-rw-r--r--fs/open.c24
-rw-r--r--fs/partitions/check.c43
-rw-r--r--fs/pipe.c321
-rw-r--r--fs/proc/base.c21
-rw-r--r--fs/proc/vmcore.c4
-rw-r--r--fs/read_write.c2
-rw-r--r--fs/reiserfs/xattr_acl.c5
-rw-r--r--fs/select.c30
-rw-r--r--fs/smbfs/file.c6
-rw-r--r--fs/splice.c1332
-rw-r--r--fs/sync.c4
-rw-r--r--fs/sysfs/dir.c3
-rw-r--r--fs/sysfs/file.c78
-rw-r--r--fs/sysfs/inode.c3
-rw-r--r--fs/sysfs/sysfs.h1
-rw-r--r--fs/sysv/dir.c6
-rw-r--r--fs/udf/inode.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c18
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c117
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c122
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h11
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h12
-rw-r--r--fs/xfs/quota/xfs_qm.c17
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c68
-rw-r--r--fs/xfs/xfs_bmap.c11
-rw-r--r--fs/xfs/xfs_bmap.h9
-rw-r--r--fs/xfs/xfs_clnt.h1
-rw-r--r--fs/xfs/xfs_error.h3
-rw-r--r--fs/xfs/xfs_ialloc.c15
-rw-r--r--fs/xfs/xfs_iget.c29
-rw-r--r--fs/xfs/xfs_inode.c27
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_mount.c73
-rw-r--r--fs/xfs/xfs_mount.h5
-rw-r--r--fs/xfs/xfs_quota.h5
-rw-r--r--fs/xfs/xfs_vfsops.c10
-rw-r--r--fs/xfs/xfs_vnodeops.c4
-rw-r--r--include/asm-alpha/numnodes.h7
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_mci.h104
-rw-r--r--include/asm-arm/arch-at91rm9200/board.h24
-rw-r--r--include/asm-arm/arch-at91rm9200/hardware.h3
-rw-r--r--include/asm-arm/arch-cl7500/hardware.h4
-rw-r--r--include/asm-arm/arch-cl7500/memory.h6
-rw-r--r--include/asm-arm/arch-ebsa110/debug-macro.S2
-rw-r--r--include/asm-arm/arch-ebsa110/hardware.h3
-rw-r--r--include/asm-arm/arch-ebsa110/memory.h6
-rw-r--r--include/asm-arm/arch-ebsa110/uncompress.h2
-rw-r--r--include/asm-arm/arch-ebsa285/hardware.h7
-rw-r--r--include/asm-arm/arch-ebsa285/memory.h12
-rw-r--r--include/asm-arm/arch-ep93xx/ts72xx.h11
-rw-r--r--include/asm-arm/arch-imx/dma.h17
-rw-r--r--include/asm-arm/arch-imx/imx-dma.h90
-rw-r--r--include/asm-arm/arch-imx/mmc.h12
-rw-r--r--include/asm-arm/arch-ixp23xx/debug-macro.S3
-rw-r--r--include/asm-arm/arch-ixp23xx/memory.h17
-rw-r--r--include/asm-arm/arch-ixp23xx/platform.h1
-rw-r--r--include/asm-arm/arch-l7200/hardware.h3
-rw-r--r--include/asm-arm/arch-l7200/memory.h6
-rw-r--r--include/asm-arm/arch-lh7a40x/memory.h2
-rw-r--r--include/asm-arm/arch-omap/aic23.h4
-rw-r--r--include/asm-arm/arch-omap/board-ams-delta.h65
-rw-r--r--include/asm-arm/arch-omap/board-apollon.h45
-rw-r--r--include/asm-arm/arch-omap/board-h2.h4
-rw-r--r--include/asm-arm/arch-omap/board-h3.h4
-rw-r--r--include/asm-arm/arch-omap/board-h4.h8
-rw-r--r--include/asm-arm/arch-omap/board-netstar.h19
-rw-r--r--include/asm-arm/arch-omap/board-nokia.h54
-rw-r--r--include/asm-arm/arch-omap/board-perseus2.h4
-rw-r--r--include/asm-arm/arch-omap/board.h30
-rw-r--r--include/asm-arm/arch-omap/clock.h13
-rw-r--r--include/asm-arm/arch-omap/dma.h1
-rw-r--r--include/asm-arm/arch-omap/dmtimer.h1
-rw-r--r--include/asm-arm/arch-omap/dsp.h6
-rw-r--r--include/asm-arm/arch-omap/dsp_common.h13
-rw-r--r--include/asm-arm/arch-omap/gpioexpander.h24
-rw-r--r--include/asm-arm/arch-omap/hardware.h8
-rw-r--r--include/asm-arm/arch-omap/irda.h36
-rw-r--r--include/asm-arm/arch-omap/irqs.h5
-rw-r--r--include/asm-arm/arch-omap/keypad.h36
-rw-r--r--include/asm-arm/arch-omap/lcd_lph8923.h14
-rw-r--r--include/asm-arm/arch-omap/mcbsp.h65
-rw-r--r--include/asm-arm/arch-omap/mcspi.h16
-rw-r--r--include/asm-arm/arch-omap/menelaus.h2
-rw-r--r--include/asm-arm/arch-omap/mux.h54
-rw-r--r--include/asm-arm/arch-omap/omap-alsa.h124
-rw-r--r--include/asm-arm/arch-omap/omapfb.h98
-rw-r--r--include/asm-arm/arch-omap/param.h8
-rw-r--r--include/asm-arm/arch-omap/pm.h81
-rw-r--r--include/asm-arm/arch-omap/prcm.h404
-rw-r--r--include/asm-arm/arch-omap/sram.h2
-rw-r--r--include/asm-arm/arch-omap/system.h17
-rw-r--r--include/asm-arm/arch-rpc/hardware.h3
-rw-r--r--include/asm-arm/arch-rpc/memory.h6
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S167
-rw-r--r--include/asm-arm/arch-s3c2410/leds-gpio.h28
-rw-r--r--include/asm-arm/arch-sa1100/hardware.h4
-rw-r--r--include/asm-arm/arch-sa1100/memory.h7
-rw-r--r--include/asm-arm/arch-shark/hardware.h6
-rw-r--r--include/asm-arm/arch-shark/memory.h6
-rw-r--r--include/asm-arm/dma-mapping.h22
-rw-r--r--include/asm-arm/fpstate.h2
-rw-r--r--include/asm-arm/memory.h16
-rw-r--r--include/asm-arm/numnodes.h26
-rw-r--r--include/asm-arm/pgtable-hwdef.h1
-rw-r--r--include/asm-arm/pgtable.h1
-rw-r--r--include/asm-arm/unistd.h18
-rw-r--r--include/asm-arm/vfpmacros.h8
-rw-r--r--include/asm-cris/system.h1
-rw-r--r--include/asm-cris/unistd.h2
-rw-r--r--include/asm-frv/system.h2
-rw-r--r--include/asm-frv/unistd.h2
-rw-r--r--include/asm-h8300/system.h2
-rw-r--r--include/asm-h8300/unistd.h2
-rw-r--r--include/asm-i386/apic.h2
-rw-r--r--include/asm-i386/atomic.h5
-rw-r--r--include/asm-i386/cpufeature.h1
-rw-r--r--include/asm-i386/e820.h4
-rw-r--r--include/asm-i386/hpet.h1
-rw-r--r--include/asm-i386/i387.h30
-rw-r--r--include/asm-i386/mpspec.h1
-rw-r--r--include/asm-i386/numnodes.h18
-rw-r--r--include/asm-i386/pgtable-2level.h3
-rw-r--r--include/asm-i386/pgtable-3level.h20
-rw-r--r--include/asm-i386/pgtable.h4
-rw-r--r--include/asm-i386/unistd.h10
-rw-r--r--include/asm-ia64/acpi-ext.h11
-rw-r--r--include/asm-ia64/acpi.h5
-rw-r--r--include/asm-ia64/kdebug.h2
-rw-r--r--include/asm-ia64/machvec.h2
-rw-r--r--include/asm-ia64/mca.h5
-rw-r--r--include/asm-ia64/mutex.h2
-rw-r--r--include/asm-ia64/numnodes.h20
-rw-r--r--include/asm-ia64/sn/sn2/sn_hwperf.h6
-rw-r--r--include/asm-ia64/sn/sn_sal.h17
-rw-r--r--include/asm-ia64/thread_info.h2
-rw-r--r--include/asm-ia64/topology.h5
-rw-r--r--include/asm-ia64/unistd.h7
-rw-r--r--include/asm-ia64/vga.h2
-rw-r--r--include/asm-m32r/assembler.h5
-rw-r--r--include/asm-m32r/mappi3/mappi3_pld.h22
-rw-r--r--include/asm-m32r/numnodes.h15
-rw-r--r--include/asm-m32r/ptrace.h25
-rw-r--r--include/asm-m32r/semaphore.h64
-rw-r--r--include/asm-m32r/sigcontext.h2
-rw-r--r--include/asm-m32r/smp.h3
-rw-r--r--include/asm-m32r/system.h71
-rw-r--r--include/asm-m32r/uaccess.h266
-rw-r--r--include/asm-m32r/unistd.h2
-rw-r--r--include/asm-mips/asmmacro.h47
-rw-r--r--include/asm-mips/bitops.h56
-rw-r--r--include/asm-mips/cacheflush.h1
-rw-r--r--include/asm-mips/cpu-features.h2
-rw-r--r--include/asm-mips/cpu-info.h10
-rw-r--r--include/asm-mips/ds1742.h13
-rw-r--r--include/asm-mips/elf.h45
-rw-r--r--include/asm-mips/fpu.h4
-rw-r--r--include/asm-mips/hazards.h2
-rw-r--r--include/asm-mips/interrupt.h65
-rw-r--r--include/asm-mips/irq.h30
-rw-r--r--include/asm-mips/kspd.h36
-rw-r--r--include/asm-mips/mach-generic/ide.h46
-rw-r--r--include/asm-mips/mach-jmr3927/ds1742.h4
-rw-r--r--include/asm-mips/mach-mips/param.h13
-rw-r--r--include/asm-mips/marvell.h2
-rw-r--r--include/asm-mips/mips-boards/atlas.h18
-rw-r--r--include/asm-mips/mips-boards/atlasint.h19
-rw-r--r--include/asm-mips/mips-boards/generic.h1
-rw-r--r--include/asm-mips/mips_mt.h15
-rw-r--r--include/asm-mips/mipsmtregs.h16
-rw-r--r--include/asm-mips/mipsregs.h136
-rw-r--r--include/asm-mips/mmu_context.h112
-rw-r--r--include/asm-mips/numnodes.h7
-rw-r--r--include/asm-mips/processor.h22
-rw-r--r--include/asm-mips/ptrace.h4
-rw-r--r--include/asm-mips/r4kcache.h130
-rw-r--r--include/asm-mips/rtc.h4
-rw-r--r--include/asm-mips/rtlx.h38
-rw-r--r--include/asm-mips/serial.h12
-rw-r--r--include/asm-mips/smtc.h55
-rw-r--r--include/asm-mips/smtc_ipi.h118
-rw-r--r--include/asm-mips/smtc_proc.h23
-rw-r--r--include/asm-mips/stackframe.h187
-rw-r--r--include/asm-mips/system.h34
-rw-r--r--include/asm-mips/unistd.h18
-rw-r--r--include/asm-mips/vpe.h37
-rw-r--r--include/asm-parisc/io.h17
-rw-r--r--include/asm-parisc/numnodes.h7
-rw-r--r--include/asm-parisc/page.h25
-rw-r--r--include/asm-parisc/pgtable.h63
-rw-r--r--include/asm-parisc/unistd.h8
-rw-r--r--include/asm-powerpc/eeh.h20
-rw-r--r--include/asm-powerpc/hvcall.h185
-rw-r--r--include/asm-powerpc/iommu.h7
-rw-r--r--include/asm-powerpc/irq.h7
-rw-r--r--include/asm-powerpc/machdep.h6
-rw-r--r--include/asm-powerpc/numnodes.h9
-rw-r--r--include/asm-powerpc/thread_info.h8
-rw-r--r--include/asm-powerpc/unistd.h4
-rw-r--r--include/asm-s390/atomic.h2
-rw-r--r--include/asm-s390/cache.h2
-rw-r--r--include/asm-s390/ebcdic.h12
-rw-r--r--include/asm-s390/futex.h123
-rw-r--r--include/asm-sh/numnodes.h7
-rw-r--r--include/asm-sh/unistd.h2
-rw-r--r--include/asm-sh64/unistd.h2
-rw-r--r--include/asm-sparc/unistd.h8
-rw-r--r--include/asm-sparc/vga.h33
-rw-r--r--include/asm-sparc64/percpu.h2
-rw-r--r--include/asm-sparc64/unistd.h6
-rw-r--r--include/asm-um/ptrace-i386.h3
-rw-r--r--include/asm-v850/system.h2
-rw-r--r--include/asm-x86_64/cache.h4
-rw-r--r--include/asm-x86_64/cpufeature.h1
-rw-r--r--include/asm-x86_64/e820.h3
-rw-r--r--include/asm-x86_64/hpet.h2
-rw-r--r--include/asm-x86_64/i387.h20
-rw-r--r--include/asm-x86_64/ia32_unistd.h2
-rw-r--r--include/asm-x86_64/io.h2
-rw-r--r--include/asm-x86_64/mce.h7
-rw-r--r--include/asm-x86_64/mmzone.h3
-rw-r--r--include/asm-x86_64/numa.h3
-rw-r--r--include/asm-x86_64/numnodes.h12
-rw-r--r--include/asm-x86_64/percpu.h2
-rw-r--r--include/asm-x86_64/timex.h2
-rw-r--r--include/asm-x86_64/unistd.h10
-rw-r--r--include/asm-xtensa/ioctls.h2
-rw-r--r--include/asm-xtensa/signal.h2
-rw-r--r--include/asm-xtensa/system.h2
-rw-r--r--include/linux/blkdev.h4
-rw-r--r--include/linux/bootmem.h1
-rw-r--r--include/linux/debugfs.h5
-rw-r--r--include/linux/dma-mapping.h2
-rw-r--r--include/linux/fs.h21
-rw-r--r--include/linux/genhd.h1
-rw-r--r--include/linux/gfp.h2
-rw-r--r--include/linux/hrtimer.h2
-rw-r--r--include/linux/ide.h1
-rw-r--r--include/linux/init.h3
-rw-r--r--include/linux/jiffies.h6
-rw-r--r--include/linux/kernel.h2
-rw-r--r--include/linux/kobject.h5
-rw-r--r--include/linux/leds.h51
-rw-r--r--include/linux/libata.h1
-rw-r--r--include/linux/memory_hotplug.h11
-rw-r--r--include/linux/mm.h5
-rw-r--r--include/linux/mv643xx.h2
-rw-r--r--include/linux/netdevice.h18
-rw-r--r--include/linux/netfilter.h42
-rw-r--r--include/linux/netfilter/x_tables.h71
-rw-r--r--include/linux/netfilter/xt_esp.h14
-rw-r--r--include/linux/netfilter/xt_multiport.h30
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h52
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h)0
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_types.h)0
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h18
-rw-r--r--include/linux/netfilter_ipv4/ipt_esp.h14
-rw-r--r--include/linux/netfilter_ipv4/ipt_multiport.h31
-rw-r--r--include/linux/netfilter_ipv6.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6t_esp.h12
-rw-r--r--include/linux/netfilter_ipv6/ip6t_multiport.h25
-rw-r--r--include/linux/numa.h8
-rw-r--r--include/linux/page-flags.h24
-rw-r--r--include/linux/pagemap.h2
-rw-r--r--include/linux/pci.h33
-rw-r--r--include/linux/pci_ids.h7
-rw-r--r--include/linux/pipe_fs_i.h45
-rw-r--r--include/linux/pm.h8
-rw-r--r--include/linux/pm_legacy.h7
-rw-r--r--include/linux/proc_fs.h2
-rw-r--r--include/linux/raid/md_p.h2
-rw-r--r--include/linux/sched.h15
-rw-r--r--include/linux/screen_info.h3
-rw-r--r--include/linux/sdla_asy.h226
-rw-r--r--include/linux/sdla_chdlc.h813
-rw-r--r--include/linux/sdla_ppp.h575
-rw-r--r--include/linux/sdla_x25.h772
-rw-r--r--include/linux/sdladrv.h66
-rw-r--r--include/linux/sdlapci.h72
-rw-r--r--include/linux/sdlasfm.h104
-rw-r--r--include/linux/seqlock.h4
-rw-r--r--include/linux/signal.h4
-rw-r--r--include/linux/skbuff.h7
-rw-r--r--include/linux/string.h17
-rw-r--r--include/linux/sunrpc/metrics.h12
-rw-r--r--include/linux/sunrpc/svc.h9
-rw-r--r--include/linux/sunrpc/xprt.h1
-rw-r--r--include/linux/swap.h1
-rw-r--r--include/linux/syscalls.h14
-rw-r--r--include/linux/sysfs.h6
-rw-r--r--include/linux/tty_flip.h25
-rw-r--r--include/linux/usb/net2280.h444
-rw-r--r--include/linux/vermagic.h7
-rw-r--r--include/linux/videodev2.h65
-rw-r--r--include/linux/wanpipe.h483
-rw-r--r--include/media/cx25840.h64
-rw-r--r--include/media/msp3400.h60
-rw-r--r--include/media/saa7115.h37
-rw-r--r--include/media/saa7127.h41
-rw-r--r--include/media/upd64031a.h40
-rw-r--r--include/media/upd64083.h58
-rw-r--r--include/net/arp.h2
-rw-r--r--include/net/ieee80211softmac.h8
-rw-r--r--include/net/inet6_hashtables.h70
-rw-r--r--include/net/ip.h1
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/sock.h1
-rw-r--r--include/net/x25device.h1
-rw-r--r--include/net/xfrm.h27
-rw-r--r--include/pcmcia/bulkmem.h4
-rw-r--r--include/pcmcia/ciscode.h5
-rw-r--r--include/pcmcia/cistpl.h21
-rw-r--r--include/pcmcia/cs.h34
-rw-r--r--include/pcmcia/ds.h80
-rw-r--r--include/pcmcia/ss.h11
-rw-r--r--include/rdma/ib_sa.h28
-rw-r--r--include/rdma/ib_verbs.h28
-rw-r--r--include/scsi/scsi_devinfo.h1
-rw-r--r--include/scsi/scsi_host.h1
-rw-r--r--include/scsi/scsi_ioctl.h2
-rw-r--r--include/scsi/scsi_transport.h5
-rw-r--r--include/scsi/scsi_transport_fc.h41
-rw-r--r--include/sound/core.h4
-rw-r--r--include/sound/pcm.h18
-rw-r--r--include/sound/pcm_oss.h3
-rw-r--r--ipc/shm.c17
-rw-r--r--ipc/util.c9
-rw-r--r--kernel/exit.c6
-rw-r--r--kernel/fork.c9
-rw-r--r--kernel/hrtimer.c5
-rw-r--r--kernel/irq/Makefile3
-rw-r--r--kernel/irq/manage.c6
-rw-r--r--kernel/irq/migration.c5
-rw-r--r--kernel/kprobes.c3
-rw-r--r--kernel/panic.c1
-rw-r--r--kernel/power/Kconfig2
-rw-r--r--kernel/power/main.c2
-rw-r--r--kernel/power/pm.c20
-rw-r--r--kernel/power/snapshot.c9
-rw-r--r--kernel/printk.c6
-rw-r--r--kernel/profile.c2
-rw-r--r--kernel/ptrace.c10
-rw-r--r--kernel/rcupdate.c4
-rw-r--r--kernel/sched.c64
-rw-r--r--kernel/signal.c11
-rw-r--r--kernel/softirq.c4
-rw-r--r--kernel/softlockup.c4
-rw-r--r--kernel/sys_ni.c12
-rw-r--r--kernel/time.c8
-rw-r--r--kernel/timer.c38
-rw-r--r--kernel/uid16.c59
-rw-r--r--kernel/workqueue.c2
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--lib/kobject.c8
-rw-r--r--lib/kobject_uevent.c8
-rw-r--r--lib/string.c5
-rw-r--r--mm/bootmem.c9
-rw-r--r--mm/filemap.c32
-rw-r--r--mm/highmem.c15
-rw-r--r--mm/madvise.c3
-rw-r--r--mm/mempolicy.c1
-rw-r--r--mm/migrate.c8
-rw-r--r--mm/mmap.c43
-rw-r--r--mm/nommu.c18
-rw-r--r--mm/oom_kill.c71
-rw-r--r--mm/page-writeback.c7
-rw-r--r--mm/page_alloc.c82
-rw-r--r--mm/shmem.c3
-rw-r--r--mm/slab.c53
-rw-r--r--mm/slob.c10
-rw-r--r--mm/swap_state.c3
-rw-r--r--mm/vmalloc.c3
-rw-r--r--mm/vmscan.c2
-rw-r--r--net/atm/clip.c460
-rw-r--r--net/bluetooth/sco.c2
-rw-r--r--net/bridge/br_forward.c8
-rw-r--r--net/bridge/br_input.c3
-rw-r--r--net/bridge/br_netfilter.c13
-rw-r--r--net/bridge/netfilter/ebtables.c38
-rw-r--r--net/compat.c3
-rw-r--r--net/core/dev.c10
-rw-r--r--net/core/dv.c5
-rw-r--r--net/core/filter.c5
-rw-r--r--net/core/flow.c8
-rw-r--r--net/core/gen_estimator.c3
-rw-r--r--net/core/neighbour.c16
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/request_sock.c4
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/core/stream.c1
-rw-r--r--net/core/utils.c4
-rw-r--r--net/core/wireless.c8
-rw-r--r--net/dccp/ipv4.c2
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c25
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c40
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c18
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c37
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/arp.c4
-rw-r--r--net/ipv4/devinet.c1
-rw-r--r--net/ipv4/esp4.c5
-rw-r--r--net/ipv4/fib_frontend.c1
-rw-r--r--net/ipv4/fib_trie.c14
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/inet_hashtables.c4
-rw-r--r--net/ipv4/ip_fragment.c15
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_output.c8
-rw-r--r--net/ipv4/ipcomp.c16
-rw-r--r--net/ipv4/ipip.c4
-rw-r--r--net/ipv4/netfilter.c50
-rw-r--r--net/ipv4/netfilter/Kconfig21
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/arp_tables.c4
-rw-r--r--net/ipv4/netfilter/arptable_filter.c19
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c66
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c268
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c71
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c159
-rw-r--r--net/ipv4/netfilter/ip_queue.c31
-rw-r--r--net/ipv4/netfilter/ip_tables.c1142
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c40
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c9
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c195
-rw-r--r--net/ipv4/netfilter/iptable_filter.c21
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c33
-rw-r--r--net/ipv4/netfilter/iptable_raw.c35
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c223
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c20
-rw-r--r--net/ipv4/proc.c4
-rw-r--r--net/ipv4/route.c7
-rw-r--r--net/ipv4/tcp_input.c1
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_output.c11
-rw-r--r--net/ipv4/tunnel4.c8
-rw-r--r--net/ipv4/xfrm4_input.c17
-rw-r--r--net/ipv4/xfrm4_tunnel.c2
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/exthdrs.c16
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/inet6_hashtables.c80
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/ipcomp6.c10
-rw-r--r--net/ipv6/netfilter.c52
-rw-r--r--net/ipv6/netfilter/Kconfig16
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c31
-rw-r--r--net/ipv6/netfilter/ip6_tables.c17
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c115
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c125
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c21
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c33
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c15
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c179
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c12
-rw-r--r--net/ipv6/proc.c4
-rw-r--r--net/ipv6/reassembly.c18
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/tunnel6.c8
-rw-r--r--net/ipv6/xfrm6_input.c11
-rw-r--r--net/ipv6/xfrm6_policy.c8
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/llc/llc_input.c3
-rw-r--r--net/netfilter/Kconfig19
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/core.c51
-rw-r--r--net/netfilter/nf_conntrack_core.c17
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c6
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c50
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c50
-rw-r--r--net/netfilter/nf_conntrack_standalone.c115
-rw-r--r--net/netfilter/nf_queue.c49
-rw-r--r--net/netfilter/nfnetlink_log.c25
-rw-r--r--net/netfilter/nfnetlink_queue.c27
-rw-r--r--net/netfilter/x_tables.c119
-rw-r--r--net/netfilter/xt_esp.c (renamed from net/ipv4/netfilter/ipt_esp.c)81
-rw-r--r--net/netfilter/xt_multiport.c314
-rw-r--r--net/netfilter/xt_policy.c2
-rw-r--r--net/sched/act_ipt.c5
-rw-r--r--net/sched/act_police.c8
-rw-r--r--net/sctp/proc.c2
-rw-r--r--net/socket.c14
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c11
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c14
-rw-r--r--net/sunrpc/stats.c3
-rw-r--r--net/tipc/name_distr.c3
-rw-r--r--net/wanrouter/af_wanpipe.c2
-rw-r--r--net/xfrm/xfrm_input.c4
-rw-r--r--net/xfrm/xfrm_policy.c10
-rw-r--r--net/xfrm/xfrm_state.c25
-rw-r--r--scripts/Kbuild.include5
-rw-r--r--scripts/Makefile.lib5
-rwxr-xr-x[-rw-r--r--]scripts/bloat-o-meter0
-rwxr-xr-x[-rw-r--r--]scripts/checkstack.pl0
-rw-r--r--scripts/gen_initramfs_list.sh225
-rw-r--r--scripts/kconfig/conf.c24
-rw-r--r--scripts/kconfig/confdata.c2
-rw-r--r--scripts/kconfig/lxdialog/checklist.c19
-rw-r--r--scripts/kconfig/lxdialog/menubox.c19
-rw-r--r--scripts/mod/modpost.c15
-rwxr-xr-x[-rw-r--r--]scripts/namespace.pl0
-rwxr-xr-x[-rw-r--r--]scripts/show_delta0
-rwxr-xr-xscripts/ver_linux4
-rw-r--r--security/keys/key.c4
-rw-r--r--security/keys/keyring.c1
-rw-r--r--security/keys/process_keys.c41
-rw-r--r--security/selinux/ss/mls.c2
-rw-r--r--security/selinux/xfrm.c4
-rw-r--r--sound/core/Kconfig5
-rw-r--r--sound/core/control.c6
-rw-r--r--sound/core/control_compat.c6
-rw-r--r--sound/core/init.c9
-rw-r--r--sound/core/oss/pcm_oss.c289
-rw-r--r--sound/core/pcm.c16
-rw-r--r--sound/core/pcm_lib.c49
-rw-r--r--sound/core/pcm_native.c159
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c42
-rw-r--r--sound/isa/Kconfig23
-rw-r--r--sound/isa/Makefile2
-rw-r--r--sound/isa/ad1848/ad1848.c16
-rw-r--r--sound/isa/adlib.c164
-rw-r--r--sound/isa/cmi8330.c20
-rw-r--r--sound/isa/cs423x/cs4231.c16
-rw-r--r--sound/isa/cs423x/cs4236.c16
-rw-r--r--sound/isa/es1688/es1688.c16
-rw-r--r--sound/isa/es18xx.c16
-rw-r--r--sound/isa/gus/gusclassic.c16
-rw-r--r--sound/isa/gus/gusextreme.c16
-rw-r--r--sound/isa/gus/gusmax.c16
-rw-r--r--sound/isa/gus/interwave.c16
-rw-r--r--sound/isa/opl3sa2.c16
-rw-r--r--sound/isa/opti9xx/Makefile2
-rw-r--r--sound/isa/opti9xx/miro.c1458
-rw-r--r--sound/isa/opti9xx/miro.h73
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c7
-rw-r--r--sound/isa/sb/sb16.c16
-rw-r--r--sound/isa/sb/sb8.c16
-rw-r--r--sound/isa/sgalaxy.c16
-rw-r--r--sound/isa/sscape.c16
-rw-r--r--sound/isa/wavefront/wavefront.c16
-rw-r--r--sound/oss/Kconfig306
-rw-r--r--sound/oss/ad1889.c198
-rw-r--r--sound/oss/ad1889.h101
-rw-r--r--sound/oss/dmasound/tas_common.c4
-rw-r--r--sound/oss/emu10k1/main.c3
-rw-r--r--sound/pci/Kconfig30
-rw-r--r--sound/pci/Makefile3
-rw-r--r--sound/pci/ac97/ac97_codec.c1
-rw-r--r--sound/pci/als300.c867
-rw-r--r--sound/pci/au88x0/au88x0.h13
-rw-r--r--sound/pci/au88x0/au88x0_core.c2
-rw-r--r--sound/pci/au88x0/au88x0_eq.c2
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c2
-rw-r--r--sound/pci/cs4281.c28
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c5
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_intel.c2
-rw-r--r--sound/pci/hda/patch_analog.c15
-rw-r--r--sound/pci/hda/patch_realtek.c298
-rw-r--r--sound/pci/hda/patch_sigmatel.c56
-rw-r--r--sound/pci/ice1712/aureon.c163
-rw-r--r--sound/pci/ice1712/ice1712.c2
-rw-r--r--sound/pci/ice1712/ice1712.h1
-rw-r--r--sound/pci/maestro3.c57
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c9
-rw-r--r--sound/pci/riptide/Makefile3
-rw-r--r--sound/pci/riptide/riptide.c2223
-rw-r--r--sound/pci/via82xx.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c86
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h2
-rw-r--r--sound/pcmcia/vx/vxpocket.c94
-rw-r--r--sound/pcmcia/vx/vxpocket.h2
-rw-r--r--sound/ppc/daca.c2
-rw-r--r--sound/ppc/tumbler.c2
-rw-r--r--sound/usb/usbmixer.c37
-rw-r--r--usr/Makefile91
-rw-r--r--usr/gen_init_cpio.c4
1793 files changed, 77440 insertions, 68681 deletions
diff --git a/CREDITS b/CREDITS
index 0bf31eac6dc2..787564bc248b 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3382,7 +3382,7 @@ S: Germany
N: Geert Uytterhoeven
E: geert@linux-m68k.org
-W: http://home.tvd.be/cr26864/
+W: http://users.telenet.be/geertu/
P: 1024/862678A6 C51D 361C 0BD1 4C90 B275 C553 6EEA 11BA 8626 78A6
D: m68k/Amiga and PPC/CHRP Longtrail coordinator
D: Frame buffer device and XF68_FBDev maintainer
@@ -3392,8 +3392,8 @@ D: Amiga Buddha and Catweasel chipset IDE
D: Atari Falcon chipset IDE
D: Amiga Gayle chipset IDE
D: mipsel NEC DDB Vrc-5074
-S: Emiel Vlieberghlaan 2A/21
-S: B-3010 Kessel-Lo
+S: Haterbeekstraat 55B
+S: B-3200 Aarschot
S: Belgium
N: Chris Vance
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 1af0f2d50220..2ffb0d62f0fe 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -33,7 +33,9 @@ pci_alloc_consistent(struct pci_dev *dev, size_t size,
Consistent memory is memory for which a write by either the device or
the processor can immediately be read by the processor or device
-without having to worry about caching effects.
+without having to worry about caching effects. (You may however need
+to make sure to flush the processor's write buffers before telling
+devices to read that memory.)
This routine allocates a region of <size> bytes of consistent memory.
it also returns a <dma_handle> which may be cast to an unsigned
@@ -304,12 +306,12 @@ dma address with dma_mapping_error(). A non zero return value means the mapping
could not be created and the driver should take appropriate action (eg
reduce current DMA mapping usage or delay and try again later).
-int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
-int
-pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
+ int
+ dma_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+ int
+ pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+ int nents, int direction)
Maps a scatter gather list from the block layer.
@@ -327,12 +329,33 @@ critical that the driver do something, in the case of a block driver
aborting the request or even oopsing is better than doing nothing and
corrupting the filesystem.
-void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-void
-pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
+With scatterlists, you use the resulting mapping like this:
+
+ int i, count = dma_map_sg(dev, sglist, nents, direction);
+ struct scatterlist *sg;
+
+ for (i = 0, sg = sglist; i < count; i++, sg++) {
+ hw_address[i] = sg_dma_address(sg);
+ hw_len[i] = sg_dma_len(sg);
+ }
+
+where nents is the number of entries in the sglist.
+
+The implementation is free to merge several consecutive sglist entries
+into one (e.g. with an IOMMU, or if several pages just happen to be
+physically contiguous) and returns the actual number of sg entries it
+mapped them to. On failure 0, is returned.
+
+Then you should loop count times (note: this can be less than nents times)
+and use sg_dma_address() and sg_dma_len() macros where you previously
+accessed sg->address and sg->length as shown above.
+
+ void
+ dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nhwentries, enum dma_data_direction direction)
+ void
+ pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+ int nents, int direction)
unmap the previously mapped scatter/gather list. All the parameters
must be the same as those and passed in to the scatter/gather mapping
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index ee4bb73683cd..7c717699032c 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -58,11 +58,15 @@ translating each of those pages back to a kernel address using
something like __va(). [ EDIT: Update this when we integrate
Gerd Knorr's generic code which does this. ]
-This rule also means that you may not use kernel image addresses
-(ie. items in the kernel's data/text/bss segment, or your driver's)
-nor may you use kernel stack addresses for DMA. Both of these items
-might be mapped somewhere entirely different than the rest of physical
-memory.
+This rule also means that you may use neither kernel image addresses
+(items in data/text/bss segments), nor module image addresses, nor
+stack addresses for DMA. These could all be mapped somewhere entirely
+different than the rest of physical memory. Even if those classes of
+memory could physically work with DMA, you'd need to ensure the I/O
+buffers were cacheline-aligned. Without that, you'd see cacheline
+sharing problems (data corruption) on CPUs with DMA-incoherent caches.
+(The CPU could write to one word, DMA would write to a different one
+in the same cache line, and one of them could be overwritten.)
Also, this means that you cannot take the return of a kmap()
call and DMA to/from that. This is similar to vmalloc().
@@ -194,7 +198,7 @@ document for how to handle this case.
Finally, if your device can only drive the low 24-bits of
address during PCI bus mastering you might do something like:
- if (pci_set_dma_mask(pdev, 0x00ffffff)) {
+ if (pci_set_dma_mask(pdev, DMA_24BIT_MASK)) {
printk(KERN_WARNING
"mydev: 24-bit DMA addressing not available.\n");
goto ignore_this_device;
@@ -212,7 +216,7 @@ functions (for example a sound card provides playback and record
functions) and the various different functions have _different_
DMA addressing limitations, you may wish to probe each mask and
only provide the functionality which the machine can handle. It
-is important that the last call to pci_set_dma_mask() be for the
+is important that the last call to pci_set_dma_mask() be for the
most specific mask.
Here is pseudo-code showing how this might be done:
@@ -284,6 +288,11 @@ There are two types of DMA mappings:
in order to get correct behavior on all platforms.
+ Also, on some platforms your driver may need to flush CPU write
+ buffers in much the same way as it needs to flush write buffers
+ found in PCI bridges (such as by reading a register's value
+ after writing it).
+
- Streaming DMA mappings which are usually mapped for one DMA transfer,
unmapped right after it (unless you use pci_dma_sync_* below) and for which
hardware can optimize for sequential accesses.
@@ -303,6 +312,9 @@ There are two types of DMA mappings:
Neither type of DMA mapping has alignment restrictions that come
from PCI, although some devices may have such restrictions.
+Also, systems with caches that aren't DMA-coherent will work better
+when the underlying buffers don't share cache lines with other data.
+
Using Consistent DMA mappings.
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 7d87dd73cbe4..5a2882d275ba 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -2,7 +2,7 @@
# This makefile is used to generate the kernel documentation,
# primarily based on in-line comments in various source files.
# See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
-# to ducument the SRC - and how to read it.
+# to document the SRC - and how to read it.
# To add a new book the only step required is to add the book to the
# list of DOCBOOKS.
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 8c9c6704e85b..ca02e04a906c 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -322,7 +322,6 @@ X!Earch/i386/kernel/mca.c
<chapter id="sysfs">
<title>The Filesystem for Exporting Kernel Objects</title>
!Efs/sysfs/file.c
-!Efs/sysfs/dir.c
!Efs/sysfs/symlink.c
!Efs/sysfs/bin.c
</chapter>
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 5bcbb6ee3bc0..f869b03929db 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -705,7 +705,7 @@ and other resources, etc.
<sect1><title>ata_scsi_error()</title>
<para>
- ata_scsi_error() is the current hostt->eh_strategy_handler()
+ ata_scsi_error() is the current transportt->eh_strategy_handler()
for libata. As discussed above, this will be entered in two
cases - timeout and ATAPI error completion. This function
calls low level libata driver's eng_timeout() callback, the
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 6c9e746267da..915ae8c986c6 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -603,7 +603,8 @@ start exactly where you are now.
----------
-Thanks to Paolo Ciarrocchi who allowed the "Development Process" section
+Thanks to Paolo Ciarrocchi who allowed the "Development Process"
+(http://linux.tar.bz/articles/2.6-development_process) section
to be based on text he had written, and to Randy Dunlap and Gerrit
Huizenga for some of the list of things you should and should not say.
Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
index 744f1aec6553..38040fa37649 100644
--- a/Documentation/acpi-hotkey.txt
+++ b/Documentation/acpi-hotkey.txt
@@ -30,7 +30,7 @@ specific hotkey(event))
echo "event_num:event_type:event_argument" >
/proc/acpi/hotkey/action.
The result of the execution of this aml method is
-attached to /proc/acpi/hotkey/poll_method, which is dnyamically
+attached to /proc/acpi/hotkey/poll_method, which is dynamically
created. Please use command "cat /proc/acpi/hotkey/polling_method"
to retrieve it.
diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
new file mode 100644
index 000000000000..5fa130a67531
--- /dev/null
+++ b/Documentation/block/switching-sched.txt
@@ -0,0 +1,22 @@
+As of the Linux 2.6.10 kernel, it is now possible to change the
+IO scheduler for a given block device on the fly (thus making it possible,
+for instance, to set the CFQ scheduler for the system default, but
+set a specific device to use the anticipatory or noop schedulers - which
+can improve that device's throughput).
+
+To set a specific scheduler, simply do this:
+
+echo SCHEDNAME > /sys/block/DEV/queue/scheduler
+
+where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
+device name (hda, hdb, sga, or whatever you happen to have).
+
+The list of defined schedulers can be found by simply doing
+a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
+will be displayed, with the currently selected scheduler in brackets:
+
+# cat /sys/block/hda/queue/scheduler
+noop anticipatory deadline [cfq]
+# echo anticipatory > /sys/block/hda/queue/scheduler
+# cat /sys/block/hda/queue/scheduler
+noop [anticipatory] deadline cfq
diff --git a/Documentation/cpu-freq/index.txt b/Documentation/cpu-freq/index.txt
index 5009805f9378..ffdb5323df37 100644
--- a/Documentation/cpu-freq/index.txt
+++ b/Documentation/cpu-freq/index.txt
@@ -53,4 +53,4 @@ the CPUFreq Mailing list:
* http://lists.linux.org.uk/mailman/listinfo/cpufreq
Clock and voltage scaling for the SA-1100:
-* http://www.lart.tudelft.nl/projects/scaling
+* http://www.lartmaker.nl/projects/scaling
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 59d0c74c79c9..421bcfff6ad2 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -25,8 +25,9 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: drivers depending on OBSOLETE_OSS_DRIVER
-When: January 2006
+What: drivers that were depending on OBSOLETE_OSS_DRIVER
+ (config options already removed)
+When: before 2.6.19
Why: OSS drivers with ALSA replacements
Who: Adrian Bunk <bunk@stusta.de>
@@ -71,14 +72,6 @@ Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
---------------------------
-What: remove EXPORT_SYMBOL(panic_timeout)
-When: April 2006
-Files: kernel/panic.c
-Why: No modular usage in the kernel.
-Who: Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
What: remove EXPORT_SYMBOL(insert_resource)
When: April 2006
Files: kernel/resource.c
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index c8bce82ddcac..89b1d196ca80 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -246,6 +246,7 @@ class/
devices/
firmware/
net/
+fs/
devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
@@ -264,6 +265,10 @@ drivers/ contains a directory for each device driver that is loaded
for devices on that particular bus (this assumes that drivers do not
span multiple bus types).
+fs/ contains a directory for some filesystems. Currently each
+filesystem wanting to export attributes must create its own hierarchy
+below fs/ (see ./fuse.txt for an example).
+
More information can driver-model specific features can be found in
Documentation/driver-model/.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index adaa899e5c90..3a2e5520c1e3 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -694,7 +694,7 @@ struct file_operations
----------------------
This describes how the VFS can manipulate an open file. As of kernel
-2.6.13, the following members are defined:
+2.6.17, the following members are defined:
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
@@ -723,6 +723,10 @@ struct file_operations {
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned
+int);
+ ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned
+int);
};
Again, all methods are called without any locks being held, unless
@@ -790,6 +794,12 @@ otherwise noted.
flock: called by the flock(2) system call
+ splice_write: called by the VFS to splice data from a pipe to a file. This
+ method is used by the splice(2) system call
+
+ splice_read: called by the VFS to splice data from file to a pipe. This
+ method is used by the splice(2) system call
+
Note that the file operations are implemented by the specific
filesystem in which the inode resides. When opening a device node
(character or block special) most filesystems will call special
diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt
index 0ed9b0a779bc..8b0a5fc8bfd9 100644
--- a/Documentation/fujitsu/frv/kernel-ABI.txt
+++ b/Documentation/fujitsu/frv/kernel-ABI.txt
@@ -1,17 +1,19 @@
- =================================
- INTERNAL KERNEL ABI FOR FR-V ARCH
- =================================
-
-The internal FRV kernel ABI is not quite the same as the userspace ABI. A number of the registers
-are used for special purposed, and the ABI is not consistent between modules vs core, and MMU vs
-no-MMU.
-
-This partly stems from the fact that FRV CPUs do not have a separate supervisor stack pointer, and
-most of them do not have any scratch registers, thus requiring at least one general purpose
-register to be clobbered in such an event. Also, within the kernel core, it is possible to simply
-jump or call directly between functions using a relative offset. This cannot be extended to modules
-for the displacement is likely to be too far. Thus in modules the address of a function to call
-must be calculated in a register and then used, requiring two extra instructions.
+ =================================
+ INTERNAL KERNEL ABI FOR FR-V ARCH
+ =================================
+
+The internal FRV kernel ABI is not quite the same as the userspace ABI. A
+number of the registers are used for special purposed, and the ABI is not
+consistent between modules vs core, and MMU vs no-MMU.
+
+This partly stems from the fact that FRV CPUs do not have a separate
+supervisor stack pointer, and most of them do not have any scratch
+registers, thus requiring at least one general purpose register to be
+clobbered in such an event. Also, within the kernel core, it is possible to
+simply jump or call directly between functions using a relative offset.
+This cannot be extended to modules for the displacement is likely to be too
+far. Thus in modules the address of a function to call must be calculated
+in a register and then used, requiring two extra instructions.
This document has the following sections:
@@ -39,7 +41,8 @@ When a system call is made, the following registers are effective:
CPU OPERATING MODES
===================
-The FR-V CPU has three basic operating modes. In order of increasing capability:
+The FR-V CPU has three basic operating modes. In order of increasing
+capability:
(1) User mode.
@@ -47,42 +50,46 @@ The FR-V CPU has three basic operating modes. In order of increasing capability:
(2) Kernel mode.
- Normal kernel mode. There are many additional control registers available that may be
- accessed in this mode, in addition to all the stuff available to user mode. This has two
- submodes:
+ Normal kernel mode. There are many additional control registers
+ available that may be accessed in this mode, in addition to all the
+ stuff available to user mode. This has two submodes:
(a) Exceptions enabled (PSR.T == 1).
- Exceptions will invoke the appropriate normal kernel mode handler. On entry to the
- handler, the PSR.T bit will be cleared.
+ Exceptions will invoke the appropriate normal kernel mode
+ handler. On entry to the handler, the PSR.T bit will be cleared.
(b) Exceptions disabled (PSR.T == 0).
- No exceptions or interrupts may happen. Any mandatory exceptions will cause the CPU to
- halt unless the CPU is told to jump into debug mode instead.
+ No exceptions or interrupts may happen. Any mandatory exceptions
+ will cause the CPU to halt unless the CPU is told to jump into
+ debug mode instead.
(3) Debug mode.
- No exceptions may happen in this mode. Memory protection and management exceptions will be
- flagged for later consideration, but the exception handler won't be invoked. Debugging traps
- such as hardware breakpoints and watchpoints will be ignored. This mode is entered only by
- debugging events obtained from the other two modes.
+ No exceptions may happen in this mode. Memory protection and
+ management exceptions will be flagged for later consideration, but
+ the exception handler won't be invoked. Debugging traps such as
+ hardware breakpoints and watchpoints will be ignored. This mode is
+ entered only by debugging events obtained from the other two modes.
- All kernel mode registers may be accessed, plus a few extra debugging specific registers.
+ All kernel mode registers may be accessed, plus a few extra debugging
+ specific registers.
=================================
INTERNAL KERNEL-MODE REGISTER ABI
=================================
-There are a number of permanent register assignments that are set up by entry.S in the exception
-prologue. Note that there is a complete set of exception prologues for each of user->kernel
-transition and kernel->kernel transition. There are also user->debug and kernel->debug mode
-transition prologues.
+There are a number of permanent register assignments that are set up by
+entry.S in the exception prologue. Note that there is a complete set of
+exception prologues for each of user->kernel transition and kernel->kernel
+transition. There are also user->debug and kernel->debug mode transition
+prologues.
REGISTER FLAVOUR USE
- =============== ======= ====================================================
+ =============== ======= ==============================================
GR1 Supervisor stack pointer
GR15 Current thread info pointer
GR16 GP-Rel base register for small data
@@ -92,10 +99,12 @@ transition prologues.
GR31 NOMMU Destroyed by debug mode entry
GR31 MMU Destroyed by TLB miss kernel mode entry
CCR.ICC2 Virtual interrupt disablement tracking
- CCCR.CC3 Cleared by exception prologue (atomic op emulation)
+ CCCR.CC3 Cleared by exception prologue
+ (atomic op emulation)
SCR0 MMU See mmu-layout.txt.
SCR1 MMU See mmu-layout.txt.
- SCR2 MMU Save for EAR0 (destroyed by icache insns in debug mode)
+ SCR2 MMU Save for EAR0 (destroyed by icache insns
+ in debug mode)
SCR3 MMU Save for GR31 during debug exceptions
DAMR/IAMR NOMMU Fixed memory protection layout.
DAMR/IAMR MMU See mmu-layout.txt.
@@ -104,18 +113,21 @@ transition prologues.
Certain registers are also used or modified across function calls:
REGISTER CALL RETURN
- =============== =============================== ===============================
+ =============== =============================== ======================
GR0 Fixed Zero -
GR2 Function call frame pointer
GR3 Special Preserved
GR3-GR7 - Clobbered
- GR8 Function call arg #1 Return value (or clobbered)
- GR9 Function call arg #2 Return value MSW (or clobbered)
+ GR8 Function call arg #1 Return value
+ (or clobbered)
+ GR9 Function call arg #2 Return value MSW
+ (or clobbered)
GR10-GR13 Function call arg #3-#6 Clobbered
GR14 - Clobbered
GR15-GR16 Special Preserved
GR17-GR27 - Preserved
- GR28-GR31 Special Only accessed explicitly
+ GR28-GR31 Special Only accessed
+ explicitly
LR Return address after CALL Clobbered
CCR/CCCR - Mostly Clobbered
@@ -124,46 +136,53 @@ Certain registers are also used or modified across function calls:
INTERNAL DEBUG-MODE REGISTER ABI
================================
-This is the same as the kernel-mode register ABI for functions calls. The difference is that in
-debug-mode there's a different stack and a different exception frame. Almost all the global
-registers from kernel-mode (including the stack pointer) may be changed.
+This is the same as the kernel-mode register ABI for functions calls. The
+difference is that in debug-mode there's a different stack and a different
+exception frame. Almost all the global registers from kernel-mode
+(including the stack pointer) may be changed.
REGISTER FLAVOUR USE
- =============== ======= ====================================================
+ =============== ======= ==============================================
GR1 Debug stack pointer
GR16 GP-Rel base register for small data
- GR31 Current debug exception frame pointer (__debug_frame)
+ GR31 Current debug exception frame pointer
+ (__debug_frame)
SCR3 MMU Saved value of GR31
-Note that debug mode is able to interfere with the kernel's emulated atomic ops, so it must be
-exceedingly careful not to do any that would interact with the main kernel in this regard. Hence
-the debug mode code (gdbstub) is almost completely self-contained. The only external code used is
-the sprintf family of functions.
+Note that debug mode is able to interfere with the kernel's emulated atomic
+ops, so it must be exceedingly careful not to do any that would interact
+with the main kernel in this regard. Hence the debug mode code (gdbstub) is
+almost completely self-contained. The only external code used is the
+sprintf family of functions.
-Futhermore, break.S is so complicated because single-step mode does not switch off on entry to an
-exception. That means unless manually disabled, single-stepping will blithely go on stepping into
-things like interrupts. See gdbstub.txt for more information.
+Futhermore, break.S is so complicated because single-step mode does not
+switch off on entry to an exception. That means unless manually disabled,
+single-stepping will blithely go on stepping into things like interrupts.
+See gdbstub.txt for more information.
==========================
VIRTUAL INTERRUPT HANDLING
==========================
-Because accesses to the PSR is so slow, and to disable interrupts we have to access it twice (once
-to read and once to write), we don't actually disable interrupts at all if we don't have to. What
-we do instead is use the ICC2 condition code flags to note virtual disablement, such that if we
-then do take an interrupt, we note the flag, really disable interrupts, set another flag and resume
-execution at the point the interrupt happened. Setting condition flags as a side effect of an
-arithmetic or logical instruction is really fast. This use of the ICC2 only occurs within the
+Because accesses to the PSR is so slow, and to disable interrupts we have
+to access it twice (once to read and once to write), we don't actually
+disable interrupts at all if we don't have to. What we do instead is use
+the ICC2 condition code flags to note virtual disablement, such that if we
+then do take an interrupt, we note the flag, really disable interrupts, set
+another flag and resume execution at the point the interrupt happened.
+Setting condition flags as a side effect of an arithmetic or logical
+instruction is really fast. This use of the ICC2 only occurs within the
kernel - it does not affect userspace.
The flags we use are:
(*) CCR.ICC2.Z [Zero flag]
- Set to virtually disable interrupts, clear when interrupts are virtually enabled. Can be
- modified by logical instructions without affecting the Carry flag.
+ Set to virtually disable interrupts, clear when interrupts are
+ virtually enabled. Can be modified by logical instructions without
+ affecting the Carry flag.
(*) CCR.ICC2.C [Carry flag]
@@ -176,8 +195,9 @@ What happens is this:
ICC2.Z is 0, ICC2.C is 1.
- (2) An interrupt occurs. The exception prologue examines ICC2.Z and determines that nothing needs
- doing. This is done simply with an unlikely BEQ instruction.
+ (2) An interrupt occurs. The exception prologue examines ICC2.Z and
+ determines that nothing needs doing. This is done simply with an
+ unlikely BEQ instruction.
(3) The interrupts are disabled (local_irq_disable)
@@ -187,48 +207,56 @@ What happens is this:
ICC2.Z would be set to 0.
- A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would be used to trap if
- interrupts were now virtually enabled, but physically disabled - which they're not, so the
- trap isn't taken. The kernel would then be back to state (1).
+ A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
+ be used to trap if interrupts were now virtually enabled, but
+ physically disabled - which they're not, so the trap isn't taken. The
+ kernel would then be back to state (1).
- (5) An interrupt occurs. The exception prologue examines ICC2.Z and determines that the interrupt
- shouldn't actually have happened. It jumps aside, and there disabled interrupts by setting
- PSR.PIL to 14 and then it clears ICC2.C.
+ (5) An interrupt occurs. The exception prologue examines ICC2.Z and
+ determines that the interrupt shouldn't actually have happened. It
+ jumps aside, and there disabled interrupts by setting PSR.PIL to 14
+ and then it clears ICC2.C.
(6) If interrupts were then saved and disabled again (local_irq_save):
- ICC2.Z would be shifted into the save variable and masked off (giving a 1).
+ ICC2.Z would be shifted into the save variable and masked off
+ (giving a 1).
- ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be unaffected (ie: 0).
+ ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
+ unaffected (ie: 0).
(7) If interrupts were then restored from state (6) (local_irq_restore):
- ICC2.Z would be set to indicate the result of XOR'ing the saved value (ie: 1) with 1, which
- gives a result of 0 - thus leaving ICC2.Z set.
+ ICC2.Z would be set to indicate the result of XOR'ing the saved
+ value (ie: 1) with 1, which gives a result of 0 - thus leaving
+ ICC2.Z set.
ICC2.C would remain unaffected (ie: 0).
- A TIHI #2 instruction would be used to again assay the current state, but this would do
- nothing as Z==1.
+ A TIHI #2 instruction would be used to again assay the current state,
+ but this would do nothing as Z==1.
(8) If interrupts were then enabled (local_irq_enable):
- ICC2.Z would be cleared. ICC2.C would be left unaffected. Both flags would now be 0.
+ ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
+ flags would now be 0.
- A TIHI #2 instruction again issued to assay the current state would then trap as both Z==0
- [interrupts virtually enabled] and C==0 [interrupts really disabled] would then be true.
+ A TIHI #2 instruction again issued to assay the current state would
+ then trap as both Z==0 [interrupts virtually enabled] and C==0
+ [interrupts really disabled] would then be true.
- (9) The trap #2 handler would simply enable hardware interrupts (set PSR.PIL to 0), set ICC2.C to
- 1 and return.
+ (9) The trap #2 handler would simply enable hardware interrupts
+ (set PSR.PIL to 0), set ICC2.C to 1 and return.
(10) Immediately upon returning, the pending interrupt would be taken.
-(11) The interrupt handler would take the path of actually processing the interrupt (ICC2.Z is
- clear, BEQ fails as per step (2)).
+(11) The interrupt handler would take the path of actually processing the
+ interrupt (ICC2.Z is clear, BEQ fails as per step (2)).
-(12) The interrupt handler would then set ICC2.C to 1 since hardware interrupts are definitely
- enabled - or else the kernel wouldn't be here.
+(12) The interrupt handler would then set ICC2.C to 1 since hardware
+ interrupts are definitely enabled - or else the kernel wouldn't be here.
(13) On return from the interrupt handler, things would be back to state (1).
-This trap (#2) is only available in kernel mode. In user mode it will result in SIGILL.
+This trap (#2) is only available in kernel mode. In user mode it will
+result in SIGILL.
diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport
index d9f23c0763f1..77b995dfca22 100644
--- a/Documentation/i2c/busses/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -12,18 +12,22 @@ meant as a replacement for the older, individual drivers:
teletext adapters)
It currently supports the following devices:
- * Philips adapter
- * home brew teletext adapter
- * Velleman K8000 adapter
- * ELV adapter
- * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032)
- * Barco LPT->DVI (K5800236) adapter
+ * (type=0) Philips adapter
+ * (type=1) home brew teletext adapter
+ * (type=2) Velleman K8000 adapter
+ * (type=3) ELV adapter
+ * (type=4) Analog Devices ADM1032 evaluation board
+ * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031
+ * (type=6) Barco LPT->DVI (K5800236) adapter
These devices use different pinout configurations, so you have to tell
the driver what you have, using the type module parameter. There is no
way to autodetect the devices. Support for different pinout configurations
can be easily added when needed.
+Earlier kernels defaulted to type=0 (Philips). But now, if the type
+parameter is missing, the driver will simply fail to initialize.
+
Building your own adapter
-------------------------
diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset
new file mode 100644
index 000000000000..85a64defd385
--- /dev/null
+++ b/Documentation/isdn/README.gigaset
@@ -0,0 +1,286 @@
+GigaSet 307x Device Driver
+==========================
+
+1. Requirements
+ ------------
+1.1. Hardware
+ --------
+ This release supports the connection of the Gigaset 307x/417x family of
+ ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
+ connection. The following devices are reported to be compatible:
+ 307x/417x:
+ Gigaset SX255isdn
+ Gigaset SX353isdn
+ Sinus 45 [AB] isdn (Deutsche Telekom)
+ Sinus 721X/XA
+ Vox Chicago 390 ISDN (KPN Telecom)
+ M101:
+ Sinus 45 Data 1 (Telekom)
+ M105:
+ Gigaset USB Adapter DECT
+ Sinus 45 Data 2 (Telekom)
+ Sinus 721 data
+ Chicago 390 USB (KPN)
+ See also http://www.erbze.info/sinus_gigaset.htm and
+ http://gigaset307x.sourceforge.net/
+
+ We had also reports from users of Gigaset M105 who could use the drivers
+ with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
+ If you have another device that works with our driver, please let us know.
+ For example, Gigaset SX205isdn/Sinus 721 X SE and Gigaset SX303isdn bases
+ are just versions without answering machine of models known to work, so
+ they should work just as well; but so far we are lacking positive reports
+ on these.
+
+ Chances of getting an USB device to work are good if the output of
+ lsusb
+ at the command line contains one of the following:
+ ID 0681:0001
+ ID 0681:0002
+ ID 0681:0009
+ ID 0681:0021
+ ID 0681:0022
+
+1.2. Software
+ --------
+ The driver works with ISDN4linux and so can be used with any software
+ which is able to use ISDN4linux for ISDN connections (voice or data).
+ CAPI4Linux support is planned but not yet available.
+
+ There are some user space tools available at
+ http://sourceforge.net/projects/gigaset307x/
+ which provide access to additional device specific functions like SMS,
+ phonebook or call journal.
+
+
+2. How to use the driver
+ ---------------------
+2.1. Modules
+ -------
+ To get the device working, you have to load the proper kernel module. You
+ can do this using
+ modprobe modulename
+ where modulename is usb_gigaset (M105) or bas_gigaset (direct USB
+ connection to the base).
+
+2.2. Device nodes for user space programs
+ ------------------------------------
+ The device can be accessed from user space (eg. by the user space tools
+ mentioned in 1.2.) through the device nodes:
+
+ - /dev/ttyGU0 for M105 (USB data boxes)
+ - /dev/ttyGB0 for the base driver (direct USB connection)
+
+ You can also select a "default device" which is used by the frontends when
+ no device node is given as parameter, by creating a symlink /dev/ttyG to
+ one of them, eg.:
+
+ ln -s /dev/ttyGB0 /dev/ttyG
+
+2.3. ISDN4linux
+ ----------
+ This is the "normal" mode of operation. After loading the module you can
+ set up the ISDN system just as you'd do with any ISDN card.
+ Your distribution should provide some configuration utility.
+ If not, you can use some HOWTOs like
+ http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
+ If this doesn't work, because you have some recent device like SX100 where
+ debug output (see section 3.2.) shows something like this when dialing
+ CMD Received: ERROR
+ Available Params: 0
+ Connection State: 0, Response: -1
+ gigaset_process_response: resp_code -1 in ConState 0 !
+ Timeout occurred
+ you might need to use unimodem mode:
+
+2.4. Unimodem mode
+ -------------
+ This is needed for some devices [e.g. SX100] as they have problems with
+ the "normal" commands.
+
+ If you have installed the command line tool gigacontr, you can enter
+ unimodem mode using
+ gigacontr --mode unimodem
+ You can switch back using
+ gigacontr --mode isdn
+
+ You can also load the driver using e.g.
+ modprobe usb_gigaset startmode=0
+ to prevent the driver from starting in "isdn4linux mode".
+
+ In this mode the device works like a modem connected to a serial port
+ (the /dev/ttyGU0, ... mentioned above) which understands the commands
+ ATZ init, reset
+ => OK or ERROR
+ ATD
+ ATDT dial
+ => OK, CONNECT,
+ BUSY,
+ NO DIAL TONE,
+ NO CARRIER,
+ NO ANSWER
+ <pause>+++<pause> change to command mode when connected
+ ATH hangup
+
+ You can use some configuration tool of your distribution to configure this
+ "modem" or configure pppd/wvdial manually. There are some example ppp
+ configuration files and chat scripts in the gigaset-VERSION/ppp directory.
+ Please note that the USB drivers are not able to change the state of the
+ control lines (the M105 driver can be configured to use some undocumented
+ control requests, if you really need the control lines, though). This means
+ you must use "Stupid Mode" if you are using wvdial or you should use the
+ nocrtscts option of pppd.
+ You must also assure that the ppp_async module is loaded with the parameter
+ flag_time=0. You can do this e.g. by adding a line like
+
+ options ppp_async flag_time=0
+
+ to /etc/modprobe.conf. If your distribution has some local module
+ configuration file like /etc/modprobe.conf.local,
+ using that should be preferred.
+
+2.5. Call-ID (CID) mode
+ ------------------
+ Call-IDs are numbers used to tag commands to, and responses from, the
+ Gigaset base in order to support the simultaneous handling of multiple
+ ISDN calls. Their use can be enabled ("CID mode") or disabled ("Unimodem
+ mode"). Without Call-IDs (in Unimodem mode), only a very limited set of
+ functions is available. It allows outgoing data connections only, but
+ does not signal incoming calls or other base events.
+
+ DECT cordless data devices (M10x) permanently occupy the cordless
+ connection to the base while Call-IDs are activated. As the Gigaset
+ bases only support one DECT data connection at a time, this prevents
+ other DECT cordless data devices from accessing the base.
+
+ During active operation, the driver switches to the necessary mode
+ automatically. However, for the reasons above, the mode chosen when
+ the device is not in use (idle) can be selected by the user.
+ - If you want to receive incoming calls, you can use the default
+ settings (CID mode).
+ - If you have several DECT data devices (M10x) which you want to use
+ in turn, select Unimodem mode by passing the parameter "cidmode=0" to
+ the driver ("modprobe usb_gigaset cidmode=0" or modprobe.conf).
+
+ If you want both of these at once, you are out of luck.
+
+ You can also use /sys/module/<name>/parameters/cidmode for changing
+ the CID mode setting (<name> is usb_gigaset or bas_gigaset).
+
+
+3. Troubleshooting
+ ---------------
+3.1. Solutions to frequently reported problems
+ -----------------------------------------
+ Problem:
+ You have a slow provider and isdn4linux gives up dialing too early.
+ Solution:
+ Load the isdn module using the dialtimeout option. You can do this e.g.
+ by adding a line like
+
+ options isdn dialtimeout=15
+
+ to /etc/modprobe.conf. If your distribution has some local module
+ configuration file like /etc/modprobe.conf.local,
+ using that should be preferred.
+
+ Problem:
+ Your isdn script aborts with a message about isdnlog.
+ Solution:
+ Try deactivating (or commenting out) isdnlog. This driver does not
+ support it.
+
+ Problem:
+ You have two or more DECT data adapters (M101/M105) and only the
+ first one you turn on works.
+ Solution:
+ Select Unimodem mode for all DECT data adapters. (see section 2.4.)
+
+3.2. Telling the driver to provide more information
+ ----------------------------------------------
+ Building the driver with the "Gigaset debugging" kernel configuration
+ option (CONFIG_GIGASET_DEBUG) gives it the ability to produce additional
+ information useful for debugging.
+
+ You can control the amount of debugging information the driver produces by
+ writing an appropriate value to /sys/module/gigaset/parameters/debug, e.g.
+ echo 0 > /sys/module/gigaset/parameters/debug
+ switches off debugging output completely,
+ echo 0x10a020 > /sys/module/gigaset/parameters/debug
+ enables the standard set of debugging output messages. These values are
+ bit patterns where every bit controls a certain type of debugging output.
+ See the constants DEBUG_* in the source file gigaset.h for details.
+
+ The initial value can be set using the debug parameter when loading the
+ module "gigaset", e.g. by adding a line
+ options gigaset debug=0
+ to /etc/modprobe.conf, ...
+
+ Generated debugging information can be found
+ - as output of the command
+ dmesg
+ - in system log files written by your syslog daemon, usually
+ in /var/log/, e.g. /var/log/messages.
+
+3.3. Reporting problems and bugs
+ ---------------------------
+ If you can't solve problems with the driver on your own, feel free to
+ use one of the forums, bug trackers, or mailing lists on
+ http://sourceforge.net/projects/gigaset307x
+ or write an electronic mail to the maintainers.
+
+ Try to provide as much information as possible, such as
+ - distribution
+ - kernel version (uname -r)
+ - gcc version (gcc --version)
+ - hardware architecture (uname -m, ...)
+ - type and firmware version of your device (base and wireless module,
+ if any)
+ - output of "lsusb -v" (if using an USB device)
+ - error messages
+ - relevant system log messages (it would help if you activate debug
+ output as described in 3.2.)
+
+ For help with general configuration problems not specific to our driver,
+ such as isdn4linux and network configuration issues, please refer to the
+ appropriate forums and newsgroups.
+
+3.4. Reporting problem solutions
+ ---------------------------
+ If you solved a problem with our drivers, wrote startup scripts for your
+ distribution, ... feel free to contact us (using one of the places
+ mentioned in 3.3.). We'd like to add scripts, hints, documentation
+ to the driver and/or the project web page.
+
+
+4. Links, other software
+ ---------------------
+ - Sourceforge project developing this driver and associated tools
+ http://sourceforge.net/projects/gigaset307x
+ - Yahoo! Group on the Siemens Gigaset family of devices
+ http://de.groups.yahoo.com/group/Siemens-Gigaset
+ - Siemens Gigaset/T-Sinus compatibility table
+ http://www.erbze.info/sinus_gigaset.htm
+
+
+5. Credits
+ -------
+ Thanks to
+
+ Karsten Keil
+ for his help with isdn4linux
+ Deti Fliegl
+ for his base driver code
+ Dennis Dietrich
+ for his kernel 2.6 patches
+ Andreas Rummel
+ for his work and logs to get unimodem mode working
+ Andreas Degert
+ for his logs and patches to get cx 100 working
+ Dietrich Feist
+ for his generous donation of one M105 and two M101 cordless adapters
+ Christoph Schweers
+ for his generous donation of a M34 device
+
+ and all the other people who sent logs and other information.
+
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index fcccf2432f98..61fc079eb966 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -44,7 +44,7 @@ What is covered within this file is mainly information to authors
of modules. The author of an external modules should supply
a makefile that hides most of the complexity so one only has to type
'make' to build the module. A complete example will be present in
-chapter ¤. Creating a kbuild file for an external module".
+chapter 4, "Creating a kbuild file for an external module".
=== 2. How to build external modules
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8cb55c30b0f..b3a6187e5305 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1,4 +1,4 @@
-February 2003 Kernel Parameters v2.5.59
+ Kernel Parameters
~~~~~~~~~~~~~~~~~
The following is a consolidated list of the kernel parameters as implemented
@@ -17,9 +17,17 @@ are specified on the kernel command line with the module name plus
usbcore.blinkenlights=1
-The text in square brackets at the beginning of the description states the
-restrictions on the kernel for the said kernel parameter to be valid. The
-restrictions referred to are that the relevant option is valid if:
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+The parameters listed below are only valid if certain kernel build options were
+enabled and if respective hardware is present. The text in square brackets at
+the beginning of each description states the restrictions within which a
+parameter is applicable:
ACPI ACPI support is enabled.
ALSA ALSA sound support is enabled.
@@ -1046,10 +1054,10 @@ running once the system is up.
noltlbs [PPC] Do not use large page/tlb entries for kernel
lowmem mapping on PPC40x.
- nomce [IA-32] Machine Check Exception
-
nomca [IA-64] Disable machine check abort handling
+ nomce [IA-32] Machine Check Exception
+
noresidual [PPC] Don't use residual data on PReP machines.
noresume [SWSUSP] Disables resume and restores original swap
@@ -1682,20 +1690,6 @@ running once the system is up.
______________________________________________________________________
-Changelog:
-
-2000-06-?? Mr. Unknown
- The last known update (for 2.4.0) - the changelog was not kept before.
-
-2002-11-24 Petr Baudis <pasky@ucw.cz>
- Randy Dunlap <randy.dunlap@verizon.net>
- Update for 2.5.49, description for most of the options introduced,
- references to other documentation (C files, READMEs, ..), added S390,
- PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and
- reformatting.
-
-2005-10-19 Randy Dunlap <rdunlap@xenotime.net>
- Lots of typos, whitespace, some reformatting.
TODO:
diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
index b18e21675906..5696e879449b 100644
--- a/Documentation/laptop-mode.txt
+++ b/Documentation/laptop-mode.txt
@@ -919,11 +919,11 @@ int main(int argc, char **argv)
int settle_time = 60;
/* Parse the simple command-line */
- if (ac == 2)
- disk = av[1];
- else if (ac == 4) {
- settle_time = atoi(av[2]);
- disk = av[3];
+ if (argc == 2)
+ disk = argv[1];
+ else if (argc == 4) {
+ settle_time = atoi(argv[2]);
+ disk = argv[3];
} else
usage();
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index f8550310a6d5..92f0056d928c 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -610,6 +610,7 @@ loads. Consider the following sequence of events:
CPU 1 CPU 2
======================= =======================
+ { B = 7; X = 9; Y = 8; C = &Y }
STORE A = 1
STORE B = 2
<write barrier>
@@ -651,7 +652,20 @@ In the above example, CPU 2 perceives that B is 7, despite the load of *C
(which would be B) coming after the the LOAD of C.
If, however, a data dependency barrier were to be placed between the load of C
-and the load of *C (ie: B) on CPU 2, then the following will occur:
+and the load of *C (ie: B) on CPU 2:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { B = 7; X = 9; Y = 8; C = &Y }
+ STORE A = 1
+ STORE B = 2
+ <write barrier>
+ STORE C = &B LOAD X
+ STORE D = 4 LOAD C (gets &B)
+ <data dependency barrier>
+ LOAD *C (reads B)
+
+then the following will occur:
+-------+ : : : :
| | +------+ +-------+
@@ -829,8 +843,8 @@ There are some more advanced barrier functions:
(*) smp_mb__after_atomic_inc();
These are for use with atomic add, subtract, increment and decrement
- functions, especially when used for reference counting. These functions
- do not imply memory barriers.
+ functions that don't return a value, especially when used for reference
+ counting. These functions do not imply memory barriers.
As an example, consider a piece of code that marks an object as being dead
and then decrements the object's reference count:
@@ -1263,15 +1277,17 @@ else.
ATOMIC OPERATIONS
-----------------
-Though they are technically interprocessor interaction considerations, atomic
-operations are noted specially as they do _not_ generally imply memory
-barriers. The possible offenders include:
+Whilst they are technically interprocessor interaction considerations, atomic
+operations are noted specially as some of them imply full memory barriers and
+some don't, but they're very heavily relied on as a group throughout the
+kernel.
+
+Any atomic operation that modifies some state in memory and returns information
+about the state (old or new) implies an SMP-conditional general memory barrier
+(smp_mb()) on each side of the actual operation. These include:
xchg();
cmpxchg();
- test_and_set_bit();
- test_and_clear_bit();
- test_and_change_bit();
atomic_cmpxchg();
atomic_inc_return();
atomic_dec_return();
@@ -1282,21 +1298,31 @@ barriers. The possible offenders include:
atomic_sub_and_test();
atomic_add_negative();
atomic_add_unless();
+ test_and_set_bit();
+ test_and_clear_bit();
+ test_and_change_bit();
-These may be used for such things as implementing LOCK operations or controlling
-the lifetime of objects by decreasing their reference counts. In such cases
-they need preceding memory barriers.
+These are used for such things as implementing LOCK-class and UNLOCK-class
+operations and adjusting reference counters towards object destruction, and as
+such the implicit memory barrier effects are necessary.
-The following may also be possible offenders as they may be used as UNLOCK
-operations.
+The following operation are potential problems as they do _not_ imply memory
+barriers, but might be used for implementing such things as UNLOCK-class
+operations:
+
+ atomic_set();
set_bit();
clear_bit();
change_bit();
- atomic_set();
+With these the appropriate explicit memory barrier should be used if necessary
+(smp_mb__before_clear_bit() for instance).
-The following are a little tricky:
+
+The following also do _not_ imply memory barriers, and so may require explicit
+memory barriers under some circumstances (smp_mb__before_atomic_dec() for
+instance)):
atomic_add();
atomic_sub();
@@ -1317,10 +1343,12 @@ specific order.
Basically, each usage case has to be carefully considered as to whether memory
-barriers are needed or not. The simplest rule is probably: if the atomic
-operation is protected by a lock, then it does not require a barrier unless
-there's another operation within the critical section with respect to which an
-ordering must be maintained.
+barriers are needed or not.
+
+[!] Note that special memory barrier primitives are available for these
+situations because on some CPUs the atomic instructions used imply full memory
+barriers, and so barrier instructions are superfluous in conjunction with them,
+and in such cases the special barrier primitives will be no-ops.
See Documentation/atomic_ops.txt for more information.
diff --git a/Documentation/mtrr.txt b/Documentation/mtrr.txt
index b78af1c32996..c39ac395970e 100644
--- a/Documentation/mtrr.txt
+++ b/Documentation/mtrr.txt
@@ -138,19 +138,29 @@ Reading MTRRs from a C program using ioctl()'s:
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
-#define MTRR_NEED_STRINGS
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
#define ERRSTRING strerror (errno)
+static char *mtrr_strings[MTRR_NUM_TYPES] =
+{
+ "uncachable", /* 0 */
+ "write-combining", /* 1 */
+ "?", /* 2 */
+ "?", /* 3 */
+ "write-through", /* 4 */
+ "write-protect", /* 5 */
+ "write-back", /* 6 */
+};
int main ()
{
@@ -232,13 +242,22 @@ Creating MTRRs from a C programme using ioctl()'s:
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
-#define MTRR_NEED_STRINGS
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
#define ERRSTRING strerror (errno)
+static char *mtrr_strings[MTRR_NUM_TYPES] =
+{
+ "uncachable", /* 0 */
+ "write-combining", /* 1 */
+ "?", /* 2 */
+ "?", /* 3 */
+ "write-through", /* 4 */
+ "write-protect", /* 5 */
+ "write-back", /* 6 */
+};
int main (int argc, char **argv)
{
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 4fc8e9874320..aaf99d5f0dad 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -254,7 +254,7 @@ and, the number of frames be
<block number> * <block size> / <frame size>
-Suposse the following parameters, which apply for 2.6 kernel and an
+Suppose the following parameters, which apply for 2.6 kernel and an
i386 architecture:
<size-max> = 131072 bytes
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index ec3d109d787a..76750fb9151a 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -138,7 +138,7 @@ This means that you have to read/write IP packets when you are using tun and
ethernet frames when using tap.
5. What is the difference between BPF and TUN/TAP driver?
-BFP is an advanced packet filter. It can be attached to existing
+BPF is an advanced packet filter. It can be attached to existing
network interface. It does not provide a virtual network interface.
A TUN/TAP driver does provide a virtual network interface and it is possible
to attach BPF to this interface.
diff --git a/Documentation/networking/xfrm_sync.txt b/Documentation/networking/xfrm_sync.txt
new file mode 100644
index 000000000000..8be626f7c0b8
--- /dev/null
+++ b/Documentation/networking/xfrm_sync.txt
@@ -0,0 +1,166 @@
+
+The sync patches work is based on initial patches from
+Krisztian <hidden@balabit.hu> and others and additional patches
+from Jamal <hadi@cyberus.ca>.
+
+The end goal for syncing is to be able to insert attributes + generate
+events so that the an SA can be safely moved from one machine to another
+for HA purposes.
+The idea is to synchronize the SA so that the takeover machine can do
+the processing of the SA as accurate as possible if it has access to it.
+
+We already have the ability to generate SA add/del/upd events.
+These patches add ability to sync and have accurate lifetime byte (to
+ensure proper decay of SAs) and replay counters to avoid replay attacks
+with as minimal loss at failover time.
+This way a backup stays as closely uptodate as an active member.
+
+Because the above items change for every packet the SA receives,
+it is possible for a lot of the events to be generated.
+For this reason, we also add a nagle-like algorithm to restrict
+the events. i.e we are going to set thresholds to say "let me
+know if the replay sequence threshold is reached or 10 secs have passed"
+These thresholds are set system-wide via sysctls or can be updated
+per SA.
+
+The identified items that need to be synchronized are:
+- the lifetime byte counter
+note that: lifetime time limit is not important if you assume the failover
+machine is known ahead of time since the decay of the time countdown
+is not driven by packet arrival.
+- the replay sequence for both inbound and outbound
+
+1) Message Structure
+----------------------
+
+nlmsghdr:aevent_id:optional-TLVs.
+
+The netlink message types are:
+
+XFRM_MSG_NEWAE and XFRM_MSG_GETAE.
+
+A XFRM_MSG_GETAE does not have TLVs.
+A XFRM_MSG_NEWAE will have at least two TLVs (as is
+discussed further below).
+
+aevent_id structure looks like:
+
+ struct xfrm_aevent_id {
+ struct xfrm_usersa_id sa_id;
+ __u32 flags;
+ };
+
+xfrm_usersa_id in this message layout identifies the SA.
+
+flags are used to indicate different things. The possible
+flags are:
+ XFRM_AE_RTHR=1, /* replay threshold*/
+ XFRM_AE_RVAL=2, /* replay value */
+ XFRM_AE_LVAL=4, /* lifetime value */
+ XFRM_AE_ETHR=8, /* expiry timer threshold */
+ XFRM_AE_CR=16, /* Event cause is replay update */
+ XFRM_AE_CE=32, /* Event cause is timer expiry */
+ XFRM_AE_CU=64, /* Event cause is policy update */
+
+How these flags are used is dependent on the direction of the
+message (kernel<->user) as well the cause (config, query or event).
+This is described below in the different messages.
+
+The pid will be set appropriately in netlink to recognize direction
+(0 to the kernel and pid = processid that created the event
+when going from kernel to user space)
+
+A program needs to subscribe to multicast group XFRMNLGRP_AEVENTS
+to get notified of these events.
+
+2) TLVS reflect the different parameters:
+-----------------------------------------
+
+a) byte value (XFRMA_LTIME_VAL)
+This TLV carries the running/current counter for byte lifetime since
+last event.
+
+b)replay value (XFRMA_REPLAY_VAL)
+This TLV carries the running/current counter for replay sequence since
+last event.
+
+c)replay threshold (XFRMA_REPLAY_THRESH)
+This TLV carries the threshold being used by the kernel to trigger events
+when the replay sequence is exceeded.
+
+d) expiry timer (XFRMA_ETIMER_THRESH)
+This is a timer value in milliseconds which is used as the nagle
+value to rate limit the events.
+
+3) Default configurations for the parameters:
+----------------------------------------------
+
+By default these events should be turned off unless there is
+at least one listener registered to listen to the multicast
+group XFRMNLGRP_AEVENTS.
+
+Programs installing SAs will need to specify the two thresholds, however,
+in order to not change existing applications such as racoon
+we also provide default threshold values for these different parameters
+in case they are not specified.
+
+the two sysctls/proc entries are:
+a) /proc/sys/net/core/sysctl_xfrm_aevent_etime
+used to provide default values for the XFRMA_ETIMER_THRESH in incremental
+units of time of 100ms. The default is 10 (1 second)
+
+b) /proc/sys/net/core/sysctl_xfrm_aevent_rseqth
+used to provide default values for XFRMA_REPLAY_THRESH parameter
+in incremental packet count. The default is two packets.
+
+4) Message types
+----------------
+
+a) XFRM_MSG_GETAE issued by user-->kernel.
+XFRM_MSG_GETAE does not carry any TLVs.
+The response is a XFRM_MSG_NEWAE which is formatted based on what
+XFRM_MSG_GETAE queried for.
+The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+*if XFRM_AE_RTHR flag is set, then XFRMA_REPLAY_THRESH is also retrieved
+*if XFRM_AE_ETHR flag is set, then XFRMA_ETIMER_THRESH is also retrieved
+
+b) XFRM_MSG_NEWAE is issued by either user space to configure
+or kernel to announce events or respond to a XFRM_MSG_GETAE.
+
+i) user --> kernel to configure a specific SA.
+any of the values or threshold parameters can be updated by passing the
+appropriate TLV.
+A response is issued back to the sender in user space to indicate success
+or failure.
+In the case of success, additionally an event with
+XFRM_MSG_NEWAE is also issued to any listeners as described in iii).
+
+ii) kernel->user direction as a response to XFRM_MSG_GETAE
+The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+The threshold TLVs will be included if explicitly requested in
+the XFRM_MSG_GETAE message.
+
+iii) kernel->user to report as event if someone sets any values or
+thresholds for an SA using XFRM_MSG_NEWAE (as described in #i above).
+In such a case XFRM_AE_CU flag is set to inform the user that
+the change happened as a result of an update.
+The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+
+iv) kernel->user to report event when replay threshold or a timeout
+is exceeded.
+In such a case either XFRM_AE_CR (replay exceeded) or XFRM_AE_CE (timeout
+happened) is set to inform the user what happened.
+Note the two flags are mutually exclusive.
+The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+
+Exceptions to threshold settings
+--------------------------------
+
+If you have an SA that is getting hit by traffic in bursts such that
+there is a period where the timer threshold expires with no packets
+seen, then an odd behavior is seen as follows:
+The first packet arrival after a timer expiry will trigger a timeout
+aevent; i.e we dont wait for a timeout period or a packet threshold
+to be reached. This is done for simplicity and efficiency reasons.
+
+-JHS
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 711210b38f5f..66bbbf1d1ef6 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -259,7 +259,17 @@ on the bus need to be capable of doing it, so this is something which needs
to be handled by platform and generic code, not individual drivers.
-8. Obsolete functions
+8. Vendor and device identifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For the future, let's avoid adding device ids to include/linux/pci_ids.h.
+
+PCI_VENDOR_ID_xxx for vendors, and a hex constant for device ids.
+
+Rationale: PCI_VENDOR_ID_xxx constants are re-used, but device ids are not.
+ Further, device ids are arbitrary hex numbers, normally used only in a
+ single location, the pci_device_id table.
+
+9. Obsolete functions
~~~~~~~~~~~~~~~~~~~~~
There are several functions which you might come across when trying to
port an old driver to the new PCI interface. They are no longer present
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 97420f08c786..4739c5c3face 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,5 +1,11 @@
This file details changes in 2.6 which affect PCMCIA card driver authors:
+* New release helper (as of 2.6.17)
+ Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's
+ necessary now is calling pcmcia_disable_device. As there is no valid
+ reason left to call pcmcia_release_io and pcmcia_release_irq, the
+ exports for them were removed.
+
* Unify detach and REMOVAL event code, as well as attach and INSERTION
code (as of 2.6.16)
void (*remove) (struct pcmcia_device *dev);
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index d18a57d1a531..43a889f8f08d 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -140,7 +140,7 @@ IBM TP T41p s3_bios (2), switch to X after resume
IBM TP T42 s3_bios (2)
IBM ThinkPad T42p (2373-GTG) s3_bios (2)
IBM TP X20 ??? (*)
-IBM TP X30 s3_bios (2)
+IBM TP X30 s3_bios, s3_mode (4)
IBM TP X31 / Type 2672-XXH none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
IBM TP X32 none (1), but backlight is on and video is trashed after long suspend. s3_bios,s3_mode (4) works too. Perhaps that gets better results?
IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index 331afd791cbb..ce767b90bb0d 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -19,9 +19,9 @@ TABLE OF CONTENTS
[2-1-1] Overview
[2-1-2] Flow of scmds through EH
[2-1-3] Flow of control
- [2-2] EH through hostt->eh_strategy_handler()
- [2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
- [2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+ [2-2] EH through transportt->eh_strategy_handler()
+ [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions
+ [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions
[2-2-3] Things to consider
@@ -413,9 +413,9 @@ scmd->allowed.
layer of failure of the scmds.
-[2-2] EH through hostt->eh_strategy_handler()
+[2-2] EH through transportt->eh_strategy_handler()
- hostt->eh_strategy_handler() is invoked in the place of
+ transportt->eh_strategy_handler() is invoked in the place of
scsi_unjam_host() and it is responsible for whole recovery process.
On completion, the handler should have made lower layers forget about
all failed scmds and either ready for new commands or offline. Also,
@@ -424,7 +424,7 @@ SCSI midlayer. IOW, of the steps described in [2-1-2], all steps
except for #1 must be implemented by eh_strategy_handler().
-[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
+[2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions
The following conditions are true on entry to the handler.
@@ -437,7 +437,7 @@ except for #1 must be implemented by eh_strategy_handler().
- shost->host_failed == shost->host_busy
-[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+[2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions
The following conditions must be true on exit from the handler.
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 8bbae3e1abdf..75a535a975c3 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -804,7 +804,6 @@ Summary:
eh_bus_reset_handler - issue SCSI bus reset
eh_device_reset_handler - issue SCSI device reset
eh_host_reset_handler - reset host (host bus adapter)
- eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
info - supply information about given host
ioctl - driver can respond to ioctls
proc_info - supports /proc/scsi/{driver_name}/{host_no}
@@ -970,24 +969,6 @@ Details:
/**
- * eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
- * @shp: host on which error has occurred
- *
- * Returns TRUE if host unjammed, else FALSE.
- *
- * Locks: none
- *
- * Calling context: kernel thread
- *
- * Notes: Invoked from scsi_eh thread. LLD supplied alternate to
- * scsi_unjam_host() found in scsi_error.c
- *
- * Optionally defined in: LLD
- **/
- int eh_strategy_handler(struct Scsi_Host * shp)
-
-
-/**
* info - supply information about given host: driver name plus data
* to distinguish given host
* @shp: host to supply information about
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index 42ef9970bc86..df82116a9f26 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -3,14 +3,11 @@
--------------------
- $Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $
-
-
This document is meant as a brief overview of some aspects of the new serial
driver. It is not complete, any questions you have should be directed to
<rmk@arm.linux.org.uk>
-The reference implementation is contained within serial_amba.c.
+The reference implementation is contained within amba_pl011.c.
@@ -31,6 +28,11 @@ The serial core provides a few helper functions. This includes identifing
the correct port structure (via uart_get_console) and decoding command line
arguments (uart_parse_options).
+There is also a helper function (uart_write_console) which performs a
+character by character write, translating newlines to CRLF sequences.
+Driver writers are recommended to use this function rather than implementing
+their own version.
+
Locking
-------
@@ -86,6 +88,7 @@ hardware.
- TIOCM_DTR DTR signal.
- TIOCM_OUT1 OUT1 signal.
- TIOCM_OUT2 OUT2 signal.
+ - TIOCM_LOOP Set the port into loopback mode.
If the appropriate bit is set, the signal should be driven
active. If the bit is clear, the signal should be driven
inactive.
@@ -141,6 +144,10 @@ hardware.
enable_ms(port)
Enable the modem status interrupts.
+ This method may be called multiple times. Modem status
+ interrupts should be disabled when the shutdown method is
+ called.
+
Locking: port->lock taken.
Interrupts: locally disabled.
This call must not sleep
@@ -160,6 +167,8 @@ hardware.
state. Enable the port for reception. It should not activate
RTS nor DTR; this will be done via a separate call to set_mctrl.
+ This method will only be called when the port is initially opened.
+
Locking: port_sem taken.
Interrupts: globally disabled.
@@ -169,6 +178,11 @@ hardware.
RTS nor DTR; this will have already been done via a separate
call to set_mctrl.
+ Drivers must not access port->info once this call has completed.
+
+ This method will only be called when there are no more users of
+ this port.
+
Locking: port_sem taken.
Interrupts: caller dependent.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 1def6049784c..0ee2c7dfc482 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -120,6 +120,34 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
enable - enable card
- Default: enabled, for PCI and ISA PnP cards
+ Module snd-adlib
+ ----------------
+
+ Module for AdLib FM cards.
+
+ port - port # for OPL chip
+
+ This module supports multiple cards. It does not support autoprobe, so
+ the port must be specified. For actual AdLib FM cards it will be 0x388.
+ Note that this card does not have PCM support and no mixer; only FM
+ synthesis.
+
+ Make sure you have "sbiload" from the alsa-tools package available and,
+ after loading the module, find out the assigned ALSA sequencer port
+ number through "sbiload -l". Example output:
+
+ Port Client name Port name
+ 64:0 OPL2 FM synth OPL2 FM Port
+
+ Load the std.sb and drums.sb patches also supplied by sbiload:
+
+ sbiload -p 64:0 std.sb drums.sb
+
+ If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
+ instead. To have the card produce sound, use aplaymidi from alsa-utils:
+
+ aplaymidi -p 64:0 foo.mid
+
Module snd-ad1816a
------------------
@@ -190,6 +218,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-als300
+ -----------------
+
+ Module for Avance Logic ALS300 and ALS300+
+
+ This module supports multiple cards.
+
+ The power-management is supported.
+
Module snd-als4000
------------------
@@ -701,6 +738,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
uniwill 3-jack
F1734 2-jack
lg LG laptop (m1 express dual)
+ lg-lw LG LW20 laptop
test for testing/debugging purpose, almost all controls can be
adjusted. Appearing only when compiled with
$CONFIG_SND_DEBUG=y
@@ -1013,6 +1051,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-miro
+ ---------------
+
+ Module for Miro soundcards: miroSOUND PCM 1 pro,
+ miroSOUND PCM 12,
+ miroSOUND PCM 20 Radio.
+
+ port - Port # (0x530,0x604,0xe80,0xf40)
+ irq - IRQ # (5,7,9,10,11)
+ dma1 - 1st dma # (0,1,3)
+ dma2 - 2nd dma # (0,1)
+ mpu_port - MPU-401 port # (0x300,0x310,0x320,0x330)
+ mpu_irq - MPU-401 irq # (5,7,9,10)
+ fm_port - FM Port # (0x388)
+ wss - enable WSS mode
+ ide - enable onboard ide support
+
Module snd-mixart
-----------------
@@ -1202,6 +1257,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-riptide
+ ------------------
+
+ Module for Conexant Riptide chip
+
+ joystick_port - Joystick port # (default: 0x200)
+ mpu_port - MPU401 port # (default: 0x330)
+ opl3_port - OPL3 port # (default: 0x388)
+
+ This module supports multiple cards.
+ The driver requires the firmware loader support on kernel.
+ You need to install the firmware file "riptide.hex" to the standard
+ firmware path (e.g. /lib/firmware).
+
Module snd-rme32
----------------
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 6feef9e82b63..68eeebc17ff4 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1123,8 +1123,8 @@
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check PCI availability (28bit DMA) */
- if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
@@ -1216,7 +1216,7 @@
The allocation of PCI resources is done in the
<function>probe()</function> function, and usually an extra
<function>xxx_create()</function> function is written for this
- purpose.
+ purpose.
</para>
<para>
@@ -1225,7 +1225,7 @@
allocating resources. Also, you need to set the proper PCI DMA
mask to limit the accessed i/o range. In some cases, you might
need to call <function>pci_set_master()</function> function,
- too.
+ too.
</para>
<para>
@@ -1236,8 +1236,8 @@
<![CDATA[
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
@@ -1256,13 +1256,13 @@
functions. Unlike ALSA ver.0.5.x., there are no helpers for
that. And these resources must be released in the destructor
function (see below). Also, on ALSA 0.9.x, you don't need to
- allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
+ allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
</para>
<para>
Now assume that this PCI device has an I/O port with 8 bytes
and an interrupt. Then struct <structname>mychip</structname> will have the
- following fields:
+ following fields:
<informalexample>
<programlisting>
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 8c7195455963..bca50903233f 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -52,7 +52,7 @@
51 -> ProVideo PV952 [1540:9524]
52 -> AverMedia AverTV/305 [1461:2108]
53 -> ASUS TV-FM 7135 [1043:4845]
- 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214]
+ 54 -> LifeView FlyTV Platinum FM / Gold [5168:0214,1489:0214,5168:0304]
55 -> LifeView FlyDVB-T DUO [5168:0306]
56 -> Avermedia AVerTV 307 [1461:a70a]
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
@@ -84,7 +84,7 @@
83 -> Terratec Cinergy 250 PCI TV [153b:1160]
84 -> LifeView FlyDVB Trio [5168:0319]
85 -> AverTV DVB-T 777 [1461:2c05]
- 86 -> LifeView FlyDVB-T [5168:0301]
+ 86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421]
88 -> Tevion/KWorld DVB-T 220RF [17de:7201]
89 -> ELSA EX-VISION 700TV [1048:226c]
@@ -92,3 +92,4 @@
91 -> AVerMedia A169 B [1461:7360]
92 -> AVerMedia A169 B1 [1461:6360]
93 -> Medion 7134 Bridge #2 [16be:0005]
+ 94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502]
diff --git a/Documentation/usb/et61x251.txt b/Documentation/video4linux/et61x251.txt
index 29340282ab5f..29340282ab5f 100644
--- a/Documentation/usb/et61x251.txt
+++ b/Documentation/video4linux/et61x251.txt
diff --git a/Documentation/usb/ibmcam.txt b/Documentation/video4linux/ibmcam.txt
index c25003644131..4a40a2e99451 100644
--- a/Documentation/usb/ibmcam.txt
+++ b/Documentation/video4linux/ibmcam.txt
@@ -122,7 +122,7 @@ WHAT YOU NEED:
- A Linux box with USB support (2.3/2.4; 2.2 w/backport may work)
- A Video4Linux compatible frame grabber program such as xawtv.
-
+
HOW TO COMPILE THE DRIVER:
You need to compile the driver only if you are a developer
diff --git a/Documentation/usb/ov511.txt b/Documentation/video4linux/ov511.txt
index a7fc0432bff1..142741e3c578 100644
--- a/Documentation/usb/ov511.txt
+++ b/Documentation/video4linux/ov511.txt
@@ -9,7 +9,7 @@ INTRODUCTION:
This is a driver for the OV511, a USB-only chip used in many "webcam" devices.
Any camera using the OV511/OV511+ and the OV6620/OV7610/20/20AE should work.
-Video capture devices that use the Philips SAA7111A decoder also work. It
+Video capture devices that use the Philips SAA7111A decoder also work. It
supports streaming and capture of color or monochrome video via the Video4Linux
API. Most V4L apps are compatible with it. Most resolutions with a width and
height that are a multiple of 8 are supported.
@@ -52,15 +52,15 @@ from it:
chmod 666 /dev/video
chmod 666 /dev/video0 (if necessary)
-
+
Now you are ready to run a video app! Both vidcat and xawtv work well for me
at 640x480.
-
+
[Using vidcat:]
vidcat -s 640x480 -p c > test.jpg
xview test.jpg
-
+
[Using xawtv:]
From the main xawtv directory:
@@ -70,7 +70,7 @@ From the main xawtv directory:
make
make install
-Now you should be able to run xawtv. Right click for the options dialog.
+Now you should be able to run xawtv. Right click for the options dialog.
MODULE PARAMETERS:
@@ -286,4 +286,3 @@ Randy Dunlap, and others. Big thanks to them for their pioneering work on that
and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and
image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio
Matsuoka for their work as well.
-
diff --git a/Documentation/usb/se401.txt b/Documentation/video4linux/se401.txt
index 7b9d1c960a10..7b9d1c960a10 100644
--- a/Documentation/usb/se401.txt
+++ b/Documentation/video4linux/se401.txt
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
index b957beae5607..142920bc011f 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -174,7 +174,7 @@ Module parameters are listed below:
-------------------------------------------------------------------------------
Name: video_nr
Type: short array (min = 0, max = 64)
-Syntax: <-1|n[,...]>
+Syntax: <-1|n[,...]>
Description: Specify V4L2 minor mode number:
-1 = use next available
n = use minor number n
@@ -187,7 +187,7 @@ Default: -1
-------------------------------------------------------------------------------
Name: force_munmap
Type: bool array (min = 0, max = 64)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Force the application to unmap previously mapped buffer memory
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
all the applications support this feature. This parameter is
@@ -206,7 +206,7 @@ Default: 2
-------------------------------------------------------------------------------
Name: debug
Type: ushort
-Syntax: <n>
+Syntax: <n>
Description: Debugging information level, from 0 to 3:
0 = none (use carefully)
1 = critical errors
@@ -267,7 +267,7 @@ The sysfs interface also provides the "frame_header" entry, which exports the
frame header of the most recent requested and captured video frame. The header
is always 18-bytes long and is appended to every video frame by the SN9C10x
controllers. As an example, this additional information can be used by the user
-application for implementing auto-exposure features via software.
+application for implementing auto-exposure features via software.
The following table describes the frame header:
@@ -441,7 +441,7 @@ blue pixels in one video frame. Each pixel is associated with a 8-bit long
value and is disposed in memory according to the pattern shown below:
B[0] G[1] B[2] G[3] ... B[m-2] G[m-1]
-G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1]
+G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1]
...
... B[(n-1)(m-2)] G[(n-1)(m-1)]
... G[n(m-2)] R[n(m-1)]
@@ -472,12 +472,12 @@ The pixel reference value is calculated as follows:
The algorithm purely describes the conversion from compressed Bayer code used
in the SN9C10x chips to uncompressed Bayer. Additional steps are required to
convert this to a color image (i.e. a color interpolation algorithm).
-
+
The following Huffman codes have been found:
-0: +0 (relative to reference pixel value)
+0: +0 (relative to reference pixel value)
100: +4
101: -4?
-1110xxxx: set absolute value to xxxx.0000
+1110xxxx: set absolute value to xxxx.0000
1101: +11
1111: -11
11001: +20
diff --git a/Documentation/usb/stv680.txt b/Documentation/video4linux/stv680.txt
index 6448041e7a37..4f8946f32f51 100644
--- a/Documentation/usb/stv680.txt
+++ b/Documentation/video4linux/stv680.txt
@@ -5,15 +5,15 @@ Copyright, 2001, Kevin Sisson
INTRODUCTION:
-STMicroelectronics produces the STV0680B chip, which comes in two
-types, -001 and -003. The -003 version allows the recording and downloading
-of sound clips from the camera, and allows a flash attachment. Otherwise,
-it uses the same commands as the -001 version. Both versions support a
-variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
-CIF pictures. The STV0680 supports either a serial or a usb interface, and
+STMicroelectronics produces the STV0680B chip, which comes in two
+types, -001 and -003. The -003 version allows the recording and downloading
+of sound clips from the camera, and allows a flash attachment. Otherwise,
+it uses the same commands as the -001 version. Both versions support a
+variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
+CIF pictures. The STV0680 supports either a serial or a usb interface, and
video is possible through the usb interface.
-The following cameras are known to work with this driver, although any
+The following cameras are known to work with this driver, although any
camera with Vendor/Product codes of 0553/0202 should work:
Aiptek Pencam (various models)
@@ -34,15 +34,15 @@ http://www.linux-usb.org
MODULE OPTIONS:
When the driver is compiled as a module, you can set a "swapRGB=1"
-option, if necessary, for those applications that require it
-(such as xawtv). However, the driver should detect and set this
+option, if necessary, for those applications that require it
+(such as xawtv). However, the driver should detect and set this
automatically, so this option should not normally be used.
KNOWN PROBLEMS:
-The driver seems to work better with the usb-ohci than the usb-uhci host
-controller driver.
+The driver seems to work better with the usb-ohci than the usb-uhci host
+controller driver.
HELP:
@@ -50,6 +50,4 @@ The latest info on this driver can be found at:
http://personal.clt.bellsouth.net/~kjsisson or at
http://stv0680-usb.sourceforge.net
-Any questions to me can be send to: kjsisson@bellsouth.net
-
-
+Any questions to me can be send to: kjsisson@bellsouth.net \ No newline at end of file
diff --git a/Documentation/usb/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
index 9d46cd0b19e3..3b704f2aae6d 100644
--- a/Documentation/usb/w9968cf.txt
+++ b/Documentation/video4linux/w9968cf.txt
@@ -1,5 +1,5 @@
- W996[87]CF JPEG USB Dual Mode Camera Chip
+ W996[87]CF JPEG USB Dual Mode Camera Chip
Driver for Linux 2.6 (basic version)
=========================================
@@ -115,7 +115,7 @@ additional testing and full support, would be much appreciated.
======================
For it to work properly, the driver needs kernel support for Video4Linux, USB
and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not
-actually using any external "ovcamchip" module, given that the W996[87]CF
+actually using any external "ovcamchip" module, given that the W996[87]CF
driver depends on the version of the module present in the official kernels.
The following options of the kernel configuration file must be enabled and
@@ -197,16 +197,16 @@ Note: The kernel must be compiled with the CONFIG_KMOD option
enabled for the 'ovcamchip' module to be loaded and for
this parameter to be present.
-------------------------------------------------------------------------------
-Name: simcams
-Type: int
-Syntax: <n>
+Name: simcams
+Type: int
+Syntax: <n>
Description: Number of cameras allowed to stream simultaneously.
n may vary from 0 to 32.
Default: 32
-------------------------------------------------------------------------------
Name: video_nr
Type: int array (min = 0, max = 32)
-Syntax: <-1|n[,...]>
+Syntax: <-1|n[,...]>
Description: Specify V4L minor mode number.
-1 = use next available
n = use minor number n
@@ -219,7 +219,7 @@ Default: -1
-------------------------------------------------------------------------------
Name: packet_size
Type: int array (min = 0, max = 32)
-Syntax: <n[,...]>
+Syntax: <n[,...]>
Description: Specify the maximum data payload size in bytes for alternate
settings, for each device. n is scaled between 63 and 1023.
Default: 1023
@@ -234,7 +234,7 @@ Default: 2
-------------------------------------------------------------------------------
Name: double_buffer
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Hardware double buffering: 0 disabled, 1 enabled.
It should be enabled if you want smooth video output: if you
obtain out of sync. video, disable it, or try to
@@ -243,13 +243,13 @@ Default: 1 for every device.
-------------------------------------------------------------------------------
Name: clamping
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Video data clamping: 0 disabled, 1 enabled.
Default: 0 for every device.
-------------------------------------------------------------------------------
Name: filter_type
Type: int array (min = 0, max = 32)
-Syntax: <0|1|2[,...]>
+Syntax: <0|1|2[,...]>
Description: Video filter type.
0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
The filter is used to reduce noise and aliasing artifacts
@@ -258,13 +258,13 @@ Default: 0 for every device.
-------------------------------------------------------------------------------
Name: largeview
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Large view: 0 disabled, 1 enabled.
Default: 1 for every device.
-------------------------------------------------------------------------------
Name: upscaling
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Software scaling (for non-compressed video only):
0 disabled, 1 enabled.
Disable it if you have a slow CPU or you don't have enough
@@ -341,8 +341,8 @@ Default: 50 for every device.
-------------------------------------------------------------------------------
Name: bandingfilter
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
-Description: Banding filter to reduce effects of fluorescent
+Syntax: <0|1[,...]>
+Description: Banding filter to reduce effects of fluorescent
lighting:
0 disabled, 1 enabled.
This filter tries to reduce the pattern of horizontal
@@ -374,7 +374,7 @@ Default: 0 for every device.
-------------------------------------------------------------------------------
Name: monochrome
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: The image sensor is monochrome:
0 = no, 1 = yes
Default: 0 for every device.
@@ -400,19 +400,19 @@ Default: 32768 for every device.
-------------------------------------------------------------------------------
Name: contrast
Type: long array (min = 0, max = 32)
-Syntax: <n[,...]>
+Syntax: <n[,...]>
Description: Set picture contrast (0-65535).
Default: 50000 for every device.
-------------------------------------------------------------------------------
Name: whiteness
Type: long array (min = 0, max = 32)
-Syntax: <n[,...]>
+Syntax: <n[,...]>
Description: Set picture whiteness (0-65535).
Default: 32768 for every device.
-------------------------------------------------------------------------------
Name: debug
Type: int
-Syntax: <n>
+Syntax: <n>
Description: Debugging information level, from 0 to 6:
0 = none (use carefully)
1 = critical errors
diff --git a/Documentation/usb/zc0301.txt b/Documentation/video4linux/zc0301.txt
index f55262c6733b..f55262c6733b 100644
--- a/Documentation/usb/zc0301.txt
+++ b/Documentation/video4linux/zc0301.txt
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 1ad9af1ca4d0..687104bfd09a 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -27,12 +27,21 @@ number of free hugetlb pages at any time. It also displays information about
the configured hugepage size - this is needed for generating the proper
alignment and size of the arguments to the above system calls.
-The output of "cat /proc/meminfo" will have output like:
+The output of "cat /proc/meminfo" will have lines like:
.....
HugePages_Total: xxx
HugePages_Free: yyy
-Hugepagesize: zzz KB
+HugePages_Rsvd: www
+Hugepagesize: zzz kB
+
+where:
+HugePages_Total is the size of the pool of hugepages.
+HugePages_Free is the number of hugepages in the pool that are not yet
+allocated.
+HugePages_Rsvd is short for "reserved," and is the number of hugepages
+for which a commitment to allocate from the pool has been made, but no
+allocation has yet been made. It's vaguely analogous to overcommit.
/proc/filesystems should also show a filesystem of type "hugetlbfs" configured
in the kernel.
@@ -42,11 +51,11 @@ pages in the kernel. Super user can dynamically request more (or free some
pre-configured) hugepages.
The allocation (or deallocation) of hugetlb pages is possible only if there are
enough physically contiguous free pages in system (freeing of hugepages is
-possible only if there are enough hugetlb pages free that can be transfered
+possible only if there are enough hugetlb pages free that can be transferred
back to regular memory pool).
-Pages that are used as hugetlb pages are reserved inside the kernel and can
-not be used for other purposes.
+Pages that are used as hugetlb pages are reserved inside the kernel and cannot
+be used for other purposes.
Once the kernel with Hugetlb page support is built and running, a user can
use either the mmap system call or shared memory system calls to start using
@@ -60,7 +69,7 @@ Use the following command to dynamically allocate/deallocate hugepages:
This command will try to configure 20 hugepages in the system. The success
or failure of allocation depends on the amount of physically contiguous
memory that is preset in system at this time. System administrators may want
-to put this command in one of the local rc init file. This will enable the
+to put this command in one of the local rc init files. This will enable the
kernel to request huge pages early in the boot process (when the possibility
of getting physical contiguous pages is still very high).
@@ -78,8 +87,8 @@ the uid and gid of the current process are taken. The mode option sets the
mode of root of file system to value & 0777. This value is given in octal.
By default the value 0755 is picked. The size option sets the maximum value of
memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
-rounded down to HPAGE_SIZE. The option nr_inode sets the maximum number of
-inodes that /mnt/huge can use. If the size or nr_inode options are not
+rounded down to HPAGE_SIZE. The option nr_inodes sets the maximum number of
+inodes that /mnt/huge can use. If the size or nr_inodes options are not
provided on command line then no limits are set. For size and nr_inodes
options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
example, size=2K has the same meaning as size=2048. An example is given at
@@ -88,7 +97,7 @@ the end of this document.
read and write system calls are not supported on files that reside on hugetlb
file systems.
-A regular chown, chgrp and chmod commands (with right permissions) could be
+Regular chown, chgrp, and chmod commands (with right permissions) could be
used to change the file attributes on hugetlbfs.
Also, it is important to note that no such mount command is required if the
@@ -96,8 +105,8 @@ applications are going to use only shmat/shmget system calls. Users who
wish to use hugetlb page via shared memory segment should be a member of
a supplementary group and system admin needs to configure that gid into
/proc/sys/vm/hugetlb_shm_group. It is possible for same or different
-applications to use any combination of mmaps and shm* calls. Though the
-mount of filesystem will be required for using mmaps.
+applications to use any combination of mmaps and shm* calls, though the
+mount of filesystem will be required for using mmap calls.
*******************************************************************
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 1921353259ae..f2cd6ef53ff3 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -151,6 +151,11 @@ NUMA
numa=fake=X Fake X nodes and ignore NUMA setup of the actual machine.
+ numa=hotadd=percent
+ Only allow hotadd memory to preallocate page structures upto
+ percent of already available memory.
+ numa=hotadd=0 will disable hotadd memory.
+
ACPI
acpi=off Don't enable ACPI
diff --git a/Kbuild b/Kbuild
index 95d6a00bace0..2d4f95e4b89f 100644
--- a/Kbuild
+++ b/Kbuild
@@ -18,7 +18,7 @@ define sed-y
"/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
endef
# Override default regexp for specific architectures
-sed-$(CONFIG_MIPS) := "/^@@@/s///p"
+sed-$(CONFIG_MIPS) := "/^@@@/{s/^@@@//; s/ \#.*\$$//; p;}"
quiet_cmd_offsets = GEN $@
define cmd_offsets
diff --git a/MAINTAINERS b/MAINTAINERS
index c9465811addc..d6a8e5b434ec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -411,6 +411,7 @@ AX.25 NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
+W: http://www.linux-ax25.org/
S: Maintained
BAYCOM/HDLCDRV DRIVERS FOR AX.25
@@ -420,6 +421,14 @@ L: linux-hams@vger.kernel.org
W: http://www.baycom.org/~tom/ham/ham.html
S: Maintained
+BCM43XX WIRELESS DRIVER
+P: Michael Buesch
+M: mb@bu3sch.de
+P: Stefano Brivio
+M: st3@riseup.net
+W: http://bcm43xx.berlios.de/
+S: Maintained
+
BEFS FILE SYSTEM
P: Sergey S. Kostyliov
M: rathamahata@php4.ru
@@ -1451,6 +1460,19 @@ P: Juanjo Ciarlante
M: jjciarla@raiz.uncu.edu.ar
S: Maintained
+IPATH DRIVER:
+P: Bryan O'Sullivan
+M: support@pathscale.com
+L: openib-general@openib.org
+S: Supported
+
+IPMI SUBSYSTEM
+P: Corey Minyard
+M: minyard@acm.org
+L: openipmi-developer@lists.sourceforge.net
+W: http://openipmi.sourceforge.net/
+S: Supported
+
IPX NETWORK LAYER
P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br
@@ -1550,9 +1572,7 @@ S: Maintained
KEXEC
P: Eric Biederman
-P: Randy Dunlap
M: ebiederm@xmission.com
-M: rdunlap@xenotime.net
W: http://www.xmission.com/~ebiederm/files/kexec/
L: linux-kernel@vger.kernel.org
L: fastboot@osdl.org
@@ -1865,6 +1885,7 @@ NETROM NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
+W: http://www.linux-ax25.org/
S: Maintained
NETWORK BLOCK DEVICE
@@ -2052,8 +2073,12 @@ P: Matthew Wilcox
M: matthew@wil.cx
P: Grant Grundler
M: grundler@parisc-linux.org
+P: Kyle McMartin
+M: kyle@parisc-linux.org
L: parisc-linux@parisc-linux.org
W: http://www.parisc-linux.org/
+T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
+T: cvs cvs.parisc-linux.org:/var/cvs/linux-2.6
S: Maintained
PCI ERROR RECOVERY
@@ -2256,6 +2281,7 @@ ROSE NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
+W: http://www.linux-ax25.org/
S: Maintained
RISCOM8 DRIVER
@@ -3054,13 +3080,6 @@ M: khali@linux-fr.org
L: lm-sensors@lm-sensors.org
S: Odd Fixes
-WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
-P: Nenad Corbic
-M: ncorbic@sangoma.com
-M: dm@sangoma.com
-W: http://www.sangoma.com
-S: Supported
-
WATCHDOG DEVICE DRIVERS
P: Wim Van Sebroeck
M: wim@iguana.be
diff --git a/Makefile b/Makefile
index af6210d48836..6bf99624bd4c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 16
-EXTRAVERSION =
+SUBLEVEL = 17
+EXTRAVERSION =-rc3
NAME=Sliding Snow Leopard
# *DOCUMENTATION*
@@ -1112,7 +1112,6 @@ modules_install: _emodinst_ _emodinst_post
install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
PHONY += _emodinst_
_emodinst_:
- $(Q)rm -rf $(MODLIB)/$(install-dir)
$(Q)mkdir -p $(MODLIB)/$(install-dir)
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
@@ -1275,40 +1274,43 @@ kernelversion:
# Single targets
# ---------------------------------------------------------------------------
-# The directory part is taken from first prerequisite, so this
-# works even with external modules
+# Single targets are compatible with:
+# - build whith mixed source and output
+# - build with separate output dir 'make O=...'
+# - external modules
+#
+# target-dir => where to store outputfile
+# build-dir => directory in kernel source tree to use
+
+ifeq ($(KBUILD_EXTMOD),)
+ build-dir = $(patsubst %/,%,$(dir $@))
+ target-dir = $(dir $@)
+else
+ zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
+ build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+ target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
+endif
+
%.s: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.i: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.lst: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.s: %.S prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.S prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-
-# For external modules we shall include any directory of the target,
-# but usual case there is no directory part.
-# make M=`pwd` module.o => $(dir $@)=./
-# make M=`pwd` foo/module.o => $(dir $@)=foo/
-# make M=`pwd` / => $(dir $@)=/
-
-ifeq ($(KBUILD_EXTMOD),)
- target-dir = $(@D)
-else
- zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
- target-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
-endif
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
-/ %/: scripts prepare FORCE
+# Modules
+/ %/: prepare scripts FORCE
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
- $(build)=$(target-dir)
-%.ko: scripts FORCE
+ $(build)=$(build-dir)
+%.ko: prepare scripts FORCE
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
- $(build)=$(target-dir) $(@:.ko=.o)
+ $(build)=$(build-dir) $(@:.ko=.o)
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
# FIXME Should go into a make.lib or something
diff --git a/README b/README
index 05e055530bbb..3e264723b863 100644
--- a/README
+++ b/README
@@ -165,10 +165,31 @@ CONFIGURING the kernel:
"make xconfig" X windows (Qt) based configuration tool.
"make gconfig" X windows (Gtk) based configuration tool.
"make oldconfig" Default all questions based on the contents of
- your existing ./.config file.
+ your existing ./.config file and asking about
+ new config symbols.
"make silentoldconfig"
Like above, but avoids cluttering the screen
with questions already answered.
+ "make defconfig" Create a ./.config file by using the default
+ symbol values from arch/$ARCH/defconfig.
+ "make allyesconfig"
+ Create a ./.config file by setting symbol
+ values to 'y' as much as possible.
+ "make allmodconfig"
+ Create a ./.config file by setting symbol
+ values to 'm' as much as possible.
+ "make allnoconfig" Create a ./.config file by setting symbol
+ values to 'n' as much as possible.
+ "make randconfig" Create a ./.config file by setting symbol
+ values to random values.
+
+ The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+ also use the environment variable KCONFIG_ALLCONFIG to specify a
+ filename that contains config options that the user requires to be
+ set to a specific value. If KCONFIG_ALLCONFIG=filename is not used,
+ "make *config" checks for a file named "all{yes/mod/no/random}.config"
+ for symbol values that are to be forced. If this file is not found,
+ it checks for a file named "all.config" to contain forced values.
NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 9bef61b30367..8290b69da202 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -549,6 +549,11 @@ config NUMA
Access). This option is for configuring high-end multiprocessor
server machines. If in doubt, say N.
+config NODES_SHIFT
+ int
+ default "7"
+ depends on NEED_MULTIPLE_NODES
+
# LARGE_VMALLOC is racy, if you *really* need it then fix it first
config ALPHA_LARGE_VMALLOC
bool
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 9d6186d50245..c645c5e14786 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(memcmp);
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index a15e18a00258..558b83368559 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -24,6 +24,7 @@
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */
#include <linux/mc146818rtc.h>
#include <linux/console.h>
+#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/string.h>
@@ -471,6 +472,22 @@ page_is_ram(unsigned long pfn)
return 0;
}
+static int __init
+register_cpus(void)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ register_cpu(p, i, NULL);
+ }
+ return 0;
+}
+
+arch_initcall(register_cpus);
+
void __init
setup_arch(char **cmdline_p)
{
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 02c2db08114a..185255416e85 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -439,7 +439,7 @@ setup_smp(void)
if ((cpu->flags & 0x1cc) == 0x1cc) {
smp_num_probed++;
/* Assume here that "whami" == index */
- cpu_set(i, cpu_possible_map);
+ cpu_set(i, cpu_present_mask);
cpu->pal_revision = boot_cpu_palrev;
}
@@ -450,9 +450,8 @@ setup_smp(void)
}
} else {
smp_num_probed = 1;
- cpu_set(boot_cpuid, cpu_possible_map);
+ cpu_set(boot_cpuid, cpu_present_mask);
}
- cpu_present_mask = cpumask_of_cpu(boot_cpuid);
printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
smp_num_probed, cpu_possible_map.bits[0]);
@@ -488,9 +487,8 @@ void __devinit
smp_prepare_boot_cpu(void)
{
/*
- * Mark the boot cpu (current cpu) as both present and online
+ * Mark the boot cpu (current cpu) as online
*/
- cpu_set(smp_processor_id(), cpu_present_mask);
cpu_set(smp_processor_id(), cpu_online_map);
}
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
index 338551c7113c..bbdef1be5f95 100644
--- a/arch/alpha/lib/strncpy.S
+++ b/arch/alpha/lib/strncpy.S
@@ -43,8 +43,8 @@ strncpy:
.align 4
$multiword:
- subq $24, 1, $2 # clear the final bits in the prev word
- or $2, $24, $2
+ subq $27, 1, $2 # clear the final bits in the prev word
+ or $2, $27, $2
zapnot $1, $2, $1
subq $18, 1, $18
@@ -70,8 +70,8 @@ $multiword:
bne $18, 0b
1: ldq_u $1, 0($16) # clear the leading bits in the final word
- subq $27, 1, $2
- or $2, $27, $2
+ subq $24, 1, $2
+ or $2, $24, $2
zap $1, $2, $1
stq_u $1, 0($16)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dc5a9332c915..1dbf6ddb300d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -512,6 +512,12 @@ config ARCH_DISCONTIGMEM_ENABLE
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
+config NODES_SHIFT
+ int
+ default "4" if ARCH_LH7A40X
+ default "2"
+ depends on NEED_MULTIPLE_NODES
+
source "mm/Kconfig"
config LEDS
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 95a96275f88a..6f8e84c1c1f2 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -66,7 +66,7 @@ tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -
tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
ifeq ($(CONFIG_AEABI),y)
-CFLAGS_ABI :=-mabi=aapcs -mno-thumb-interwork
+CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork
else
CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
endif
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index eed616113e47..153a07e7222b 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -18,6 +18,7 @@ SECTIONS
_start = .;
*(.start)
*(.text)
+ *(.text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata)
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 5e830f444c6c..314ebd3a1d71 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -18,6 +18,18 @@
#include <asm/io.h>
#include <asm/hardware/scoop.h>
+/* PCMCIA to Scoop linkage
+
+ There is no easy way to link multiple scoop devices into one
+ single entity for the pxa2xx_pcmcia device so this structure
+ is used which is setup by the platform code.
+
+ This file is never modular so this symbol is always
+ accessile to the board support files.
+*/
+struct scoop_pcmcia_config *platform_scoop_config;
+EXPORT_SYMBOL(platform_scoop_config);
+
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
struct scoop_dev {
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 1fe73d198888..9e1c1cceb735 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -379,7 +379,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
#
# NAND Flash Device Drivers
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index b7d934cdb1b7..6e0805a971d7 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -370,7 +370,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
#
# NAND Flash Device Drivers
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 8dcc8e8ec813..b69e88bbc909 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,12 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Mon Mar 20 14:54:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:21:01 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
@@ -28,6 +30,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -67,6 +65,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -94,6 +93,7 @@ CONFIG_ARCH_EP93XX=y
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -112,7 +112,6 @@ CONFIG_ARCH_EP93XX=y
#
# Cirrus EP93xx Implementation Options
#
-CONFIG_CRUNCH=y
#
# EP93xx Platforms
@@ -232,12 +231,15 @@ CONFIG_SYN_COOKIES=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -346,7 +348,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_OTP is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -371,7 +372,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -412,7 +412,7 @@ CONFIG_MTD_NAND_IDS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -576,13 +576,13 @@ CONFIG_WATCHDOG=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
#
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -626,9 +626,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
@@ -690,7 +688,16 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
#
#
@@ -702,6 +709,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -718,6 +726,7 @@ CONFIG_HWMON=y
#
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB=y
CONFIG_USB_DEBUG=y
@@ -776,15 +785,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -813,6 +813,7 @@ CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IPAQ is not set
# CONFIG_USB_SERIAL_IR is not set
@@ -825,6 +826,7 @@ CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
@@ -865,6 +867,32 @@ CONFIG_USB_SERIAL_PL2303=y
# CONFIG_MMC is not set
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_M48T86=y
+CONFIG_RTC_DRV_EP93XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -912,7 +940,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1044,6 +1071,7 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1053,6 +1081,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
index 7b02ca04c3ee..e6f3e4873d6c 100644
--- a/arch/arm/configs/ixp2000_defconfig
+++ b/arch/arm/configs/ixp2000_defconfig
@@ -1,18 +1,19 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb 8 04:49:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:12:49 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -29,6 +30,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -60,7 +58,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -68,6 +65,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -89,11 +87,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -123,6 +123,7 @@ CONFIG_ARCH_IXDP2800=y
CONFIG_ARCH_IXDP2X00=y
CONFIG_ARCH_IXDP2401=y
CONFIG_ARCH_IXDP2801=y
+CONFIG_MACH_IXDP28X5=y
CONFIG_ARCH_IXDP2X01=y
# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
@@ -147,7 +148,6 @@ CONFIG_XSCALE_PMU=y
# Bus support
#
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -160,6 +160,7 @@ CONFIG_PCI_LEGACY_PROC=y
#
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
# CONFIG_AEABI is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -213,6 +214,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -232,12 +234,15 @@ CONFIG_SYN_COOKIES=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -347,7 +352,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -366,7 +370,6 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -614,8 +617,9 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -623,6 +627,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -650,7 +655,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -696,7 +700,6 @@ CONFIG_I2C_IXP2000=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -715,9 +718,7 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -730,6 +731,11 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_SPI_MASTER is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Hardware Monitoring support
#
CONFIG_HWMON=y
@@ -742,6 +748,7 @@ CONFIG_HWMON=y
# 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
@@ -776,7 +783,16 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
#
#
@@ -804,6 +820,7 @@ CONFIG_HWMON=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -821,6 +838,12 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -870,7 +893,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -972,6 +994,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
index 1a2751e9ab05..9ce898a6cf87 100644
--- a/arch/arm/configs/ixp23xx_defconfig
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -1,12 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Tue Mar 21 03:27:20 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:13:50 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
@@ -28,6 +30,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -67,6 +65,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -143,7 +142,6 @@ CONFIG_CPU_BIG_ENDIAN=y
# Bus support
#
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -230,12 +228,15 @@ CONFIG_SYN_COOKIES=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -365,7 +366,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -527,7 +527,6 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -735,6 +734,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
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
@@ -776,7 +776,6 @@ CONFIG_WATCHDOG=y
#
# CONFIG_USBPCWATCHDOG is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -821,7 +820,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -840,9 +838,7 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -907,7 +903,16 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
#
#
@@ -919,6 +924,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -935,6 +941,7 @@ CONFIG_HWMON=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
@@ -1000,9 +1007,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -1017,15 +1022,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1076,6 +1072,12 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1127,7 +1129,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1268,6 +1269,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 2ce0e3a27a45..a601b8b55f35 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,7 +29,7 @@ ifneq ($(CONFIG_ARCH_EBSA110),y)
obj-y += io.o
endif
-head-y := head.o
+head-y := head$(MMUEXT).o
obj-$(CONFIG_DEBUG_LL) += debug.o
extra-y := $(head-y) init_task.o vmlinux.lds
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 1574941ebfe1..c49b5d4d7fca 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -100,23 +100,11 @@ EXPORT_SYMBOL(__raw_writesl);
#endif
/* string / mem functions */
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(__memzero);
@@ -190,8 +178,6 @@ EXPORT_SYMBOL(_find_next_bit_be);
/* syscalls */
EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_exit);
EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index b093ab8738b5..0bea65864051 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -20,10 +20,11 @@
#include <asm/mach-types.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
-#include <asm/constants.h>
+#include <asm/thread_info.h>
#include <asm/system.h>
#define PROCINFO_INITFUNC 12
+#define MACHINFO_TYPE 0
/*
* Kernel startup entry point.
@@ -79,5 +80,6 @@ __after_proc_init:
mov pc, r13 @ clear the BSS and jump
@ to start_kernel
+ .ltorg
#include "head-common.S"
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7cd280bfd63..9fc9af88c60c 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -252,6 +252,9 @@ static void __init dump_cpu_info(int cpu)
dump_cache("cache", cpu, CACHE_ISIZE(info));
}
}
+
+ if (arch_is_coherent())
+ printk("Cache coherency enabled\n");
}
int cpu_architecture(void)
@@ -319,6 +322,12 @@ static void __init setup_processor(void)
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
elf_hwcap = list->elf_hwcap;
+#ifndef CONFIG_ARM_THUMB
+ elf_hwcap &= ~HWCAP_THUMB;
+#endif
+#ifndef CONFIG_VFP
+ elf_hwcap &= ~HWCAP_VFP;
+#endif
cpu_proc_init();
}
@@ -398,7 +407,7 @@ static void __init early_initrd(char **p)
}
__early_param("initrd=", early_initrd);
-static void __init add_memory(unsigned long start, unsigned long size)
+static void __init arm_add_memory(unsigned long start, unsigned long size)
{
/*
* Ensure that start/size are aligned to a page boundary.
@@ -436,7 +445,7 @@ static void __init early_mem(char **p)
if (**p == '@')
start = memparse(*p + 1, p);
- add_memory(start, size);
+ arm_add_memory(start, size);
}
__early_param("mem=", early_mem);
@@ -578,7 +587,7 @@ static int __init parse_tag_mem32(const struct tag *tag)
tag->u.mem.start, tag->u.mem.size / 1024);
return -EINVAL;
}
- add_memory(tag->u.mem.start, tag->u.mem.size);
+ arm_add_memory(tag->u.mem.start, tag->u.mem.size);
return 0;
}
@@ -798,7 +807,7 @@ static int __init topology_init(void)
{
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
return 0;
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index 75e6ee318ded..ef88c4128edc 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -16,11 +16,12 @@ obj-$(CONFIG_MACH_CSB637) += board-csb637.o
#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
# LEDs support
-#led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
-#led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
-#led-$(CONFIG_MACH_CSB337) += leds.o
-#led-$(CONFIG_MACH_CSB637) += leds.o
+led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
+led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
+led-$(CONFIG_MACH_CSB337) += leds.o
+led-$(CONFIG_MACH_CSB637) += leds.o
#led-$(CONFIG_MACH_KB9200) += leds.o
+#led-$(CONFIG_MACH_KAFA) += leds.o
obj-$(CONFIG_LEDS) += $(led-y)
# VGA support
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 54022e58d50d..f45104ceea8f 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -67,6 +67,9 @@ static void __init csb337_map_io(void)
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = CSB337_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index 8195f9d919ea..f2c2d6e79bc6 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -67,6 +67,9 @@ static void __init csb637_map_io(void)
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = CSB637_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 8a783368366e..2d7200ed66ed 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -70,6 +70,9 @@ static void __init dk_map_io(void)
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = DK_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
@@ -118,9 +121,14 @@ static void __init dk_board_init(void)
at91_add_device_udc(&dk_udc_data);
/* Compact Flash */
at91_add_device_cf(&dk_cf_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB7, 0);
+#else
/* MMC */
- at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(&dk_mmc_data);
+#endif
/* VGA */
// dk_add_device_video();
}
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index fd0752eba897..80d90f5135a1 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -70,6 +70,9 @@ static void __init ek_map_io(void)
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = EK_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
@@ -111,9 +114,14 @@ static void __init ek_board_init(void)
at91_add_device_usbh(&ek_usbh_data);
/* USB Device */
at91_add_device_udc(&ek_udc_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
/* MMC */
- at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(&ek_mmc_data);
+#endif
/* VGA */
// ek_add_device_video();
}
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index 57eedd5beaf6..bfe47bd6e50c 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -28,10 +28,10 @@
static u64 ohci_dmamask = 0xffffffffUL;
static struct at91_usbh_data usbh_data;
-static struct resource at91rm9200_usbh_resource[] = {
+static struct resource at91_usbh_resource[] = {
[0] = {
.start = AT91_UHP_BASE,
- .end = AT91_UHP_BASE + SZ_1M -1,
+ .end = AT91_UHP_BASE + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -49,8 +49,8 @@ static struct platform_device at91rm9200_usbh_device = {
.coherent_dma_mask = 0xffffffff,
.platform_data = &usbh_data,
},
- .resource = at91rm9200_usbh_resource,
- .num_resources = ARRAY_SIZE(at91rm9200_usbh_resource),
+ .resource = at91_usbh_resource,
+ .num_resources = ARRAY_SIZE(at91_usbh_resource),
};
void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -121,6 +121,19 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
static u64 eth_dmamask = 0xffffffffUL;
static struct at91_eth_data eth_data;
+static struct resource at91_eth_resources[] = {
+ [0] = {
+ .start = AT91_BASE_EMAC,
+ .end = AT91_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_EMAC,
+ .end = AT91_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct platform_device at91rm9200_eth_device = {
.name = "at91_ether",
.id = -1,
@@ -129,7 +142,8 @@ static struct platform_device at91rm9200_eth_device = {
.coherent_dma_mask = 0xffffffff,
.platform_data = &eth_data,
},
- .num_resources = 0,
+ .resource = at91_eth_resources,
+ .num_resources = ARRAY_SIZE(at91_eth_resources),
};
void __init at91_add_device_eth(struct at91_eth_data *data)
@@ -180,13 +194,23 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
static struct at91_cf_data cf_data;
+static struct resource at91_cf_resources[] = {
+ [0] = {
+ .start = AT91_CF_BASE,
+ /* ties up CS4, CS5, and CS6 */
+ .end = AT91_CF_BASE + (0x30000000 - 1),
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+ },
+};
+
static struct platform_device at91rm9200_cf_device = {
.name = "at91_cf",
.id = -1,
.dev = {
.platform_data = &cf_data,
},
- .num_resources = 0,
+ .resource = at91_cf_resources,
+ .num_resources = ARRAY_SIZE(at91_cf_resources),
};
void __init at91_add_device_cf(struct at91_cf_data *data)
@@ -224,15 +248,20 @@ static u64 mmc_dmamask = 0xffffffffUL;
static struct at91_mmc_data mmc_data;
static struct resource at91_mmc_resources[] = {
- {
+ [0] = {
.start = AT91_BASE_MCI,
.end = AT91_BASE_MCI + SZ_16K - 1,
.flags = IORESOURCE_MEM,
- }
+ },
+ [1] = {
+ .start = AT91_ID_MCI,
+ .end = AT91_ID_MCI,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device at91rm9200_mmc_device = {
- .name = "at91rm9200_mci",
+ .name = "at91_mci",
.id = -1,
.dev = {
.dma_mask = &mmc_dmamask,
@@ -290,4 +319,123 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+static struct resource at91_nand_resources[] = {
+ {
+ .start = AT91_SMARTMEDIA_BASE,
+ .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = at91_nand_resources,
+ .num_resources = ARRAY_SIZE(at91_nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ if (!data)
+ return;
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */
+ at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */
+
+ nand_data = *data;
+ platform_device_register(&at91_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+static struct platform_device at91rm9200_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .num_resources = 0,
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PA25, 1);
+
+ at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PA26, 1);
+
+ platform_device_register(&at91rm9200_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+ .name = "at91_rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+void __init at91_add_device_rtc(void)
+{
+ platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
/* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c
new file mode 100644
index 000000000000..28150e8905ba
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/leds.c
@@ -0,0 +1,100 @@
+/*
+ * LED driver for Atmel AT91-based boards.
+ *
+ * Copyright (C) SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+static inline void at91_led_on(unsigned int led)
+{
+ at91_set_gpio_value(led, 0);
+}
+
+static inline void at91_led_off(unsigned int led)
+{
+ at91_set_gpio_value(led, 1);
+}
+
+static inline void at91_led_toggle(unsigned int led)
+{
+ unsigned long is_off = at91_get_gpio_value(led);
+ if (is_off)
+ at91_led_on(led);
+ else
+ at91_led_off(led);
+}
+
+
+/*
+ * Handle LED events.
+ */
+static void at91_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch(evt) {
+ case led_start: /* System startup */
+ at91_led_on(at91_leds_cpu);
+ break;
+
+ case led_stop: /* System stop / suspend */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer: /* Every 50 timer ticks */
+ at91_led_toggle(at91_leds_timer);
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start: /* Entering idle state */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+ case led_idle_end: /* Exit idle state */
+ at91_led_on(at91_leds_cpu);
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ local_irq_restore(flags);
+}
+
+
+static int __init leds_init(void)
+{
+ if (!at91_leds_timer || !at91_leds_cpu)
+ return -ENODEV;
+
+ /* Enable PIO to access the LEDs */
+ at91_set_gpio_output(at91_leds_timer, 1);
+ at91_set_gpio_output(at91_leds_cpu, 1);
+
+ leds_event = at91_leds_event;
+
+ leds_event(led_start);
+ return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 2d892e4daa07..dcd417625389 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -424,6 +424,14 @@ static struct amba_device uart3_device = {
.periphid = 0x00041010,
};
+
+static struct platform_device ep93xx_rtc_device = {
+ .name = "ep93xx-rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+
void __init ep93xx_init_devices(void)
{
unsigned int v;
@@ -439,4 +447,6 @@ void __init ep93xx_init_devices(void)
amba_device_register(&uart1_device, &iomem_resource);
amba_device_register(&uart2_device, &iomem_resource);
amba_device_register(&uart3_device, &iomem_resource);
+
+ platform_device_register(&ep93xx_rtc_device);
}
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 777e75daa8a5..9be01b0c3f48 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -17,6 +17,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -39,6 +41,16 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
.pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
.length = TS72XX_OPTIONS2_SIZE,
.type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_INDEX_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
+ .length = TS72XX_RTC_INDEX_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_DATA_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+ .length = TS72XX_RTC_DATA_SIZE,
+ .type = MT_DEVICE,
}
};
@@ -99,11 +111,38 @@ static void __init ts72xx_map_io(void)
}
}
+static unsigned char ts72xx_rtc_readb(unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static struct m48t86_ops ts72xx_rtc_ops = {
+ .readb = ts72xx_rtc_readb,
+ .writeb = ts72xx_rtc_writeb,
+};
+
+static struct platform_device ts72xx_rtc_device = {
+ .name = "rtc-m48t86",
+ .id = -1,
+ .dev = {
+ .platform_data = &ts72xx_rtc_ops,
+ },
+ .num_resources = 0,
+};
+
static void __init ts72xx_init_machine(void)
{
ep93xx_init_devices();
if (board_is_ts7200())
physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+ platform_device_register(&ts72xx_rtc_device);
}
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 71a59e196166..4ca51dcf13ac 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -7,11 +7,18 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ * 2004-03-03 Sascha Hauer <sascha@saschahauer.de>
* initial version heavily inspired by
* linux/arch/arm/mach-pxa/dma.c
+ *
+ * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Changed to support scatter gather DMA
+ * by taking Russell's code from RiscPC
+ *
*/
+#undef DEBUG
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -22,69 +29,368 @@
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>
+#include <asm/arch/imx-dma.h>
+
+struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+/*
+ * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @lastcount: number of bytes transferred during last transfer
+ *
+ * Functions prepares DMA controller for next sg data chunk transfer.
+ * The @lastcount argument informs function about number of bytes transferred
+ * during last block. Zero value can be used for @lastcount to setup DMA
+ * for the first chunk.
+ */
+static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned int nextcount;
+ unsigned int nextaddr;
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return 0;
+ }
+
+ imxdma->resbytes -= lastcount;
+
+ if (!imxdma->sg) {
+ pr_debug("imxdma%d: no sg data\n", dma_ch);
+ return 0;
+ }
+
+ imxdma->sgbc += lastcount;
+ if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) {
+ if ((imxdma->sgcount <= 1) || !imxdma->resbytes) {
+ pr_debug("imxdma%d: sg transfer limit reached\n",
+ dma_ch);
+ imxdma->sgcount=0;
+ imxdma->sg = NULL;
+ return 0;
+ } else {
+ imxdma->sgcount--;
+ imxdma->sg++;
+ imxdma->sgbc = 0;
+ }
+ }
+ nextcount = imxdma->sg->length - imxdma->sgbc;
+ nextaddr = imxdma->sg->dma_address + imxdma->sgbc;
-static struct dma_channel {
- char *name;
- void (*irq_handler) (int, void *, struct pt_regs *);
- void (*err_handler) (int, void *, struct pt_regs *);
- void *data;
-} dma_channels[11];
+ if(imxdma->resbytes < nextcount)
+ nextcount = imxdma->resbytes;
-/* set err_handler to NULL to have the standard info-only error handler */
+ if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
+ DAR(dma_ch) = nextaddr;
+ else
+ SAR(dma_ch) = nextaddr;
+
+ CNTR(dma_ch) = nextcount;
+ pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n",
+ dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch));
+
+ return nextcount;
+}
+
+/*
+ * imx_dma_setup_sg_base - scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ *
+ * Functions sets up i.MX DMA state for emulated scatter-gather transfer
+ * and sets up channel registers to be ready for the first chunk
+ */
+static int
+imx_dma_setup_sg_base(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+ imxdma->sg = sg;
+ imxdma->sgcount = sgcount;
+ imxdma->sgbc = 0;
+ return imx_dma_sg_next(dma_ch, 0);
+}
+
+/**
+ * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @dma_address: the DMA/physical memory address of the linear data block
+ * to transfer
+ * @dma_length: length of the data block in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ * or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel source and destination addresses for transfer
+ * specified by provided parameters. The scatter-gather emulation is disabled,
+ * because linear data block
+ * form the physical address range is transfered.
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
int
-imx_request_dma(char *name, imx_dma_prio prio,
- void (*irq_handler) (int, void *, struct pt_regs *),
- void (*err_handler) (int, void *, struct pt_regs *), void *data)
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+ unsigned int dma_length, unsigned int dev_addr,
+ dmamode_t dmamode)
{
- unsigned long flags;
- int i, found = 0;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
- /* basic sanity checks */
- if (!name || !irq_handler)
+ imxdma->sg = NULL;
+ imxdma->sgcount = 0;
+ imxdma->dma_mode = dmamode;
+ imxdma->resbytes = dma_length;
+
+ if (!dma_address) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
+ dma_ch);
return -EINVAL;
+ }
- local_irq_save(flags);
+ if (!dma_length) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
+ dma_ch);
+ return -EINVAL;
+ }
- /* try grabbing a DMA channel with the requested priority */
- for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
+ if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n",
+ dma_ch, (unsigned int)dma_address, dma_length,
+ dev_addr);
+ SAR(dma_ch) = dev_addr;
+ DAR(dma_ch) = (unsigned int)dma_address;
+ } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+ pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n",
+ dma_ch, (unsigned int)dma_address, dma_length,
+ dev_addr);
+ SAR(dma_ch) = (unsigned int)dma_address;
+ DAR(dma_ch) = dev_addr;
+ } else {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
+ dma_ch);
+ return -EINVAL;
}
- if (!found) {
- /* requested prio group is full, try hier priorities */
- for (i = prio - 1; i >= 0; i--) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
- }
+ CNTR(dma_ch) = dma_length;
+
+ return 0;
+}
+
+/**
+ * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ * @dma_length: total length of the transfer request in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ * or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel state and registers to be ready for transfer
+ * specified by provided parameters. The scatter-gather emulation is set up
+ * according to the parameters.
+ *
+ * The full preparation of the transfer requires setup of more register
+ * by the caller before imx_dma_enable() can be called.
+ *
+ * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes
+ *
+ * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx
+ *
+ * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical
+ * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified
+ *
+ * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
+ *
+ * The typical setup for %DMA_MODE_WRITE is specified by next options combination
+ *
+ * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
+ *
+ * Be carefull there and do not mistakenly mix source and target device
+ * port sizes constants, they are really different:
+ * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
+ * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
+ *
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+ unsigned int dev_addr, dmamode_t dmamode)
+{
+ int res;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+ imxdma->sg = NULL;
+ imxdma->sgcount = 0;
+ imxdma->dma_mode = dmamode;
+ imxdma->resbytes = dma_length;
+
+ if (!sg || !sgcount) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n",
+ dma_ch);
+ return -EINVAL;
+ }
+
+ if (!sg->length) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
+ dma_ch);
+ return -EINVAL;
}
- if (found) {
- DIMR &= ~(1 << i);
- dma_channels[i].name = name;
- dma_channels[i].irq_handler = irq_handler;
- dma_channels[i].err_handler = err_handler;
- dma_channels[i].data = data;
+ if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n",
+ dma_ch, sg, sgcount, dma_length, dev_addr);
+ SAR(dma_ch) = dev_addr;
+ } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+ pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n",
+ dma_ch, sg, sgcount, dma_length, dev_addr);
+ DAR(dma_ch) = dev_addr;
} else {
- printk(KERN_WARNING "No more available DMA channels for %s\n",
- name);
- i = -ENODEV;
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
+ dma_ch);
+ return -EINVAL;
+ }
+
+ res = imx_dma_setup_sg_base(dma_ch, sg, sgcount);
+ if (res <= 0) {
+ printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers
+ * @dma_ch: i.MX DMA channel number
+ * @irq_handler: the pointer to the function called if the transfer
+ * ends successfully
+ * @err_handler: the pointer to the function called if the premature
+ * end caused by error occurs
+ * @data: user specified value to be passed to the handlers
+ */
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+ void (*irq_handler) (int, void *, struct pt_regs *),
+ void (*err_handler) (int, void *, struct pt_regs *),
+ void *data)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return -ENODEV;
+ }
+
+ local_irq_save(flags);
+ DISR = (1 << dma_ch);
+ imxdma->irq_handler = irq_handler;
+ imxdma->err_handler = err_handler;
+ imxdma->data = data;
+ local_irq_restore(flags);
+ return 0;
+}
+
+/**
+ * imx_dma_enable - function to start i.MX DMA channel operation
+ * @dma_ch: i.MX DMA channel number
+ *
+ * The channel has to be allocated by driver through imx_dma_request()
+ * or imx_dma_request_by_prio() function.
+ * The transfer parameters has to be set to the channel registers through
+ * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
+ * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to
+ * be set prior this function call by the channel user.
+ */
+void imx_dma_enable(imx_dmach_t dma_ch)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ pr_debug("imxdma%d: imx_dma_enable\n", dma_ch);
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return;
+ }
+
+ local_irq_save(flags);
+ DISR = (1 << dma_ch);
+ DIMR &= ~(1 << dma_ch);
+ CCR(dma_ch) |= CCR_CEN;
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_disable - stop, finish i.MX DMA channel operatin
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_disable(imx_dmach_t dma_ch)
+{
+ unsigned long flags;
+
+ pr_debug("imxdma%d: imx_dma_disable\n", dma_ch);
+
+ local_irq_save(flags);
+ DIMR |= (1 << dma_ch);
+ CCR(dma_ch) &= ~CCR_CEN;
+ DISR = (1 << dma_ch);
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_request - request/allocate specified channel number
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ */
+int imx_dma_request(imx_dmach_t dma_ch, const char *name)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ /* basic sanity checks */
+ if (!name)
+ return -EINVAL;
+
+ if (dma_ch >= IMX_DMA_CHANNELS) {
+ printk(KERN_CRIT "%s: called for non-existed channel %d\n",
+ __FUNCTION__, dma_ch);
+ return -EINVAL;
}
+ local_irq_save(flags);
+ if (imxdma->name) {
+ local_irq_restore(flags);
+ return -ENODEV;
+ }
+
+ imxdma->name = name;
+ imxdma->irq_handler = NULL;
+ imxdma->err_handler = NULL;
+ imxdma->data = NULL;
+ imxdma->sg = NULL;
local_irq_restore(flags);
- return i;
+ return 0;
}
-void
-imx_free_dma(int dma_ch)
+/**
+ * imx_dma_free - release previously acquired channel
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_free(imx_dmach_t dma_ch)
{
unsigned long flags;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
- if (!dma_channels[dma_ch].name) {
+ if (!imxdma->name) {
printk(KERN_CRIT
"%s: trying to free channel %d which is already freed\n",
__FUNCTION__, dma_ch);
@@ -92,27 +398,84 @@ imx_free_dma(int dma_ch)
}
local_irq_save(flags);
- DIMR &= ~(1 << dma_ch);
- dma_channels[dma_ch].name = NULL;
+ /* Disable interrupts */
+ DIMR |= (1 << dma_ch);
+ CCR(dma_ch) &= ~CCR_CEN;
+ imxdma->name = NULL;
local_irq_restore(flags);
}
-static irqreturn_t
-dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+/**
+ * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ * @prio: one of the hardware distinguished priority level:
+ * %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW
+ *
+ * This function tries to find free channel in the specified priority group
+ * if the priority cannot be achieved it tries to look for free channel
+ * in the higher and then even lower priority groups.
+ *
+ * Return value: If there is no free channel to allocate, -%ENODEV is returned.
+ * Zero value indicates successful channel allocation.
+ */
+int
+imx_dma_request_by_prio(imx_dmach_t * pdma_ch, const char *name,
+ imx_dma_prio prio)
+{
+ int i;
+ int best;
+
+ switch (prio) {
+ case (DMA_PRIO_HIGH):
+ best = 8;
+ break;
+ case (DMA_PRIO_MEDIUM):
+ best = 4;
+ break;
+ case (DMA_PRIO_LOW):
+ default:
+ best = 0;
+ break;
+ }
+
+ for (i = best; i < IMX_DMA_CHANNELS; i++) {
+ if (!imx_dma_request(i, name)) {
+ *pdma_ch = i;
+ return 0;
+ }
+ }
+
+ for (i = best - 1; i >= 0; i--) {
+ if (!imx_dma_request(i, name)) {
+ *pdma_ch = i;
+ return 0;
+ }
+ }
+
+ printk(KERN_ERR "%s: no free DMA channel found\n", __FUNCTION__);
+
+ return -ENODEV;
+}
+
+static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
- struct dma_channel *channel;
+ struct imx_dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
DISR = disr;
- for (i = 0; i < 11; i++) {
- channel = &dma_channels[i];
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ channel = &imx_dma_channels[i];
- if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+ if ((err_mask & 1 << i) && channel->name
+ && channel->err_handler) {
channel->err_handler(i, channel->data, regs);
continue;
}
+ imx_dma_channels[i].sg = NULL;
+
if (DBTOSR & (1 << i)) {
printk(KERN_WARNING
"Burst timeout on channel %d (%s)\n",
@@ -141,17 +504,27 @@ dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t
-dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
+ pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
+ disr);
+
DISR = disr;
- for (i = 0; i < 11; i++) {
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
if (disr & (1 << i)) {
- struct dma_channel *channel = &dma_channels[i];
- if (channel->name && channel->irq_handler) {
- channel->irq_handler(i, channel->data, regs);
+ struct imx_dma_channel *channel = &imx_dma_channels[i];
+ if (channel->name) {
+ if (imx_dma_sg_next(i, CNTR(i))) {
+ CCR(i) &= ~CCR_CEN;
+ mb();
+ CCR(i) |= CCR_CEN;
+ } else {
+ if (channel->irq_handler)
+ channel->irq_handler(i,
+ channel->data, regs);
+ }
} else {
/*
* IRQ for an unregistered DMA channel:
@@ -165,10 +538,10 @@ dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static int __init
-imx_dma_init(void)
+static int __init imx_dma_init(void)
{
int ret;
+ int i;
/* reset DMA module */
DCR = DCR_DRST;
@@ -189,15 +562,27 @@ imx_dma_init(void)
DCR = DCR_DEN;
/* clear all interrupts */
- DISR = 0x3ff;
+ DISR = (1 << IMX_DMA_CHANNELS) - 1;
/* enable interrupts */
- DIMR = 0;
+ DIMR = (1 << IMX_DMA_CHANNELS) - 1;
+
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ imx_dma_channels[i].sg = NULL;
+ imx_dma_channels[i].dma_num = i;
+ }
return ret;
}
arch_initcall(imx_dma_init);
-EXPORT_SYMBOL(imx_request_dma);
-EXPORT_SYMBOL(imx_free_dma);
+EXPORT_SYMBOL(imx_dma_setup_single);
+EXPORT_SYMBOL(imx_dma_setup_sg);
+EXPORT_SYMBOL(imx_dma_setup_handlers);
+EXPORT_SYMBOL(imx_dma_enable);
+EXPORT_SYMBOL(imx_dma_disable);
+EXPORT_SYMBOL(imx_dma_request);
+EXPORT_SYMBOL(imx_dma_free);
+EXPORT_SYMBOL(imx_dma_request_by_prio);
+EXPORT_SYMBOL(imx_dma_channels);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 37613ad68366..9d8331be2b58 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -33,6 +33,7 @@
#include <asm/arch/imx-regs.h>
#include <asm/mach/map.h>
+#include <asm/arch/mmc.h>
void imx_gpio_mode(int gpio_mode)
{
@@ -175,13 +176,25 @@ static struct resource imx_mmc_resources[] = {
},
};
+static u64 imxmmmc_dmamask = 0xffffffffUL;
+
static struct platform_device imx_mmc_device = {
.name = "imx-mmc",
.id = 0,
+ .dev = {
+ .dma_mask = &imxmmmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
.num_resources = ARRAY_SIZE(imx_mmc_resources),
.resource = imx_mmc_resources,
};
+void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
+{
+ imx_mmc_device.dev.platform_data = info;
+}
+EXPORT_SYMBOL(imx_set_mmc_info);
+
static struct resource imx_uart1_resources[] = {
[0] = {
.start = 0x00206000,
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index 8ab1b040288c..e34d0df90aed 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -25,6 +25,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/arch/mmc.h>
#include <linux/interrupt.h>
#include "generic.h"
@@ -51,12 +52,29 @@ static struct platform_device *devices[] __initdata = {
&cs89x0_device,
};
+#ifdef CONFIG_MMC_IMX
+static int mx1ads_mmc_card_present(void)
+{
+ /* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */
+ return (SSR(1) & (1 << 20) ? 0 : 1);
+}
+
+static struct imxmmc_platform_data mx1ads_mmc_info = {
+ .card_present = mx1ads_mmc_card_present,
+};
+#endif
+
static void __init
mx1ads_init(void)
{
#ifdef CONFIG_LEDS
imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2);
#endif
+#ifdef CONFIG_MMC_IMX
+ /* SD/MMC card detect */
+ imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
+ imx_set_mmc_info(&mx1ads_mmc_info);
+#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index 2327c9790416..bf688c128630 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -44,6 +44,15 @@
#include <asm/mach/irq.h>
#include <asm/mach/pci.h>
+static int __init espresso_pci_init(void)
+{
+ if (machine_is_espresso())
+ ixp23xx_pci_slave_init();
+
+ return 0;
+};
+subsys_initcall(espresso_pci_init);
+
static void __init espresso_init(void)
{
physmap_configure(0x90000000, 0x02000000, 2, NULL);
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index 5330ad78c1bb..ac72f94c5b4d 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -201,7 +201,7 @@ int clear_master_aborts(void)
return 0;
}
-void __init ixp23xx_pci_preinit(void)
+static void __init ixp23xx_pci_common_init(void)
{
#ifdef __ARMEB__
*IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */
@@ -219,7 +219,18 @@ void __init ixp23xx_pci_preinit(void)
*IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
} else {
*IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
+
+ /*
+ * Enable coherency on A2 silicon.
+ */
+ if (arch_is_coherent())
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
}
+}
+
+void __init ixp23xx_pci_preinit(void)
+{
+ ixp23xx_pci_common_init();
hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
"PCI config cycle to non-existent device");
@@ -273,3 +284,8 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
return 1;
}
+
+void ixp23xx_pci_slave_init(void)
+{
+ ixp23xx_pci_common_init();
+}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index a0888e160e3b..00b761ff0f9c 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -91,7 +91,7 @@ static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
/*
* IRQ -> GPIO mapping table
*/
-static char irq2gpio[32] = {
+static signed char irq2gpio[32] = {
-1, -1, -1, -1, -1, -1, 0, 1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 2, 3, 4, 5, 6,
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 86a0f0d14345..f8d716ccc1df 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -69,12 +69,6 @@ config MACH_VOICEBLUE
Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
such a board.
-config MACH_NETSTAR
- bool "NetStar"
- depends on ARCH_OMAP1 && ARCH_OMAP15XX
- help
- Support for NetStar PBX. Say Y here if you have such a board.
-
config MACH_OMAP_PALMTE
bool "Palm Tungsten E"
depends on ARCH_OMAP1 && ARCH_OMAP15XX
@@ -85,6 +79,20 @@ config MACH_OMAP_PALMTE
informations.
Say Y here if you have such a PDA, say NO otherwise.
+config MACH_NOKIA770
+ bool "Nokia 770"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ help
+ Support for the Nokia 770 Internet Tablet. Say Y here if you
+ have such a device.
+
+config MACH_AMS_DELTA
+ bool "Amstrad E3 (Delta)"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Amstrad E3 (codename Delta) videophone. Say Y here
+ if you have such a device.
+
config MACH_OMAP_GENERIC
bool "Generic OMAP board"
depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index b0b00156faae..9ea719550ad3 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,13 @@
#
# Common support
-obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o
+obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+
+obj-$(CONFIG_OMAP_MPU_TIMER) += time.o
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
led-y := leds.o
# Specific board support
@@ -14,8 +20,9 @@ obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
-obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
+obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
+obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o
ifeq ($(CONFIG_ARCH_OMAP15XX),y)
# Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
new file mode 100644
index 000000000000..6178f046f128
--- /dev/null
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-omap1/board-ams-delta.c
+ *
+ * Modified from board-generic.c
+ *
+ * Board specific inits for the Amstrad E3 (codename Delta) videophone
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board-ams-delta.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+
+static u8 ams_delta_latch1_reg;
+static u16 ams_delta_latch2_reg;
+
+void ams_delta_latch1_write(u8 mask, u8 value)
+{
+ ams_delta_latch1_reg &= ~mask;
+ ams_delta_latch1_reg |= value;
+ *(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg;
+}
+
+void ams_delta_latch2_write(u16 mask, u16 value)
+{
+ ams_delta_latch2_reg &= ~mask;
+ ams_delta_latch2_reg |= value;
+ *(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
+}
+
+static void __init ams_delta_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static struct map_desc ams_delta_io_desc[] __initdata = {
+ // AMS_DELTA_LATCH1
+ {
+ .virtual = AMS_DELTA_LATCH1_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_LATCH1_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ },
+ // AMS_DELTA_LATCH2
+ {
+ .virtual = AMS_DELTA_LATCH2_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_LATCH2_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ },
+ // AMS_DELTA_MODEM
+ {
+ .virtual = AMS_DELTA_MODEM_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_MODEM_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ }
+};
+
+static struct omap_uart_config ams_delta_uart_config __initdata = {
+ .enabled_uarts = 1,
+};
+
+static struct omap_board_config_kernel ams_delta_config[] = {
+ { OMAP_TAG_UART, &ams_delta_uart_config },
+};
+
+static void __init ams_delta_init(void)
+{
+ iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+
+ omap_board_config = ams_delta_config;
+ omap_board_config_size = ARRAY_SIZE(ams_delta_config);
+ omap_serial_init();
+
+ /* Clear latch2 (NAND, LCD, modem enable) */
+ ams_delta_latch2_write(~0, 0);
+}
+
+static void __init ams_delta_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
+ /* Maintainer: Jonathan McDowell <noodles@earth.li> */
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = ams_delta_map_io,
+ .init_irq = ams_delta_init_irq,
+ .init_machine = ams_delta_init,
+ .timer = &omap_timer,
+MACHINE_END
+
+EXPORT_SYMBOL(ams_delta_latch1_write);
+EXPORT_SYMBOL(ams_delta_latch2_write);
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index a177e78b2b87..33d01adab1ed 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -88,7 +88,7 @@ static struct omap_board_config_kernel generic_config[] = {
static void __init omap_generic_init(void)
{
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
generic_config[0].data = &generic1510_usb_config;
}
#endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 89f0cc74a519..cd3a06dfc0a8 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -24,7 +24,9 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -35,12 +37,55 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
extern int omap_gpio_init(void);
-static struct mtd_partition h2_partitions[] = {
+static int h2_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F10),
+ KEY(0, 4, KEY_F5),
+ KEY(0, 5, KEY_9),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_2),
+ KEY(1, 3, KEY_F9),
+ KEY(1, 4, KEY_F7),
+ KEY(1, 5, KEY_0),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(2, 3, KEY_F2),
+ KEY(2, 4, KEY_F6),
+ KEY(2, 5, KEY_HOME),
+ KEY(3, 0, KEY_8),
+ KEY(3, 1, KEY_5),
+ KEY(3, 2, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(3, 4, KEY_F8),
+ KEY(3, 5, KEY_END),
+ KEY(4, 0, KEY_7),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_F11),
+ KEY(4, 3, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(4, 5, KEY_ESC),
+ KEY(5, 0, KEY_F13),
+ KEY(5, 1, KEY_F14),
+ KEY(5, 2, KEY_F15),
+ KEY(5, 3, KEY_F16),
+ KEY(5, 4, KEY_SLEEP),
+ 0
+};
+
+static struct mtd_partition h2_nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -71,26 +116,26 @@ static struct mtd_partition h2_partitions[] = {
}
};
-static struct flash_platform_data h2_flash_data = {
+static struct flash_platform_data h2_nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = h2_partitions,
- .nr_parts = ARRAY_SIZE(h2_partitions),
+ .parts = h2_nor_partitions,
+ .nr_parts = ARRAY_SIZE(h2_nor_partitions),
};
-static struct resource h2_flash_resource = {
+static struct resource h2_nor_resource = {
/* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
-static struct platform_device h2_flash_device = {
+static struct platform_device h2_nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &h2_flash_data,
+ .platform_data = &h2_nor_data,
},
.num_resources = 1,
- .resource = &h2_flash_resource,
+ .resource = &h2_nor_resource,
};
static struct resource h2_smc91x_resources[] = {
@@ -113,9 +158,119 @@ static struct platform_device h2_smc91x_device = {
.resource = h2_smc91x_resources,
};
+static struct resource h2_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data h2_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = h2_keymap,
+ .rep = 1,
+};
+
+static struct platform_device h2_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h2_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(h2_kp_resources),
+ .resource = h2_kp_resources,
+};
+
+#define H2_IRDA_FIRSEL_GPIO_PIN 17
+
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+static int h2_transceiver_mode(struct device *dev, int state)
+{
+ if (state & IR_SIRMODE)
+ omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+ else /* MIR/FIR */
+ omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1);
+
+ return 0;
+}
+#endif
+
+static struct omap_irda_config h2_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource h2_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct platform_device h2_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_irda_data,
+ },
+ .num_resources = ARRAY_SIZE(h2_irda_resources),
+ .resource = h2_irda_resources,
+};
+
+static struct platform_device h2_lcd_device = {
+ .name = "lcd_h2",
+ .id = -1,
+};
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(15),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+ .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+ //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "H2 TSC2101",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // tsc2101_configure,
+ .codec_set_samplerate = NULL, // tsc2101_set_samplerate,
+ .codec_clock_setup = NULL, // tsc2101_clock_setup,
+ .codec_clock_on = NULL, // tsc2101_clock_on,
+ .codec_clock_off = NULL, // tsc2101_clock_off,
+ .get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h2_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
static struct platform_device *h2_devices[] __initdata = {
- &h2_flash_device,
+ &h2_nor_device,
&h2_smc91x_device,
+ &h2_irda_device,
+ &h2_kp_device,
+ &h2_lcd_device,
+ &h2_mcbsp1_device,
};
static void __init h2_init_smc91x(void)
@@ -164,7 +319,6 @@ static struct omap_uart_config h2_uart_config __initdata = {
};
static struct omap_lcd_config h2_lcd_config __initdata = {
- .panel_name = "h2",
.ctrl_name = "internal",
};
@@ -177,16 +331,34 @@ static struct omap_board_config_kernel h2_config[] = {
static void __init h2_init(void)
{
- /* NOTE: revC boards support NAND-boot, which can put NOR on CS2B
- * and NAND (either 16bit or 8bit) on CS3.
+ /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
+ * to address 0 by a dip switch), NAND on CS2B. The NAND driver will
+ * notice whether a NAND chip is enabled at probe time.
+ *
+ * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
+ * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3. Try
+ * detecting that in code here, to avoid probing every possible flash
+ * configuration...
*/
- h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
- h2_flash_resource.end += SZ_32M - 1;
+ h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+ h2_nor_resource.end += SZ_32M - 1;
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
/* MMC: card detect and WP */
// omap_cfg_reg(U19_ARMIO1); /* CD */
omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */
+ /* Irda */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+ omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);
+ if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) {
+ omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+ h2_irda_data.transceiver_mode = h2_transceiver_mode;
+ }
+#endif
+
platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
omap_board_config = h2_config;
omap_board_config_size = ARRAY_SIZE(h2_config);
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index d9f386265996..4b8d0ec73cb7 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -21,8 +21,11 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
+#include <linux/workqueue.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -33,15 +36,59 @@
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
#include <asm/arch/irqs.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/dma.h>
#include <asm/arch/common.h>
extern int omap_gpio_init(void);
-static struct mtd_partition h3_partitions[] = {
+static int h3_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F10),
+ KEY(0, 4, KEY_F5),
+ KEY(0, 5, KEY_9),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_2),
+ KEY(1, 3, KEY_F9),
+ KEY(1, 4, KEY_F7),
+ KEY(1, 5, KEY_0),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(2, 3, KEY_F2),
+ KEY(2, 4, KEY_F6),
+ KEY(2, 5, KEY_HOME),
+ KEY(3, 0, KEY_8),
+ KEY(3, 1, KEY_5),
+ KEY(3, 2, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(3, 4, KEY_F8),
+ KEY(3, 5, KEY_END),
+ KEY(4, 0, KEY_7),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_F11),
+ KEY(4, 3, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(4, 5, KEY_ESC),
+ KEY(5, 0, KEY_F13),
+ KEY(5, 1, KEY_F14),
+ KEY(5, 2, KEY_F15),
+ KEY(5, 3, KEY_F16),
+ KEY(5, 4, KEY_SLEEP),
+ 0
+};
+
+
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -72,26 +119,80 @@ static struct mtd_partition h3_partitions[] = {
}
};
-static struct flash_platform_data h3_flash_data = {
+static struct flash_platform_data nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = h3_partitions,
- .nr_parts = ARRAY_SIZE(h3_partitions),
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
};
-static struct resource h3_flash_resource = {
+static struct resource nor_resource = {
/* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
-static struct platform_device flash_device = {
+static struct platform_device nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &h3_flash_data,
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static struct mtd_partition nand_partitions[] = {
+#if 0
+ /* REVISIT: enable these partitions if you make NAND BOOT work */
+ {
+ .name = "xloader",
+ .offset = 0,
+ .size = 64 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "bootloader",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 192 * 1024,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * SZ_1M,
+ },
+#endif
+ {
+ .name = "filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ },
+};
+
+/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */
+static struct nand_platform_data nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .parts = nand_partitions,
+ .nr_parts = ARRAY_SIZE(nand_partitions),
+};
+
+static struct resource nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
},
.num_resources = 1,
- .resource = &h3_flash_resource,
+ .resource = &nand_resource,
};
static struct resource smc91x_resources[] = {
@@ -138,10 +239,136 @@ static struct platform_device intlat_device = {
.resource = intlat_resources,
};
+static struct resource h3_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data h3_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = h3_keymap,
+ .rep = 1,
+};
+
+static struct platform_device h3_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h3_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(h3_kp_resources),
+ .resource = h3_kp_resources,
+};
+
+
+/* Select between the IrDA and aGPS module
+ */
+static int h3_select_irda(struct device *dev, int state)
+{
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x26))) {
+ printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+ return err;
+ }
+
+ /* 'P6' enable/disable IRDA_TX and IRDA_RX */
+ if (state & IR_SEL) { /* IrDA */
+ if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
+ printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+ return err;
+ }
+ } else {
+ if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
+ printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+ return err;
+ }
+ }
+ return err;
+}
+
+static void set_trans_mode(void *data)
+{
+ int *mode = data;
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ }
+
+ expa &= ~0x03;
+
+ if (*mode & IR_SIRMODE) {
+ expa |= 0x01;
+ } else { /* MIR/FIR */
+ expa |= 0x03;
+ }
+
+ if ((err = write_gpio_expa(expa, 0x27)) != 0) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ }
+}
+
+static int h3_transceiver_mode(struct device *dev, int mode)
+{
+ struct omap_irda_config *irda_config = dev->platform_data;
+
+ cancel_delayed_work(&irda_config->gpio_expa);
+ PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+ schedule_work(&irda_config->gpio_expa);
+
+ return 0;
+}
+
+static struct omap_irda_config h3_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .transceiver_mode = h3_transceiver_mode,
+ .select_irda = h3_select_irda,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource h3_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device h3_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h3_irda_data,
+ },
+ .num_resources = ARRAY_SIZE(h3_irda_resources),
+ .resource = h3_irda_resources,
+};
+
+static struct platform_device h3_lcd_device = {
+ .name = "lcd_h3",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
- &flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
&intlat_device,
+ &h3_irda_device,
+ &h3_kp_device,
+ &h3_lcd_device,
};
static struct omap_usb_config h3_usb_config __initdata = {
@@ -171,7 +398,6 @@ static struct omap_uart_config h3_uart_config __initdata = {
};
static struct omap_lcd_config h3_lcd_config __initdata = {
- .panel_name = "h3",
.ctrl_name = "internal",
};
@@ -182,11 +408,36 @@ static struct omap_board_config_kernel h3_config[] = {
{ OMAP_TAG_LCD, &h3_lcd_config },
};
+#define H3_NAND_RB_GPIO_PIN 10
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+}
+
static void __init h3_init(void)
{
- h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys();
- h3_flash_resource.end += OMAP_CS3_SIZE - 1;
- (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
+ * to address 0 by a dip switch), NAND on CS2B. The NAND driver will
+ * notice whether a NAND chip is enabled at probe time.
+ *
+ * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
+ * (which on H2 may be 16bit) on CS3. Try detecting that in code here,
+ * to avoid probing every possible flash configuration...
+ */
+ nor_resource.end = nor_resource.start = omap_cs3_phys();
+ nor_resource.end += SZ_32M - 1;
+
+ nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
+ nand_resource.end += SZ_4K - 1;
+ if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN)))
+ nand_data.dev_ready = nand_dev_ready;
+
+ /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+ /* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+ omap_cfg_reg(V2_1710_GPIO10);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
omap_board_config = h3_config;
omap_board_config_size = ARRAY_SIZE(h3_config);
omap_serial_init();
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index a04e4332915e..e90c137a4cf3 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -34,8 +35,22 @@
#include <asm/arch/gpio.h>
#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+static int innovator_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 3, KEY_DOWN),
+ KEY(1, 1, KEY_F2),
+ KEY(1, 2, KEY_RIGHT),
+ KEY(2, 0, KEY_F3),
+ KEY(2, 1, KEY_F4),
+ KEY(2, 2, KEY_UP),
+ KEY(3, 2, KEY_ENTER),
+ KEY(3, 3, KEY_LEFT),
+ 0
+};
+
static struct mtd_partition innovator_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -97,6 +112,31 @@ static struct platform_device innovator_flash_device = {
.resource = &innovator_flash_resource,
};
+static struct resource innovator_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data innovator_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = innovator_keymap,
+};
+
+static struct platform_device innovator_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &innovator_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(innovator_kp_resources),
+ .resource = innovator_kp_resources,
+};
+
+
#ifdef CONFIG_ARCH_OMAP15XX
/* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -129,9 +169,16 @@ static struct platform_device innovator1510_smc91x_device = {
.resource = innovator1510_smc91x_resources,
};
+static struct platform_device innovator1510_lcd_device = {
+ .name = "lcd_inn1510",
+ .id = -1,
+};
+
static struct platform_device *innovator1510_devices[] __initdata = {
&innovator_flash_device,
&innovator1510_smc91x_device,
+ &innovator_kp_device,
+ &innovator1510_lcd_device,
};
#endif /* CONFIG_ARCH_OMAP15XX */
@@ -158,9 +205,16 @@ static struct platform_device innovator1610_smc91x_device = {
.resource = innovator1610_smc91x_resources,
};
+static struct platform_device innovator1610_lcd_device = {
+ .name = "inn1610_lcd",
+ .id = -1,
+};
+
static struct platform_device *innovator1610_devices[] __initdata = {
&innovator_flash_device,
&innovator1610_smc91x_device,
+ &innovator_kp_device,
+ &innovator1610_lcd_device,
};
#endif /* CONFIG_ARCH_OMAP16XX */
@@ -206,7 +260,6 @@ static struct omap_usb_config innovator1510_usb_config __initdata = {
};
static struct omap_lcd_config innovator1510_lcd_config __initdata = {
- .panel_name = "inn1510",
.ctrl_name = "internal",
};
#endif
@@ -228,7 +281,6 @@ static struct omap_usb_config h2_usb_config __initdata = {
};
static struct omap_lcd_config innovator1610_lcd_config __initdata = {
- .panel_name = "inn1610",
.ctrl_name = "internal",
};
#endif
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
deleted file mode 100644
index 7520e602d7a2..000000000000
--- a/arch/arm/mach-omap1/board-netstar.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Modified from board-generic.c
- *
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Code for Netstar OMAP board.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/usb.h>
-#include <asm/arch/common.h>
-
-extern void __init omap_init_time(void);
-extern int omap_gpio_init(void);
-
-static struct resource netstar_smc91x_resources[] = {
- [0] = {
- .start = OMAP_CS1_PHYS + 0x300,
- .end = OMAP_CS1_PHYS + 0x300 + 16,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = OMAP_GPIO_IRQ(8),
- .end = OMAP_GPIO_IRQ(8),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netstar_smc91x_device = {
- .name = "smc91x",
- .id = 0,
- .num_resources = ARRAY_SIZE(netstar_smc91x_resources),
- .resource = netstar_smc91x_resources,
-};
-
-static struct platform_device *netstar_devices[] __initdata = {
- &netstar_smc91x_device,
-};
-
-static struct omap_uart_config netstar_uart_config __initdata = {
- .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
-};
-
-static struct omap_board_config_kernel netstar_config[] = {
- { OMAP_TAG_UART, &netstar_uart_config },
-};
-
-static void __init netstar_init_irq(void)
-{
- omap1_init_common_hw();
- omap_init_irq();
- omap_gpio_init();
-}
-
-static void __init netstar_init(void)
-{
- /* green LED */
- omap_request_gpio(4);
- omap_set_gpio_direction(4, 0);
- /* smc91x reset */
- omap_request_gpio(7);
- omap_set_gpio_direction(7, 0);
- omap_set_gpio_dataout(7, 1);
- udelay(2); /* wait at least 100ns */
- omap_set_gpio_dataout(7, 0);
- mdelay(50); /* 50ms until PHY ready */
- /* smc91x interrupt pin */
- omap_request_gpio(8);
-
- omap_request_gpio(12);
- omap_request_gpio(13);
- omap_request_gpio(14);
- omap_request_gpio(15);
- set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING);
-
- platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
-
- /* Switch on green LED */
- omap_set_gpio_dataout(4, 0);
- /* Switch off red LED */
- omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
- omap_writeb(0x80, OMAP_LPG1_LCR);
-
- omap_board_config = netstar_config;
- omap_board_config_size = ARRAY_SIZE(netstar_config);
- omap_serial_init();
-}
-
-static void __init netstar_map_io(void)
-{
- omap1_map_common_io();
-}
-
-#define MACHINE_PANICED 1
-#define MACHINE_REBOOTING 2
-#define MACHINE_REBOOT 4
-static unsigned long machine_state;
-
-static int panic_event(struct notifier_block *this, unsigned long event,
- void *ptr)
-{
- if (test_and_set_bit(MACHINE_PANICED, &machine_state))
- return NOTIFY_DONE;
-
- /* Switch off green LED */
- omap_set_gpio_dataout(4, 1);
- /* Flash red LED */
- omap_writeb(0x78, OMAP_LPG1_LCR);
- omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
- .notifier_call = panic_event,
-};
-
-static int __init netstar_late_init(void)
-{
- /* TODO: Setup front panel switch here */
-
- /* Setup panic notifier */
- atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
-
- return 0;
-}
-
-postcore_initcall(netstar_late_init);
-
-MACHINE_START(NETSTAR, "NetStar OMAP5910")
- /* Maintainer: Ladislav Michl <michl@2n.cz> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
- .boot_params = 0x10000100,
- .map_io = netstar_map_io,
- .init_irq = netstar_init_irq,
- .init_machine = netstar_init,
- .timer = &omap_timer,
-MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
new file mode 100644
index 000000000000..02b980d77b12
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -0,0 +1,268 @@
+/*
+ * linux/arch/arm/mach-omap1/board-nokia770.c
+ *
+ * Modified from board-generic.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/aic23.h>
+#include <asm/arch/gpio.h>
+
+static void __init omap_nokia770_init_irq(void)
+{
+ /* On Nokia 770, the SleepX signal is masked with an
+ * MPUIO line by default. It has to be unmasked for it
+ * to become functional */
+
+ /* SleepX mask direction */
+ omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+ /* Unmask SleepX signal */
+ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static int nokia770_keymap[] = {
+ KEY(0, 1, GROUP_0 | KEY_UP),
+ KEY(0, 2, GROUP_1 | KEY_F5),
+ KEY(1, 0, GROUP_0 | KEY_LEFT),
+ KEY(1, 1, GROUP_0 | KEY_ENTER),
+ KEY(1, 2, GROUP_0 | KEY_RIGHT),
+ KEY(2, 0, GROUP_1 | KEY_ESC),
+ KEY(2, 1, GROUP_0 | KEY_DOWN),
+ KEY(2, 2, GROUP_1 | KEY_F4),
+ KEY(3, 0, GROUP_2 | KEY_F7),
+ KEY(3, 1, GROUP_2 | KEY_F8),
+ KEY(3, 2, GROUP_2 | KEY_F6),
+ 0
+};
+
+static struct resource nokia770_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data nokia770_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = nokia770_keymap
+};
+
+static struct platform_device nokia770_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &nokia770_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(nokia770_kp_resources),
+ .resource = nokia770_kp_resources,
+};
+
+static struct platform_device *nokia770_devices[] __initdata = {
+ &nokia770_kp_device,
+};
+
+static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
+ .x_max = 0x0fff,
+ .y_max = 0x0fff,
+ .x_plate_ohms = 180,
+ .pressure_max = 255,
+ .debounce_max = 10,
+ .debounce_tol = 3,
+};
+
+static struct spi_board_info nokia770_spi_board_info[] __initdata = {
+ [0] = {
+ .modalias = "lcd_lph8923",
+ .bus_num = 2,
+ .chip_select = 3,
+ .max_speed_hz = 12000000,
+ },
+ [1] = {
+ .modalias = "ads7846",
+ .bus_num = 2,
+ .chip_select = 0,
+ .max_speed_hz = 2500000,
+ .irq = OMAP_GPIO_IRQ(15),
+ .platform_data = &nokia770_ads7846_platform_data,
+ },
+};
+
+
+/* assume no Mini-AB port */
+
+static struct omap_usb_config nokia770_usb_config __initdata = {
+ .otg = 1,
+ .register_host = 1,
+ .register_dev = 1,
+ .hmc_mode = 16,
+ .pins[0] = 6,
+};
+
+static struct omap_mmc_config nokia770_mmc_config __initdata = {
+ .mmc[0] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+ .mmc[1] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_board_config_kernel nokia770_config[] = {
+ { OMAP_TAG_USB, NULL },
+ { OMAP_TAG_MMC, &nokia770_mmc_config },
+};
+
+/*
+ * audio power control
+ */
+#define HEADPHONE_GPIO 14
+#define AMPLIFIER_CTRL_GPIO 58
+
+static struct clk *dspxor_ck;
+static DECLARE_MUTEX(audio_pwr_sem);
+/*
+ * audio_pwr_state
+ * +--+-------------------------+---------------------------------------+
+ * |-1|down |power-up request -> 0 |
+ * +--+-------------------------+---------------------------------------+
+ * | 0|up |power-down(1) request -> 1 |
+ * | | |power-down(2) request -> (ignore) |
+ * +--+-------------------------+---------------------------------------+
+ * | 1|up, |power-up request -> 0 |
+ * | |received down(1) request |power-down(2) request -> -1 |
+ * +--+-------------------------+---------------------------------------+
+ */
+static int audio_pwr_state = -1;
+
+/*
+ * audio_pwr_up / down should be called under audio_pwr_sem
+ */
+static void nokia770_audio_pwr_up(void)
+{
+ clk_enable(dspxor_ck);
+
+ /* Turn on codec */
+ tlv320aic23_power_up();
+
+ if (omap_get_gpio_datain(HEADPHONE_GPIO))
+ /* HP not connected, turn on amplifier */
+ omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1);
+ else
+ /* HP connected, do not turn on amplifier */
+ printk("HP connected\n");
+}
+
+static void codec_delayed_power_down(void *arg)
+{
+ down(&audio_pwr_sem);
+ if (audio_pwr_state == -1)
+ tlv320aic23_power_down();
+ clk_disable(dspxor_ck);
+ up(&audio_pwr_sem);
+}
+
+static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL);
+
+static void nokia770_audio_pwr_down(void)
+{
+ /* Turn off amplifier */
+ omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0);
+
+ /* Turn off codec: schedule delayed work */
+ schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */
+}
+
+void nokia770_audio_pwr_up_request(int stage)
+{
+ down(&audio_pwr_sem);
+ if (audio_pwr_state == -1)
+ nokia770_audio_pwr_up();
+ /* force audio_pwr_state = 0, even if it was 1. */
+ audio_pwr_state = 0;
+ up(&audio_pwr_sem);
+}
+
+void nokia770_audio_pwr_down_request(int stage)
+{
+ down(&audio_pwr_sem);
+ switch (stage) {
+ case 1:
+ if (audio_pwr_state == 0)
+ audio_pwr_state = 1;
+ break;
+ case 2:
+ if (audio_pwr_state == 1) {
+ nokia770_audio_pwr_down();
+ audio_pwr_state = -1;
+ }
+ break;
+ }
+ up(&audio_pwr_sem);
+}
+
+static void __init omap_nokia770_init(void)
+{
+ nokia770_config[0].data = &nokia770_usb_config;
+
+ platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
+ spi_register_board_info(nokia770_spi_board_info,
+ ARRAY_SIZE(nokia770_spi_board_info));
+ omap_board_config = nokia770_config;
+ omap_board_config_size = ARRAY_SIZE(nokia770_config);
+ omap_serial_init();
+ omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request;
+ omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request;
+ dspxor_ck = clk_get(0, "dspxor_ck");
+}
+
+static void __init omap_nokia770_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(NOKIA770, "Nokia 770")
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = omap_nokia770_map_io,
+ .init_irq = omap_nokia770_init_irq,
+ .init_machine = omap_nokia770_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 543fa136106d..1160093e8ef6 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -33,6 +33,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -44,7 +45,24 @@
#include <asm/arch/usb.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
+
+static int osk_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 3, KEY_UP),
+ KEY(1, 1, KEY_LEFTCTRL),
+ KEY(1, 2, KEY_LEFT),
+ KEY(2, 0, KEY_SPACE),
+ KEY(2, 1, KEY_ESC),
+ KEY(2, 2, KEY_DOWN),
+ KEY(3, 2, KEY_ENTER),
+ KEY(3, 3, KEY_RIGHT),
+ 0
+};
+
static struct mtd_partition osk_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
@@ -133,9 +151,69 @@ static struct platform_device osk5912_cf_device = {
.resource = osk5912_cf_resources,
};
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+ /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
+ .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "OSK AIC23",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // aic23_configure,
+ .codec_set_samplerate = NULL, // aic23_set_samplerate,
+ .codec_clock_setup = NULL, // aic23_clock_setup,
+ .codec_clock_on = NULL, // aic23_clock_on,
+ .codec_clock_off = NULL, // aic23_clock_off,
+ .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+};
+
static struct platform_device osk5912_mcbsp1_device = {
- .name = "omap_mcbsp",
- .id = 1,
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
+static struct resource osk5912_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data osk_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = osk_keymap,
+};
+
+static struct platform_device osk5912_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &osk_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(osk5912_kp_resources),
+ .resource = osk5912_kp_resources,
+};
+
+static struct platform_device osk5912_lcd_device = {
+ .name = "lcd_osk",
+ .id = -1,
};
static struct platform_device *osk5912_devices[] __initdata = {
@@ -143,6 +221,8 @@ static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_smc91x_device,
&osk5912_cf_device,
&osk5912_mcbsp1_device,
+ &osk5912_kp_device,
+ &osk5912_lcd_device,
};
static void __init osk_init_smc91x(void)
@@ -197,7 +277,6 @@ static struct omap_uart_config osk_uart_config __initdata = {
};
static struct omap_lcd_config osk_lcd_config __initdata = {
- .panel_name = "osk",
.ctrl_name = "internal",
};
@@ -255,8 +334,18 @@ static void __init osk_mistral_init(void)
static void __init osk_mistral_init(void) { }
#endif
+#define EMIFS_CS3_VAL (0x88013141)
+
static void __init osk_init(void)
{
+ /* Workaround for wrong CS3 (NOR flash) timing
+ * There are some U-Boot versions out there which configure
+ * wrong CS3 memory timings. This mainly leads to CRC
+ * or similiar errors if you use NOR flash (e.g. with JFFS2)
+ */
+ if (EMIFS_CCS(3) != EMIFS_CS3_VAL)
+ EMIFS_CCS(3) = EMIFS_CS3_VAL;
+
osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys();
osk_flash_resource.end += SZ_32M - 1;
platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index e488f7236775..4bc8a62909b9 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -38,6 +38,15 @@ static void __init omap_generic_init_irq(void)
omap_init_irq();
}
+static struct platform_device palmte_lcd_device = {
+ .name = "lcd_palmte",
+ .id = -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &palmte_lcd_device,
+};
+
static struct omap_usb_config palmte_usb_config __initdata = {
.register_dev = 1,
.hmc_mode = 0,
@@ -55,7 +64,6 @@ static struct omap_mmc_config palmte_mmc_config __initdata = {
};
static struct omap_lcd_config palmte_lcd_config __initdata = {
- .panel_name = "palmte",
.ctrl_name = "internal",
};
@@ -69,6 +77,8 @@ static void __init omap_generic_init(void)
{
omap_board_config = palmte_config;
omap_board_config_size = ARRAY_SIZE(palmte_config);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
}
static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3913a3cc0ce6..64b45d8ae357 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -16,7 +16,9 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -28,9 +30,44 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
#include <asm/arch/board.h>
+static int p2_keymap[] = {
+ KEY(0,0,KEY_UP),
+ KEY(0,1,KEY_RIGHT),
+ KEY(0,2,KEY_LEFT),
+ KEY(0,3,KEY_DOWN),
+ KEY(0,4,KEY_CENTER),
+ KEY(0,5,KEY_0_5),
+ KEY(1,0,KEY_SOFT2),
+ KEY(1,1,KEY_SEND),
+ KEY(1,2,KEY_END),
+ KEY(1,3,KEY_VOLUMEDOWN),
+ KEY(1,4,KEY_VOLUMEUP),
+ KEY(1,5,KEY_RECORD),
+ KEY(2,0,KEY_SOFT1),
+ KEY(2,1,KEY_3),
+ KEY(2,2,KEY_6),
+ KEY(2,3,KEY_9),
+ KEY(2,4,KEY_SHARP),
+ KEY(2,5,KEY_2_5),
+ KEY(3,0,KEY_BACK),
+ KEY(3,1,KEY_2),
+ KEY(3,2,KEY_5),
+ KEY(3,3,KEY_8),
+ KEY(3,4,KEY_0),
+ KEY(3,5,KEY_HEADSETHOOK),
+ KEY(4,0,KEY_HOME),
+ KEY(4,1,KEY_1),
+ KEY(4,2,KEY_4),
+ KEY(4,3,KEY_7),
+ KEY(4,4,KEY_STAR),
+ KEY(4,5,KEY_POWER),
+ 0
+};
+
static struct resource smc91x_resources[] = {
[0] = {
.start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
@@ -44,7 +81,7 @@ static struct resource smc91x_resources[] = {
},
};
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -75,27 +112,47 @@ static struct mtd_partition p2_partitions[] = {
},
};
-static struct flash_platform_data p2_flash_data = {
+static struct flash_platform_data nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = p2_partitions,
- .nr_parts = ARRAY_SIZE(p2_partitions),
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
};
-static struct resource p2_flash_resource = {
+static struct resource nor_resource = {
.start = OMAP_CS0_PHYS,
.end = OMAP_CS0_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
};
-static struct platform_device p2_flash_device = {
+static struct platform_device nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &p2_flash_data,
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+ .start = OMAP_CS3_PHYS,
+ .end = OMAP_CS3_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
},
.num_resources = 1,
- .resource = &p2_flash_resource,
+ .resource = &nand_resource,
};
static struct platform_device smc91x_device = {
@@ -105,17 +162,55 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+static struct resource kp_resources[] = {
+ [0] = {
+ .start = INT_730_MPUIO_KEYPAD,
+ .end = INT_730_MPUIO_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = p2_keymap,
+};
+
+static struct platform_device kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &kp_data,
+ },
+ .num_resources = ARRAY_SIZE(kp_resources),
+ .resource = kp_resources,
+};
+
+static struct platform_device lcd_device = {
+ .name = "lcd_p2",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
- &p2_flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
+ &kp_device,
+ &lcd_device,
};
+#define P2_NAND_RB_GPIO_PIN 62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
static struct omap_uart_config perseus2_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1)),
};
static struct omap_lcd_config perseus2_lcd_config __initdata = {
- .panel_name = "p2",
.ctrl_name = "internal",
};
@@ -126,7 +221,13 @@ static struct omap_board_config_kernel perseus2_config[] = {
static void __init omap_perseus2_init(void)
{
- (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+ nand_data.dev_ready = nand_dev_ready;
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
omap_board_config = perseus2_config;
omap_board_config_size = ARRAY_SIZE(perseus2_config);
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 52e4a9d69642..447a586eb334 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -155,9 +155,9 @@ static struct omap_uart_config voiceblue_uart_config __initdata = {
};
static struct omap_board_config_kernel voiceblue_config[] = {
- { OMAP_TAG_USB, &voiceblue_usb_config },
- { OMAP_TAG_MMC, &voiceblue_mmc_config },
- { OMAP_TAG_UART, &voiceblue_uart_config },
+ { OMAP_TAG_USB, &voiceblue_usb_config },
+ { OMAP_TAG_MMC, &voiceblue_mmc_config },
+ { OMAP_TAG_UART, &voiceblue_uart_config },
};
static void __init voiceblue_init_irq(void)
@@ -235,7 +235,7 @@ static struct notifier_block panic_block = {
static int __init voiceblue_setup(void)
{
/* Setup panic notifier */
- atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 75110ba10424..619db18144ea 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -345,7 +345,7 @@ static unsigned calc_ext_dsor(unsigned long rate)
*/
for (dsor = 2; dsor < 96; ++dsor) {
if ((dsor & 1) && dsor > 8)
- continue;
+ continue;
if (rate >= 96000000 / dsor)
break;
}
@@ -687,6 +687,11 @@ int __init omap1_clk_init(void)
clk_register(*clkp);
continue;
}
+
+ if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) {
+ clk_register(*clkp);
+ continue;
+ }
}
info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
@@ -784,7 +789,7 @@ int __init omap1_clk_init(void)
clk_enable(&armxor_ck.clk);
clk_enable(&armtim_ck.clk); /* This should be done by timer code */
- if (cpu_is_omap1510())
+ if (cpu_is_omap15xx())
clk_enable(&arm_gpio_ck);
return 0;
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 4f18d1b94449..b7c68819c4e7 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -151,7 +151,7 @@ static struct clk ck_ref = {
.name = "ck_ref",
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -160,7 +160,7 @@ static struct clk ck_dpll1 = {
.name = "ck_dpll1",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_PROPAGATES | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -183,7 +183,8 @@ static struct clk arm_ck = {
.name = "arm_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
+ ALWAYS_ENABLED,
.rate_offset = CKCTL_ARMDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.enable = &omap1_clk_enable_generic,
@@ -195,7 +196,8 @@ static struct arm_idlect1_clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_CKCTL | CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | RATE_CKCTL |
+ CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_PERCK,
.rate_offset = CKCTL_PERDIV_OFFSET,
@@ -209,7 +211,7 @@ static struct arm_idlect1_clk armper_ck = {
static struct clk arm_gpio_ck = {
.name = "arm_gpio_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_GPIOCK,
.recalc = &followparent_recalc,
@@ -222,7 +224,7 @@ static struct arm_idlect1_clk armxor_ck = {
.name = "armxor_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_XORPCK,
.recalc = &followparent_recalc,
@@ -237,7 +239,7 @@ static struct arm_idlect1_clk armtim_ck = {
.name = "armtim_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_TIMCK,
.recalc = &followparent_recalc,
@@ -252,7 +254,7 @@ static struct arm_idlect1_clk armwdt_ck = {
.name = "armwdt_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_WDTCK,
.recalc = &omap1_watchdog_recalc,
@@ -344,9 +346,9 @@ static struct arm_idlect1_clk tc_ck = {
.name = "tc_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IN_OMAP730 | RATE_CKCTL |
- RATE_PROPAGATES | ALWAYS_ENABLED |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
+ RATE_CKCTL | RATE_PROPAGATES |
+ ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.enable = &omap1_clk_enable_generic,
@@ -358,7 +360,8 @@ static struct arm_idlect1_clk tc_ck = {
static struct clk arminth_ck1510 = {
.name = "arminth_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ALWAYS_ENABLED,
.recalc = &followparent_recalc,
/* Note: On 1510 the frequency follows TC_CK
*
@@ -372,7 +375,8 @@ static struct clk tipb_ck = {
/* No-idle controlled by "tc_ck" */
.name = "tibp_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ALWAYS_ENABLED,
.recalc = &followparent_recalc,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
@@ -417,7 +421,7 @@ static struct clk dma_ck = {
.name = "dma_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
@@ -437,7 +441,7 @@ static struct arm_idlect1_clk api_ck = {
.name = "api_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_APICK,
.recalc = &followparent_recalc,
@@ -451,7 +455,8 @@ static struct arm_idlect1_clk lb_ck = {
.clk = {
.name = "lb_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LBCK,
.recalc = &followparent_recalc,
@@ -495,8 +500,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = {
.clk = {
.name = "lcd_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | RATE_CKCTL |
- CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ RATE_CKCTL | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
@@ -512,8 +517,9 @@ static struct clk uart1_1510 = {
/* Direct from ULPD, no real parent */
.parent = &armper_ck.clk,
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
- ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ENABLE_REG_32BIT | ALWAYS_ENABLED |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 29, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -544,8 +550,8 @@ static struct clk uart2_ck = {
.parent = &armper_ck.clk,
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ENABLE_REG_32BIT | ALWAYS_ENABLED |
- CLOCK_NO_IDLE_PARENT,
+ CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
+ ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -559,8 +565,9 @@ static struct clk uart3_1510 = {
/* Direct from ULPD, no real parent */
.parent = &armper_ck.clk,
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
- ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ENABLE_REG_32BIT | ALWAYS_ENABLED |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 31, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -590,7 +597,7 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
/* Direct from ULPD, no parent */
.rate = 6000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_FIXED | ENABLE_REG_32BIT,
+ CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)ULPD_CLOCK_CTRL,
.enable_bit = USB_MCLK_EN_BIT,
.enable = &omap1_clk_enable_generic,
@@ -601,7 +608,7 @@ static struct clk usb_hhc_ck1510 = {
.name = "usb_hhc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
- .flags = CLOCK_IN_OMAP1510 |
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = USB_HOST_HHC_UHOST_EN,
@@ -637,7 +644,9 @@ static struct clk mclk_1510 = {
.name = "mclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
+ .enable_reg = (void __iomem *)SOFT_REQ_REG,
+ .enable_bit = 6,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -659,7 +668,7 @@ static struct clk bclk_1510 = {
.name = "bclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -678,12 +687,14 @@ static struct clk bclk_16xx = {
};
static struct clk mmc1_ck = {
- .name = "mmc1_ck",
+ .name = "mmc_ck",
+ .id = 1,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
.parent = &armper_ck.clk,
.rate = 48000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 23,
.enable = &omap1_clk_enable_generic,
@@ -691,7 +702,8 @@ static struct clk mmc1_ck = {
};
static struct clk mmc2_ck = {
- .name = "mmc2_ck",
+ .name = "mmc_ck",
+ .id = 2,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
.parent = &armper_ck.clk,
.rate = 48000000,
@@ -706,7 +718,7 @@ static struct clk mmc2_ck = {
static struct clk virtual_ck_mpu = {
.name = "mpu",
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- VIRTUAL_CLOCK | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
.parent = &arm_ck, /* Is smarter alias for */
.recalc = &followparent_recalc,
.set_rate = &omap1_select_table_rate,
@@ -715,6 +727,20 @@ static struct clk virtual_ck_mpu = {
.disable = &omap1_clk_disable_generic,
};
+/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
+remains active during MPU idle whenever this is enabled */
+static struct clk i2c_fck = {
+ .name = "i2c_fck",
+ .id = 1,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+ ALWAYS_ENABLED,
+ .parent = &armxor_ck.clk,
+ .recalc = &followparent_recalc,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
+};
+
static struct clk * onchip_clks[] = {
/* non-ULPD clocks */
&ck_ref,
@@ -763,6 +789,7 @@ static struct clk * onchip_clks[] = {
&mmc2_ck,
/* Virtual clocks */
&virtual_ck_mpu,
+ &i2c_fck,
};
#endif
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index ecbc47514adc..847329cafc5c 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -25,10 +25,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-extern void omap_nop_release(struct device *dev);
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
static u64 irda_dmamask = 0xffffffff;
@@ -37,7 +33,6 @@ static struct platform_device omap1610ir_device = {
.name = "omap1610-ir",
.id = -1,
.dev = {
- .release = omap_nop_release,
.dma_mask = &irda_dmamask,
},
};
@@ -84,9 +79,6 @@ static struct resource rtc_resources[] = {
static struct platform_device omap_rtc_device = {
.name = "omap_rtc",
.id = -1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(rtc_resources),
.resource = rtc_resources,
};
@@ -99,6 +91,42 @@ static void omap_init_rtc(void)
static inline void omap_init_rtc(void) {}
#endif
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP1_STI_BASE IO_ADDRESS(0xfffea000)
+#define OMAP1_STI_CHANNEL_BASE (OMAP1_STI_BASE + 0x400)
+
+static struct resource sti_resources[] = {
+ {
+ .start = OMAP1_STI_BASE,
+ .end = OMAP1_STI_BASE + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP1_STI_CHANNEL_BASE,
+ .end = OMAP1_STI_CHANNEL_BASE + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_STI,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device sti_device = {
+ .name = "sti",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(sti_resources),
+ .resource = sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+ platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
/*-------------------------------------------------------------------------*/
@@ -129,6 +157,7 @@ static int __init omap1_init_devices(void)
*/
omap_init_irda();
omap_init_rtc();
+ omap_init_sti();
return 0;
}
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 82d556be79c5..be3a2a4ee2b8 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,6 +18,7 @@
#include <asm/io.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/omapfb.h>
extern int omap1_clk_init(void);
extern void omap_check_revision(void);
@@ -110,7 +111,7 @@ void __init omap1_map_common_io(void)
}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
}
#endif
@@ -121,6 +122,7 @@ void __init omap1_map_common_io(void)
#endif
omap_sram_init();
+ omapfb_reserve_mem();
}
/*
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index ed65a7d2e941..a0431c00fa81 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -60,7 +60,7 @@ struct omap_irq_bank {
unsigned long wake_enable;
};
-static unsigned int irq_bank_count = 0;
+static unsigned int irq_bank_count;
static struct omap_irq_bank *irq_banks;
static inline unsigned int irq_bank_readl(int bank, int offset)
@@ -142,28 +142,28 @@ static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger)
#ifdef CONFIG_ARCH_OMAP730
static struct omap_irq_bank omap730_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 },
};
#endif
#ifdef CONFIG_ARCH_OMAP15XX
static struct omap_irq_bank omap1510_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
};
static struct omap_irq_bank omap310_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 },
};
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_irq_bank omap1610_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff },
{ .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff },
};
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index d4b8d624e742..10fe0b3efcac 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -35,16 +35,20 @@
#ifdef CONFIG_ARCH_OMAP730
struct pin_config __initdata_or_module omap730_pins[] = {
-MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 0, 20, 1, NA, 0, 0)
-MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 0, 24, 1, NA, 0, 0)
-MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 0, 28, 1, NA, 0, 0)
-MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 0, 1, NA, 0, 0)
-MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 0, 4, 1, NA, 0, 0)
-MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 0, 8, 1, NA, 0, 0)
-MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 0, 12, 1, NA, 0, 0)
-MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 0, 16, 1, NA, 0, 0)
-MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 0, 20, 1, NA, 0, 0)
-MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 0, 24, 1, NA, 0, 0)
+MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0)
+MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0)
+MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0)
+MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 1, 0)
+MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 4, 1, 0)
+MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 8, 1, 0)
+MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 12, 1, 0)
+MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 16, 1, 0)
+MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 20, 1, 0)
+MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 24, 1, 0)
+
+MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0)
+MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0)
+MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0)
};
#endif
@@ -73,8 +77,8 @@ MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0)
MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0)
/* PWT & PWL, conflicts with UART3 */
-MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
-MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
+MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
+MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
/* USB internal master generic */
MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1)
@@ -151,7 +155,7 @@ MUX_CFG("MCBSP3_CLKX", 9, 3, 1, 1, 29, 0, NA, 0, 1)
/* Misc ballouts */
MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1)
-MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0)
+MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0)
/* OMAP-1610 MMC2 */
MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1)
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
new file mode 100644
index 000000000000..ddf6b07dc9c7
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.c
@@ -0,0 +1,770 @@
+/*
+ * linux/arch/arm/mach-omap1/pm.c
+ *
+ * OMAP Power Management Routines
+ *
+ * Original code for the SA11x0:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Modified for the PXA250 by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Modified for the OMAP1510 by David Singleton:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/dmtimer.h>
+
+static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
+static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
+static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+static unsigned short enable_dyn_sleep = 1;
+
+static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+ const char * buf,
+ size_t n)
+{
+ unsigned short value;
+ if (sscanf(buf, "%hu", &value) != 1 ||
+ (value != 0 && value != 1)) {
+ printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+ return -EINVAL;
+ }
+ enable_dyn_sleep = value;
+ return n;
+}
+
+static struct subsys_attribute sleep_while_idle_attr = {
+ .attr = {
+ .name = __stringify(sleep_while_idle),
+ .mode = 0644,
+ },
+ .show = omap_pm_sleep_while_idle_show,
+ .store = omap_pm_sleep_while_idle_store,
+};
+
+extern struct subsystem power_subsys;
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
+/*
+ * Let's power down on idle, but only if we are really
+ * idle, because once we start down the path of
+ * going idle we continue to do idle even if we get
+ * a clock tick interrupt . .
+ */
+void omap_pm_idle(void)
+{
+ extern __u32 arm_idlect1_mask;
+ __u32 use_idlect1 = arm_idlect1_mask;
+#ifndef CONFIG_OMAP_MPU_TIMER
+ int do_sleep;
+#endif
+
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+ /*
+ * Since an interrupt may set up a timer, we don't want to
+ * reprogram the hardware timer with interrupts enabled.
+ * Re-enable interrupts only after returning from idle.
+ */
+ timer_dyn_reprogram();
+
+#ifdef CONFIG_OMAP_MPU_TIMER
+#warning Enable 32kHz OS timer in order to allow sleep states in idle
+ use_idlect1 = use_idlect1 & ~(1 << 9);
+#else
+
+ do_sleep = 0;
+ while (enable_dyn_sleep) {
+
+#ifdef CONFIG_CBUS_TAHVO_USB
+ extern int vbus_active;
+ /* Clock requirements? */
+ if (vbus_active)
+ break;
+#endif
+ do_sleep = 1;
+ break;
+ }
+
+#ifdef CONFIG_OMAP_DM_TIMER
+ use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
+#endif
+
+ if (omap_dma_running()) {
+ use_idlect1 &= ~(1 << 6);
+ if (omap_lcd_dma_ext_running())
+ use_idlect1 &= ~(1 << 12);
+ }
+
+ /* We should be able to remove the do_sleep variable and multiple
+ * tests above as soon as drivers, timer and DMA code have been fixed.
+ * Even the sleep block count should become obsolete. */
+ if ((use_idlect1 != ~0) || !do_sleep) {
+
+ __u32 saved_idlect1 = omap_readl(ARM_IDLECT1);
+ if (cpu_is_omap15xx())
+ use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST;
+ else
+ use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL;
+ omap_writel(use_idlect1, ARM_IDLECT1);
+ __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
+ omap_writel(saved_idlect1, ARM_IDLECT1);
+
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+ omap_sram_suspend(omap_readl(ARM_IDLECT1),
+ omap_readl(ARM_IDLECT2));
+#endif
+
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+/*
+ * Configuration of the wakeup event is board specific. For the
+ * moment we put it into this helper function. Later it may move
+ * to board specific files.
+ */
+static void omap_pm_wakeup_setup(void)
+{
+ u32 level1_wake = 0;
+ u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
+
+ /*
+ * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
+ * and the L2 wakeup interrupts: keypad and UART2. Note that the
+ * drivers must still separately call omap_set_gpio_wakeup() to
+ * wake up to a GPIO interrupt.
+ */
+ if (cpu_is_omap730())
+ level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_730_IH2_IRQ);
+ else if (cpu_is_omap15xx())
+ level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
+ else if (cpu_is_omap16xx())
+ level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
+
+ omap_writel(~level1_wake, OMAP_IH1_MIR);
+
+ if (cpu_is_omap730()) {
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+ omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) |
+ OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)),
+ OMAP_IH2_1_MIR);
+ } else if (cpu_is_omap15xx()) {
+ level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+ omap_writel(~level2_wake, OMAP_IH2_MIR);
+ } else if (cpu_is_omap16xx()) {
+ level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+
+ /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
+ omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ),
+ OMAP_IH2_1_MIR);
+ omap_writel(~0x0, OMAP_IH2_2_MIR);
+ omap_writel(~0x0, OMAP_IH2_3_MIR);
+ }
+
+ /* New IRQ agreement, recalculate in cascade order */
+ omap_writel(1, OMAP_IH2_CONTROL);
+ omap_writel(1, OMAP_IH1_CONTROL);
+}
+
+#define EN_DSPCK 13 /* ARM_CKCTL */
+#define EN_APICK 6 /* ARM_IDLECT2 */
+#define DSP_EN 1 /* ARM_RSTCT1 */
+
+void omap_pm_suspend(void)
+{
+ unsigned long arg0 = 0, arg1 = 0;
+
+ printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
+
+ omap_serial_wake_trigger(1);
+
+ if (machine_is_omap_osk()) {
+ /* Stop LED1 (D9) blink */
+ tps65010_set_led(LED1, OFF);
+ }
+
+ omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
+ */
+
+ local_irq_disable();
+ local_fiq_disable();
+
+ /*
+ * Step 2: save registers
+ *
+ * The omap is a strange/beautiful device. The caches, memory
+ * and register state are preserved across power saves.
+ * We have to save and restore very little register state to
+ * idle the omap.
+ *
+ * Save interrupt, MPUI, ARM and UPLD control registers.
+ */
+
+ if (cpu_is_omap730()) {
+ MPUI730_SAVE(OMAP_IH1_MIR);
+ MPUI730_SAVE(OMAP_IH2_0_MIR);
+ MPUI730_SAVE(OMAP_IH2_1_MIR);
+ MPUI730_SAVE(MPUI_CTRL);
+ MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI730_SAVE(EMIFS_CONFIG);
+ MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_SAVE(OMAP_IH1_MIR);
+ MPUI1510_SAVE(OMAP_IH2_MIR);
+ MPUI1510_SAVE(MPUI_CTRL);
+ MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1510_SAVE(EMIFS_CONFIG);
+ MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_SAVE(OMAP_IH1_MIR);
+ MPUI1610_SAVE(OMAP_IH2_0_MIR);
+ MPUI1610_SAVE(OMAP_IH2_1_MIR);
+ MPUI1610_SAVE(OMAP_IH2_2_MIR);
+ MPUI1610_SAVE(OMAP_IH2_3_MIR);
+ MPUI1610_SAVE(MPUI_CTRL);
+ MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1610_SAVE(EMIFS_CONFIG);
+ MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+ }
+
+ ARM_SAVE(ARM_CKCTL);
+ ARM_SAVE(ARM_IDLECT1);
+ ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap15xx()))
+ ARM_SAVE(ARM_IDLECT3);
+ ARM_SAVE(ARM_EWUPCT);
+ ARM_SAVE(ARM_RSTCT1);
+ ARM_SAVE(ARM_RSTCT2);
+ ARM_SAVE(ARM_SYSST);
+ ULPD_SAVE(ULPD_CLOCK_CTRL);
+ ULPD_SAVE(ULPD_STATUS_REQ);
+
+ /* (Step 3 removed - we now allow deep sleep by default) */
+
+ /*
+ * Step 4: OMAP DSP Shutdown
+ */
+
+ /* stop DSP */
+ omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1);
+
+ /* shut down dsp_ck */
+ omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL);
+
+ /* temporarily enabling api_ck to access DSP registers */
+ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+ /* save DSP registers */
+ DSP_SAVE(DSP_IDLECT2);
+
+ /* Stop all DSP domain clocks */
+ __raw_writew(0, DSP_IDLECT2);
+
+ /*
+ * Step 5: Wakeup Event Setup
+ */
+
+ omap_pm_wakeup_setup();
+
+ /*
+ * Step 6: ARM and Traffic controller shutdown
+ */
+
+ /* disable ARM watchdog */
+ omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
+ omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
+
+ /*
+ * Step 6b: ARM and Traffic controller shutdown
+ *
+ * Step 6 continues here. Prepare jump to power management
+ * assembly code in internal SRAM.
+ *
+ * Since the omap_cpu_suspend routine has been copied to
+ * SRAM, we'll do an indirect procedure call to it and pass the
+ * contents of arm_idlect1 and arm_idlect2 so it can restore
+ * them when it wakes up and it will return.
+ */
+
+ arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
+ arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
+
+ /*
+ * Step 6c: ARM and Traffic controller shutdown
+ *
+ * Jump to assembly code. The processor will stay there
+ * until wake up.
+ */
+ omap_sram_suspend(arg0, arg1);
+
+ /*
+ * If we are here, processor is woken up!
+ */
+
+ /*
+ * Restore DSP clocks
+ */
+
+ /* again temporarily enabling api_ck to access DSP registers */
+ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+ /* Restore DSP domain clocks */
+ DSP_RESTORE(DSP_IDLECT2);
+
+ /*
+ * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
+ */
+
+ if (!(cpu_is_omap15xx()))
+ ARM_RESTORE(ARM_IDLECT3);
+ ARM_RESTORE(ARM_CKCTL);
+ ARM_RESTORE(ARM_EWUPCT);
+ ARM_RESTORE(ARM_RSTCT1);
+ ARM_RESTORE(ARM_RSTCT2);
+ ARM_RESTORE(ARM_SYSST);
+ ULPD_RESTORE(ULPD_CLOCK_CTRL);
+ ULPD_RESTORE(ULPD_STATUS_REQ);
+
+ if (cpu_is_omap730()) {
+ MPUI730_RESTORE(EMIFS_CONFIG);
+ MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI730_RESTORE(OMAP_IH1_MIR);
+ MPUI730_RESTORE(OMAP_IH2_0_MIR);
+ MPUI730_RESTORE(OMAP_IH2_1_MIR);
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_RESTORE(MPUI_CTRL);
+ MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
+ MPUI1510_RESTORE(EMIFS_CONFIG);
+ MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI1510_RESTORE(OMAP_IH1_MIR);
+ MPUI1510_RESTORE(OMAP_IH2_MIR);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_RESTORE(MPUI_CTRL);
+ MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
+ MPUI1610_RESTORE(EMIFS_CONFIG);
+ MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
+
+ MPUI1610_RESTORE(OMAP_IH1_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_0_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_1_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_2_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_3_MIR);
+ }
+
+ omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Reenable interrupts
+ */
+
+ local_irq_enable();
+ local_fiq_enable();
+
+ omap_serial_wake_trigger(0);
+
+ printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
+
+ if (machine_is_omap_osk()) {
+ /* Let LED1 (D9) blink again */
+ tps65010_set_led(LED1, BLINK);
+ }
+}
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+static int g_read_completed;
+
+/*
+ * Read system PM registers for debugging
+ */
+static int omap_pm_read_proc(
+ char *page_buffer,
+ char **my_first_byte,
+ off_t virtual_start,
+ int length,
+ int *eof,
+ void *data)
+{
+ int my_buffer_offset = 0;
+ char * const my_base = page_buffer;
+
+ ARM_SAVE(ARM_CKCTL);
+ ARM_SAVE(ARM_IDLECT1);
+ ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap15xx()))
+ ARM_SAVE(ARM_IDLECT3);
+ ARM_SAVE(ARM_EWUPCT);
+ ARM_SAVE(ARM_RSTCT1);
+ ARM_SAVE(ARM_RSTCT2);
+ ARM_SAVE(ARM_SYSST);
+
+ ULPD_SAVE(ULPD_IT_STATUS);
+ ULPD_SAVE(ULPD_CLOCK_CTRL);
+ ULPD_SAVE(ULPD_SOFT_REQ);
+ ULPD_SAVE(ULPD_STATUS_REQ);
+ ULPD_SAVE(ULPD_DPLL_CTRL);
+ ULPD_SAVE(ULPD_POWER_CTRL);
+
+ if (cpu_is_omap730()) {
+ MPUI730_SAVE(MPUI_CTRL);
+ MPUI730_SAVE(MPUI_DSP_STATUS);
+ MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI730_SAVE(EMIFS_CONFIG);
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_SAVE(MPUI_CTRL);
+ MPUI1510_SAVE(MPUI_DSP_STATUS);
+ MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI1510_SAVE(EMIFS_CONFIG);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_SAVE(MPUI_CTRL);
+ MPUI1610_SAVE(MPUI_DSP_STATUS);
+ MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI1610_SAVE(EMIFS_CONFIG);
+ }
+
+ if (virtual_start == 0) {
+ g_read_completed = 0;
+
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "ARM_CKCTL_REG: 0x%-8x \n"
+ "ARM_IDLECT1_REG: 0x%-8x \n"
+ "ARM_IDLECT2_REG: 0x%-8x \n"
+ "ARM_IDLECT3_REG: 0x%-8x \n"
+ "ARM_EWUPCT_REG: 0x%-8x \n"
+ "ARM_RSTCT1_REG: 0x%-8x \n"
+ "ARM_RSTCT2_REG: 0x%-8x \n"
+ "ARM_SYSST_REG: 0x%-8x \n"
+ "ULPD_IT_STATUS_REG: 0x%-4x \n"
+ "ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
+ "ULPD_SOFT_REQ_REG: 0x%-4x \n"
+ "ULPD_DPLL_CTRL_REG: 0x%-4x \n"
+ "ULPD_STATUS_REQ_REG: 0x%-4x \n"
+ "ULPD_POWER_CTRL_REG: 0x%-4x \n",
+ ARM_SHOW(ARM_CKCTL),
+ ARM_SHOW(ARM_IDLECT1),
+ ARM_SHOW(ARM_IDLECT2),
+ ARM_SHOW(ARM_IDLECT3),
+ ARM_SHOW(ARM_EWUPCT),
+ ARM_SHOW(ARM_RSTCT1),
+ ARM_SHOW(ARM_RSTCT2),
+ ARM_SHOW(ARM_SYSST),
+ ULPD_SHOW(ULPD_IT_STATUS),
+ ULPD_SHOW(ULPD_CLOCK_CTRL),
+ ULPD_SHOW(ULPD_SOFT_REQ),
+ ULPD_SHOW(ULPD_DPLL_CTRL),
+ ULPD_SHOW(ULPD_STATUS_REQ),
+ ULPD_SHOW(ULPD_POWER_CTRL));
+
+ if (cpu_is_omap730()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI730_CTRL_REG 0x%-8x \n"
+ "MPUI730_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI730_SHOW(MPUI_CTRL),
+ MPUI730_SHOW(MPUI_DSP_STATUS),
+ MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI730_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI730_SHOW(EMIFS_CONFIG));
+ } else if (cpu_is_omap15xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI1510_CTRL_REG 0x%-8x \n"
+ "MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI1510_SHOW(MPUI_CTRL),
+ MPUI1510_SHOW(MPUI_DSP_STATUS),
+ MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI1510_SHOW(EMIFS_CONFIG));
+ } else if (cpu_is_omap16xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI1610_CTRL_REG 0x%-8x \n"
+ "MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI1610_SHOW(MPUI_CTRL),
+ MPUI1610_SHOW(MPUI_DSP_STATUS),
+ MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI1610_SHOW(EMIFS_CONFIG));
+ }
+
+ g_read_completed++;
+ } else if (g_read_completed >= 1) {
+ *eof = 1;
+ return 0;
+ }
+ g_read_completed++;
+
+ *my_first_byte = page_buffer;
+ return my_buffer_offset;
+}
+
+static void omap_pm_init_proc(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_read_entry("driver/omap_pm",
+ S_IWUSR | S_IRUGO, NULL,
+ omap_pm_read_proc, NULL);
+}
+
+#endif /* DEBUG && CONFIG_PROC_FS */
+
+static void (*saved_idle)(void) = NULL;
+
+/*
+ * omap_pm_prepare - Do preliminary suspend work.
+ * @state: suspend state we're entering.
+ *
+ */
+static int omap_pm_prepare(suspend_state_t state)
+{
+ int error = 0;
+
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return error;
+}
+
+
+/*
+ * omap_pm_enter - Actually enter a sleep state.
+ * @state: State we're entering.
+ *
+ */
+
+static int omap_pm_enter(suspend_state_t state)
+{
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ omap_pm_suspend();
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * omap_pm_finish - Finish up suspend sequence.
+ * @state: State we're coming out of.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+
+static int omap_pm_finish(suspend_state_t state)
+{
+ pm_idle = saved_idle;
+ return 0;
+}
+
+
+static irqreturn_t omap_wakeup_interrupt(int irq, void * dev,
+ struct pt_regs * regs)
+{
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+ .name = "peripheral wakeup",
+ .flags = SA_INTERRUPT,
+ .handler = omap_wakeup_interrupt
+};
+
+
+
+static struct pm_ops omap_pm_ops ={
+ .pm_disk_mode = 0,
+ .prepare = omap_pm_prepare,
+ .enter = omap_pm_enter,
+ .finish = omap_pm_finish,
+};
+
+static int __init omap_pm_init(void)
+{
+ printk("Power Management for TI OMAP.\n");
+
+ /*
+ * We copy the assembler sleep/wakeup routines to SRAM.
+ * These routines need to be in SRAM as that's the only
+ * memory the MPU can see when it wakes up.
+ */
+ if (cpu_is_omap730()) {
+ omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
+ omap730_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
+ omap730_cpu_suspend_sz);
+ } else if (cpu_is_omap15xx()) {
+ omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+ omap1510_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+ omap1510_cpu_suspend_sz);
+ } else if (cpu_is_omap16xx()) {
+ omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+ omap1610_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+ omap1610_cpu_suspend_sz);
+ }
+
+ if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+ printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+ return -ENODEV;
+ }
+
+ pm_idle = omap_pm_idle;
+
+ if (cpu_is_omap730())
+ setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
+ else if (cpu_is_omap16xx())
+ setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+
+ /* Program new power ramp-up time
+ * (0 for most boards since we don't lower voltage when in deep sleep)
+ */
+ omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
+
+ /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
+ omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
+
+ /* Configure IDLECT3 */
+ if (cpu_is_omap730())
+ omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
+ else if (cpu_is_omap16xx())
+ omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
+ pm_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+ omap_pm_init_proc();
+#endif
+
+ subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+
+ if (cpu_is_omap16xx()) {
+ /* configure LOW_PWR pin */
+ omap_cfg_reg(T20_1610_LOW_PWR);
+ }
+
+ return 0;
+}
+__initcall(omap_pm_init);
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index e924e0c6a4ce..9b4cd698bec8 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -30,9 +30,9 @@
#include <asm/arch/pm.h>
#endif
-static struct clk * uart1_ck = NULL;
-static struct clk * uart2_ck = NULL;
-static struct clk * uart3_ck = NULL;
+static struct clk * uart1_ck;
+static struct clk * uart2_ck;
+static struct clk * uart3_ck;
static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
int offset)
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/mach-omap1/sleep.S
index 4cd7d292f854..e58295e2d3b2 100644
--- a/arch/arm/plat-omap/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/plat-omap/sleep.S
+ * linux/arch/arm/mach-omap1/sleep.S
*
* Low-level OMAP730/1510/1610 sleep/wakeUp support
*
@@ -383,60 +383,133 @@ ENTRY(omap1610_cpu_suspend)
mcr p15, 0, r0, c7, c10, 4
nop
- @ load base address of Traffic Controller
+ @ Load base address of Traffic Controller
mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
- @ prepare to put SDRAM into self-refresh manually
+ @ Prepare to put SDRAM into self-refresh manually
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
- @ prepare to put EMIFS to Sleep
+ @ Prepare to put EMIFS to Sleep
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- @ load base address of ARM_IDLECT1 and ARM_IDLECT2
+ @ Load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
- @ turn off clock domains
- @ do not disable PERCK (0x04)
+ @ Turn off clock domains
+ @ Do not disable PERCK (0x04)
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- @ request ARM idle
+ @ Request ARM idle
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- @ disable instruction cache
- mrc p15, 0, r9, c1, c0, 0
- bic r2, r9, #0x1000
- mcr p15, 0, r2, c1, c0, 0
- nop
-
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
*/
mov r2, #0
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+
+ @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
+ @ according to this formula:
+ @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
+ @ Max DPLL_MULT = 18
+ @ DPLL_DIV = 1
+ @ ARMDIV = 1
+ @ => 74 nop-instructions
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @10
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @20
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @30
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @40
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @50
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @60
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @70
+ nop
+ nop
+ nop
+ nop @74
/*
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack.
*/
- @ re-enable Icache
- mcr p15, 0, r9, c1, c0, 0
-
- @ reset the ARM_IDLECT1 and ARM_IDLECT2.
+ @ Restore the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@@ -444,7 +517,7 @@ ENTRY(omap1610_cpu_suspend)
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- @ restore regs and return
+ @ Restore regs and return
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index cdbf4d7620c6..a85fe6066bc4 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -51,8 +51,6 @@
struct sys_timer omap_timer;
-#ifdef CONFIG_OMAP_MPU_TIMER
-
/*
* ---------------------------------------------------------------------------
* MPU timer
@@ -222,195 +220,6 @@ unsigned long long sched_clock(void)
return cycles_2_ns(ticks64);
}
-#endif /* CONFIG_OMAP_MPU_TIMER */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-
-#ifdef CONFIG_ARCH_OMAP15XX
-#error OMAP 32KHz timer does not currently work on 15XX!
-#endif
-
-/*
- * ---------------------------------------------------------------------------
- * 32KHz OS timer
- *
- * This currently works only on 16xx, as 1510 does not have the continuous
- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
- * on 1510 would be possible, but the timer would not be as accurate as
- * with the 32KHz synchronized timer.
- * ---------------------------------------------------------------------------
- */
-#define OMAP_32K_TIMER_BASE 0xfffb9000
-#define OMAP_32K_TIMER_CR 0x08
-#define OMAP_32K_TIMER_TVR 0x00
-#define OMAP_32K_TIMER_TCR 0x04
-
-#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
-
-/*
- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
- * so with HZ = 100, TVR = 327.68.
- */
-#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
-#define TIMER_32K_SYNCHRONIZED 0xfffbc410
-
-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
- (((nr_jiffies) * (clock_rate)) / HZ)
-
-static inline void omap_32k_timer_write(int val, int reg)
-{
- omap_writew(val, reg + OMAP_32K_TIMER_BASE);
-}
-
-static inline unsigned long omap_32k_timer_read(int reg)
-{
- return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
-}
-
-/*
- * The 32KHz synchronized timer is an additional timer on 16xx.
- * It is always running.
- */
-static inline unsigned long omap_32k_sync_timer_read(void)
-{
- return omap_readl(TIMER_32K_SYNCHRONIZED);
-}
-
-static inline void omap_32k_timer_start(unsigned long load_val)
-{
- omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
- omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
-}
-
-static inline void omap_32k_timer_stop(void)
-{
- omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
-}
-
-/*
- * Rounds down to nearest usec. Note that this will overflow for larger values.
- */
-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
-{
- return (ticks_32k * 5*5*5*5*5*5) >> 9;
-}
-
-/*
- * Rounds down to nearest nsec.
- */
-static inline unsigned long long
-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
-{
- return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
-}
-
-static unsigned long omap_32k_last_tick = 0;
-
-/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
- unsigned long now = omap_32k_sync_timer_read();
- return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
- return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
-}
-
-/*
- * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
- * function is also called from other interrupts to remove latency
- * issues with dynamic tick. In the dynamic tick case, we need to lock
- * with irqsave.
- */
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- unsigned long flags;
- unsigned long now;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- now = omap_32k_sync_timer_read();
-
- while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
- omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
- timer_tick(regs);
- }
-
- /* Restart timer so we don't drift off due to modulo or dynamic tick.
- * By default we program the next timer to be continuous to avoid
- * latencies during high system load. During dynamic tick operation the
- * continuous timer can be overridden from pm_idle to be longer.
- */
- omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-/*
- * Programs the next timer interrupt needed. Called when dynamic tick is
- * enabled, and to reprogram the ticks to skip from pm_idle. Note that
- * we can keep the timer continuous, and don't need to set it to run in
- * one-shot mode. This is because the timer will get reprogrammed again
- * after next interrupt.
- */
-void omap_32k_timer_reprogram(unsigned long next_tick)
-{
- omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
-}
-
-static struct irqaction omap_32k_timer_irq;
-extern struct timer_update_handler timer_update;
-
-static int omap_32k_timer_enable_dyn_tick(void)
-{
- /* No need to reprogram timer, just use the next interrupt */
- return 0;
-}
-
-static int omap_32k_timer_disable_dyn_tick(void)
-{
- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
- return 0;
-}
-
-static struct dyn_tick_timer omap_dyn_tick_timer = {
- .enable = omap_32k_timer_enable_dyn_tick,
- .disable = omap_32k_timer_disable_dyn_tick,
- .reprogram = omap_32k_timer_reprogram,
- .handler = omap_32k_timer_interrupt,
-};
-#endif /* CONFIG_NO_IDLE_HZ */
-
-static struct irqaction omap_32k_timer_irq = {
- .name = "32KHz timer",
- .flags = SA_INTERRUPT | SA_TIMER,
- .handler = omap_32k_timer_interrupt,
-};
-
-static __init void omap_init_32k_timer(void)
-{
-
-#ifdef CONFIG_NO_IDLE_HZ
- omap_timer.dyn_tick = &omap_dyn_tick_timer;
-#endif
-
- setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
- omap_timer.offset = omap_32k_timer_gettimeoffset;
- omap_32k_last_tick = omap_32k_sync_timer_read();
- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-}
-#endif /* CONFIG_OMAP_32K_TIMER */
/*
* ---------------------------------------------------------------------------
@@ -419,13 +228,7 @@ static __init void omap_init_32k_timer(void)
*/
static void __init omap_timer_init(void)
{
-#if defined(CONFIG_OMAP_MPU_TIMER)
omap_init_mpu_timer();
-#elif defined(CONFIG_OMAP_32K_TIMER)
- omap_init_32k_timer();
-#else
-#error No system timer selected in Kconfig!
-#endif
}
struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 578880943cf2..537dd2e6d380 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -20,3 +20,6 @@ config MACH_OMAP_H4
bool "OMAP 2420 H4 board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
+config MACH_OMAP_APOLLON
+ bool "OMAP 2420 Apollon board"
+ depends on ARCH_OMAP2 && ARCH_OMAP24XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 42041166435c..111eaa64258f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,11 +3,15 @@
#
# Common support
-obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o
obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
# Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
+obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
new file mode 100644
index 000000000000..6c6ba172cdf6
--- /dev/null
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -0,0 +1,285 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-apollon.c
+ *
+ * Copyright (C) 2005,2006 Samsung Electronics
+ * Author: Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Modified from mach-omap/omap2/board-h4.c
+ *
+ * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
+ * the bootloader passes the board-specific data to the kernel.
+ * Do not put any board specific code to this file; create a new machine
+ * type if you need custom low-level initializations.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include "prcm-regs.h"
+
+/* LED & Switch macros */
+#define LED0_GPIO13 13
+#define LED1_GPIO14 14
+#define LED2_GPIO15 15
+#define SW_ENTER_GPIO16 16
+#define SW_UP_GPIO17 17
+#define SW_DOWN_GPIO58 58
+
+static struct mtd_partition apollon_partitions[] = {
+ {
+ .name = "X-Loader + U-Boot",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ },
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_16M,
+ },
+ {
+ .name = "filesystem00",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_32M,
+ },
+ {
+ .name = "filesystem01",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data apollon_flash_data = {
+ .parts = apollon_partitions,
+ .nr_parts = ARRAY_SIZE(apollon_partitions),
+};
+
+static struct resource apollon_flash_resource = {
+ .start = APOLLON_CS0_BASE,
+ .end = APOLLON_CS0_BASE + SZ_128K,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device apollon_onenand_device = {
+ .name = "onenand",
+ .id = -1,
+ .dev = {
+ .platform_data = &apollon_flash_data,
+ },
+ .num_resources = ARRAY_SIZE(&apollon_flash_resource),
+ .resource = &apollon_flash_resource,
+};
+
+static struct resource apollon_smc91x_resources[] = {
+ [0] = {
+ .start = APOLLON_ETHR_START, /* Physical */
+ .end = APOLLON_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+ .end = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device apollon_smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(apollon_smc91x_resources),
+ .resource = apollon_smc91x_resources,
+};
+
+static struct platform_device apollon_lcd_device = {
+ .name = "apollon_lcd",
+ .id = -1,
+};
+
+static struct platform_device *apollon_devices[] __initdata = {
+ &apollon_onenand_device,
+ &apollon_smc91x_device,
+ &apollon_lcd_device,
+};
+
+static inline void __init apollon_init_smc91x(void)
+{
+ /* Make sure CS1 timings are correct */
+ GPMC_CONFIG1_1 = 0x00011203;
+ GPMC_CONFIG2_1 = 0x001f1f01;
+ GPMC_CONFIG3_1 = 0x00080803;
+ GPMC_CONFIG4_1 = 0x1c091c09;
+ GPMC_CONFIG5_1 = 0x041f1f1f;
+ GPMC_CONFIG6_1 = 0x000004c4;
+ GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+ udelay(100);
+
+ omap_cfg_reg(W4__24XX_GPIO74);
+ if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ APOLLON_ETHR_GPIO_IRQ);
+ return;
+ }
+ omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
+}
+
+static void __init omap_apollon_init_irq(void)
+{
+ omap2_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+ apollon_init_smc91x();
+}
+
+static struct omap_uart_config apollon_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
+};
+
+static struct omap_mmc_config apollon_mmc_config __initdata = {
+ .mmc [0] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_lcd_config apollon_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel apollon_config[] = {
+ { OMAP_TAG_UART, &apollon_uart_config },
+ { OMAP_TAG_MMC, &apollon_mmc_config },
+ { OMAP_TAG_LCD, &apollon_lcd_config },
+};
+
+static void __init apollon_led_init(void)
+{
+ /* LED0 - AA10 */
+ omap_cfg_reg(AA10_242X_GPIO13);
+ omap_request_gpio(LED0_GPIO13);
+ omap_set_gpio_direction(LED0_GPIO13, 0);
+ omap_set_gpio_dataout(LED0_GPIO13, 0);
+ /* LED1 - AA6 */
+ omap_cfg_reg(AA6_242X_GPIO14);
+ omap_request_gpio(LED1_GPIO14);
+ omap_set_gpio_direction(LED1_GPIO14, 0);
+ omap_set_gpio_dataout(LED1_GPIO14, 0);
+ /* LED2 - AA4 */
+ omap_cfg_reg(AA4_242X_GPIO15);
+ omap_request_gpio(LED2_GPIO15);
+ omap_set_gpio_direction(LED2_GPIO15, 0);
+ omap_set_gpio_dataout(LED2_GPIO15, 0);
+}
+
+static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+ static unsigned int led0, led1, led2;
+
+ if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16))
+ omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1);
+ else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17))
+ omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1);
+ else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58))
+ omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1);
+
+ return IRQ_HANDLED;
+}
+
+static void __init apollon_sw_init(void)
+{
+ /* Enter SW - Y11 */
+ omap_cfg_reg(Y11_242X_GPIO16);
+ omap_request_gpio(SW_ENTER_GPIO16);
+ omap_set_gpio_direction(SW_ENTER_GPIO16, 1);
+ /* Up SW - AA12 */
+ omap_cfg_reg(AA12_242X_GPIO17);
+ omap_request_gpio(SW_UP_GPIO17);
+ omap_set_gpio_direction(SW_UP_GPIO17, 1);
+ /* Down SW - AA8 */
+ omap_cfg_reg(AA8_242X_GPIO58);
+ omap_request_gpio(SW_DOWN_GPIO58);
+ omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
+
+ set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
+ SA_SHIRQ, "enter sw",
+ &apollon_sw_interrupt))
+ return;
+ set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
+ SA_SHIRQ, "up sw",
+ &apollon_sw_interrupt))
+ return;
+ set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
+ SA_SHIRQ, "down sw",
+ &apollon_sw_interrupt))
+ return;
+}
+
+static void __init omap_apollon_init(void)
+{
+ apollon_led_init();
+ apollon_sw_init();
+
+ /* REVISIT: where's the correct place */
+ omap_cfg_reg(W19_24XX_SYS_NIRQ);
+
+ /*
+ * Make sure the serial ports are muxed on at this point.
+ * You have to mux them off in device drivers later on
+ * if not needed.
+ */
+ platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
+ omap_board_config = apollon_config;
+ omap_board_config_size = ARRAY_SIZE(apollon_config);
+ omap_serial_init();
+}
+
+static void __init omap_apollon_map_io(void)
+{
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
+ /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap_apollon_map_io,
+ .init_irq = omap_apollon_init_irq,
+ .init_machine = omap_apollon_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index a300d634d8a5..4933fce766c8 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -17,6 +17,8 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -25,15 +27,57 @@
#include <asm/mach/flash.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
+#include <asm/arch/irda.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
-#include <asm/arch/prcm.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/arch/dma.h>
+#include "prcm-regs.h"
#include <asm/io.h>
#include <asm/delay.h>
+static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+
+static int h4_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_A),
+ KEY(0, 3, KEY_B),
+ KEY(0, 4, KEY_C),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_E),
+ KEY(1, 3, KEY_F),
+ KEY(1, 4, KEY_G),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_I),
+ KEY(2, 2, KEY_J),
+ KEY(2, 3, KEY_K),
+ KEY(2, 4, KEY_3),
+ KEY(3, 0, KEY_M),
+ KEY(3, 1, KEY_N),
+ KEY(3, 2, KEY_O),
+ KEY(3, 3, KEY_P),
+ KEY(3, 4, KEY_Q),
+ KEY(4, 0, KEY_R),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_T),
+ KEY(4, 3, KEY_U),
+ KEY(4, 4, KEY_ENTER),
+ KEY(5, 0, KEY_V),
+ KEY(5, 1, KEY_W),
+ KEY(5, 2, KEY_L),
+ KEY(5, 3, KEY_S),
+ KEY(5, 4, KEY_ENTER),
+ 0
+};
+
static struct mtd_partition h4_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -108,9 +152,123 @@ static struct platform_device h4_smc91x_device = {
.resource = h4_smc91x_resources,
};
+/* Select between the IrDA and aGPS module
+ */
+static int h4_select_irda(struct device *dev, int state)
+{
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x21))) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ return err;
+ }
+
+ /* 'P6' enable/disable IRDA_TX and IRDA_RX */
+ if (state & IR_SEL) { /* IrDa */
+ if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ return err;
+ }
+ } else {
+ if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ return err;
+ }
+ }
+ return err;
+}
+
+static void set_trans_mode(void *data)
+{
+ int *mode = data;
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ }
+
+ expa &= ~0x01;
+
+ if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */
+ expa |= 0x01;
+ }
+
+ if ((err = write_gpio_expa(expa, 0x20)) != 0) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ }
+}
+
+static int h4_transceiver_mode(struct device *dev, int mode)
+{
+ struct omap_irda_config *irda_config = dev->platform_data;
+
+ cancel_delayed_work(&irda_config->gpio_expa);
+ PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+ schedule_work(&irda_config->gpio_expa);
+
+ return 0;
+}
+
+static struct omap_irda_config h4_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .transceiver_mode = h4_transceiver_mode,
+ .select_irda = h4_select_irda,
+ .rx_channel = OMAP24XX_DMA_UART3_RX,
+ .tx_channel = OMAP24XX_DMA_UART3_TX,
+ .dest_start = OMAP_UART3_BASE,
+ .src_start = OMAP_UART3_BASE,
+ .tx_trigger = OMAP24XX_DMA_UART3_TX,
+ .rx_trigger = OMAP24XX_DMA_UART3_RX,
+};
+
+static struct resource h4_irda_resources[] = {
+ [0] = {
+ .start = INT_24XX_UART3_IRQ,
+ .end = INT_24XX_UART3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device h4_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &h4_irda_data,
+ },
+ .num_resources = 1,
+ .resource = h4_irda_resources,
+};
+
+static struct omap_kp_platform_data h4_kp_data = {
+ .rows = 6,
+ .cols = 7,
+ .keymap = h4_keymap,
+ .rep = 1,
+ .row_gpios = row_gpios,
+ .col_gpios = col_gpios,
+};
+
+static struct platform_device h4_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h4_kp_data,
+ },
+};
+
+static struct platform_device h4_lcd_device = {
+ .name = "lcd_h4",
+ .id = -1,
+};
+
static struct platform_device *h4_devices[] __initdata = {
&h4_smc91x_device,
&h4_flash_device,
+ &h4_irda_device,
+ &h4_kp_device,
+ &h4_lcd_device,
};
static inline void __init h4_init_smc91x(void)
@@ -157,7 +315,6 @@ static struct omap_mmc_config h4_mmc_config __initdata = {
};
static struct omap_lcd_config h4_lcd_config __initdata = {
- .panel_name = "h4",
.ctrl_name = "internal",
};
@@ -174,6 +331,19 @@ static void __init omap_h4_init(void)
* You have to mux them off in device drivers later on
* if not needed.
*/
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+ omap_cfg_reg(K15_24XX_UART3_TX);
+ omap_cfg_reg(K14_24XX_UART3_RX);
+#endif
+
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+ if (omap_has_menelaus()) {
+ row_gpios[5] = 0;
+ col_gpios[2] = 15;
+ col_gpios[6] = 18;
+ }
+#endif
+
platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
omap_board_config = h4_config;
omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180f675c9064..72eb4bf571ac 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -28,14 +28,14 @@
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
+#include "memory.h"
#include "clock.h"
//#define DOWN_VARIABLE_DPLL 1 /* Experimental */
static struct prcm_config *curr_prcm_set;
-static struct memory_timings mem_timings;
static u32 curr_perf_level = PRCM_FULL_SPEED;
/*-------------------------------------------------------------------------
@@ -54,11 +54,13 @@ static void omap2_sys_clk_recalc(struct clk * clk)
static u32 omap2_get_dpll_rate(struct clk * tclk)
{
- int dpll_clk, dpll_mult, dpll_div, amult;
+ long long dpll_clk;
+ int dpll_mult, dpll_div, amult;
dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */
dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */
- dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
+ dpll_clk = (long long)tclk->parent->rate * dpll_mult;
+ do_div(dpll_clk, dpll_div + 1);
amult = CM_CLKSEL2_PLL & 0x3;
dpll_clk *= amult;
@@ -385,75 +387,23 @@ static u32 omap2_dll_force_needed(void)
return 0;
}
-static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
-{
- unsigned long dll_cnt;
- u32 fast_dll = 0;
-
- mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
-
- /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
- * In the case of 2422, its ok to use CS1 instead of CS0.
- */
-
-#if 0 /* FIXME: Enable after 24xx cpu detection works */
- ctype = get_cpu_type();
- if (cpu_is_omap2422())
- mem_timings.base_cs = 1;
- else
-#endif
- mem_timings.base_cs = 0;
-
- if (mem_timings.m_type != M_DDR)
- return;
-
- /* With DDR we need to determine the low frequency DLL value */
- if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
- mem_timings.dll_mode = M_UNLOCK;
- else
- mem_timings.dll_mode = M_LOCK;
-
- if (mem_timings.base_cs == 0) {
- fast_dll = SDRC_DLLA_CTRL;
- dll_cnt = SDRC_DLLA_STATUS & 0xff00;
- } else {
- fast_dll = SDRC_DLLB_CTRL;
- dll_cnt = SDRC_DLLB_STATUS & 0xff00;
- }
- if (force_lock_to_unlock_mode) {
- fast_dll &= ~0xff00;
- fast_dll |= dll_cnt; /* Current lock mode */
- }
- mem_timings.fast_dll_ctrl = fast_dll;
-
- /* No disruptions, DDR will be offline & C-ABI not followed */
- omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
- mem_timings.fast_dll_ctrl,
- mem_timings.base_cs,
- force_lock_to_unlock_mode);
- mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
-
- /* Turn status into unlock ctrl */
- mem_timings.slow_dll_ctrl |=
- ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
-
- /* 90 degree phase for anything below 133Mhz */
- mem_timings.slow_dll_ctrl |= (1 << 1);
-}
-
static u32 omap2_reprogram_sdrc(u32 level, u32 force)
{
+ u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
u32 prev = curr_perf_level, flags;
if ((curr_perf_level == level) && !force)
return prev;
+ m_type = omap2_memory_get_type();
+ slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+ fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+
if (level == PRCM_HALF_SPEED) {
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
- mem_timings.slow_dll_ctrl,
- mem_timings.m_type);
+ slow_dll_ctrl, m_type);
curr_perf_level = PRCM_HALF_SPEED;
local_irq_restore(flags);
}
@@ -461,8 +411,7 @@ static u32 omap2_reprogram_sdrc(u32 level, u32 force)
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
- mem_timings.fast_dll_ctrl,
- mem_timings.m_type);
+ fast_dll_ctrl, m_type);
curr_perf_level = PRCM_FULL_SPEED;
local_irq_restore(flags);
}
@@ -650,7 +599,7 @@ static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
case 13: /* dss2 */
mask = 0x1; break;
case 25: /* usb */
- mask = 0xf; break;
+ mask = 0x7; break;
}
}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 6cab20b1d3c1..6c78d471fab7 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -33,20 +33,6 @@ static u32 omap2_clksel_get_divisor(struct clk *clk);
#define RATE_IN_242X (1 << 0)
#define RATE_IN_243X (1 << 1)
-/* Memory timings */
-#define M_DDR 1
-#define M_LOCK_CTRL (1 << 2)
-#define M_UNLOCK 0
-#define M_LOCK 1
-
-struct memory_timings {
- u32 m_type; /* ddr = 1, sdr = 0 */
- u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */
- u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */
- u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */
- u32 base_cs; /* base chip select to use for calculations */
-};
-
/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
* xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
* CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
@@ -731,6 +717,16 @@ static struct clk sys_clkout2 = {
.recalc = &omap2_clksel_recalc,
};
+static struct clk emul_ck = {
+ .name = "emul_ck",
+ .parent = &func_54m_ck,
+ .flags = CLOCK_IN_OMAP242X,
+ .enable_reg = (void __iomem *)&PRCM_CLKEMUL_CTRL,
+ .enable_bit = 0,
+ .recalc = &omap2_propagate_rate,
+
+};
+
/*
* MPU clock domain
* Clocks:
@@ -1702,7 +1698,8 @@ static struct clk hdq_fck = {
};
static struct clk i2c2_ick = {
- .name = "i2c2_ick",
+ .name = "i2c_ick",
+ .id = 2,
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1711,7 +1708,8 @@ static struct clk i2c2_ick = {
};
static struct clk i2c2_fck = {
- .name = "i2c2_fck",
+ .name = "i2c_fck",
+ .id = 2,
.parent = &func_12m_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1729,7 +1727,8 @@ static struct clk i2chs2_fck = {
};
static struct clk i2c1_ick = {
- .name = "i2c1_ick",
+ .name = "i2c_ick",
+ .id = 1,
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1738,7 +1737,8 @@ static struct clk i2c1_ick = {
};
static struct clk i2c1_fck = {
- .name = "i2c1_fck",
+ .name = "i2c_fck",
+ .id = 1,
.parent = &func_12m_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1971,6 +1971,7 @@ static struct clk *onchip_clks[] = {
&wdt1_osc_ck,
&sys_clkout,
&sys_clkout2,
+ &emul_ck,
/* mpu domain clocks */
&mpu_ck,
/* dsp domain clocks */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 7181edb89352..fb7f91da1aad 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -25,10 +25,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-extern void omap_nop_release(struct device *dev);
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
#define OMAP2_I2C_BASE2 0x48072000
@@ -49,9 +45,6 @@ static struct resource i2c_resources2[] = {
static struct platform_device omap_i2c_device2 = {
.name = "i2c_omap",
.id = 2,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(i2c_resources2),
.resource = i2c_resources2,
};
@@ -74,6 +67,44 @@ static void omap_init_i2c(void) {}
#endif
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP2_STI_BASE IO_ADDRESS(0x48068000)
+#define OMAP2_STI_CHANNEL_BASE 0x54000000
+#define OMAP2_STI_IRQ 4
+
+static struct resource sti_resources[] = {
+ {
+ .start = OMAP2_STI_BASE,
+ .end = OMAP2_STI_BASE + 0x7ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP2_STI_CHANNEL_BASE,
+ .end = OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP2_STI_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device sti_device = {
+ .name = "sti",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(sti_resources),
+ .resource = sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+ platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
+
/*-------------------------------------------------------------------------*/
static int __init omap2_init_devices(void)
@@ -82,6 +113,7 @@ static int __init omap2_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_i2c();
+ omap_init_sti();
return 0;
}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 8ea67bf196a5..7d5711611f2f 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -16,9 +16,13 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/mach/map.h>
+#include <asm/tlb.h>
#include <asm/io.h>
+
+#include <asm/mach/map.h>
+
#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
extern void omap_sram_init(void);
extern int omap2_clk_init(void);
@@ -43,11 +47,24 @@ static struct map_desc omap2_io_desc[] __initdata = {
}
};
-void __init omap_map_common_io(void)
+void __init omap2_map_common_io(void)
{
iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+
+ /* Normally devicemaps_init() would flush caches and tlb after
+ * mdesc->map_io(), but we must also do it here because of the CPU
+ * revision check below.
+ */
+ local_flush_tlb_all();
+ flush_cache_all();
+
omap2_check_revision();
omap_sram_init();
+ omapfb_reserve_mem();
+}
+
+void __init omap2_init_common_hw(void)
+{
omap2_mux_init();
omap2_clk_init();
}
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
new file mode 100644
index 000000000000..1d925d69fc35
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.c
+ *
+ * Memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+
+#include "prcm-regs.h"
+#include "memory.h"
+
+static struct memory_timings mem_timings;
+
+u32 omap2_memory_get_slow_dll_ctrl(void)
+{
+ return mem_timings.slow_dll_ctrl;
+}
+
+u32 omap2_memory_get_fast_dll_ctrl(void)
+{
+ return mem_timings.fast_dll_ctrl;
+}
+
+u32 omap2_memory_get_type(void)
+{
+ return mem_timings.m_type;
+}
+
+void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+ unsigned long dll_cnt;
+ u32 fast_dll = 0;
+
+ mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+ /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+ * In the case of 2422, its ok to use CS1 instead of CS0.
+ */
+ if (cpu_is_omap2422())
+ mem_timings.base_cs = 1;
+ else
+ mem_timings.base_cs = 0;
+
+ if (mem_timings.m_type != M_DDR)
+ return;
+
+ /* With DDR we need to determine the low frequency DLL value */
+ if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+ mem_timings.dll_mode = M_UNLOCK;
+ else
+ mem_timings.dll_mode = M_LOCK;
+
+ if (mem_timings.base_cs == 0) {
+ fast_dll = SDRC_DLLA_CTRL;
+ dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+ } else {
+ fast_dll = SDRC_DLLB_CTRL;
+ dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+ }
+ if (force_lock_to_unlock_mode) {
+ fast_dll &= ~0xff00;
+ fast_dll |= dll_cnt; /* Current lock mode */
+ }
+ /* set fast timings with DLL filter disabled */
+ mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8));
+
+ /* No disruptions, DDR will be offline & C-ABI not followed */
+ omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+ mem_timings.fast_dll_ctrl,
+ mem_timings.base_cs,
+ force_lock_to_unlock_mode);
+ mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
+
+ /* Turn status into unlock ctrl */
+ mem_timings.slow_dll_ctrl |=
+ ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+ /* 90 degree phase for anything below 133Mhz + disable DLL filter */
+ mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
+}
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
new file mode 100644
index 000000000000..d212eea83a05
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.h
+ *
+ * Interface for memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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.
+ */
+
+/* Memory timings */
+#define M_DDR 1
+#define M_LOCK_CTRL (1 << 2)
+#define M_UNLOCK 0
+#define M_LOCK 1
+
+struct memory_timings {
+ u32 m_type; /* ddr = 1, sdr = 0 */
+ u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */
+ u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */
+ u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */
+ u32 base_cs; /* base chip select to use for calculations */
+};
+
+extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+extern u32 omap2_memory_get_slow_dll_ctrl(void);
+extern u32 omap2_memory_get_fast_dll_ctrl(void);
+extern u32 omap2_memory_get_type(void);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index ea4654815dd1..1197dc38c20a 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -50,9 +50,54 @@ MUX_CFG_24XX("H19_24XX_I2C2_SDA", 0x114, 0, 0, 0, 1)
/* Menelaus interrupt */
MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1)
+/* 24xx clocks */
+MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1)
+
+/* 24xx McBSP */
+MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1)
+MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1)
+MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1)
+MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1)
+
/* 24xx GPIO */
+MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1)
+MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1)
+MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1)
+MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1)
+MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1)
+MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
+MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1)
+MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1)
+MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1)
+
+/* TSC IRQ */
+MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1)
+
+/* UART3 */
+MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1)
+MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1)
+
+/* Keypad GPIO*/
+MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1)
+MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1)
+MUX_CFG_24XX("V18_24XX_KBR2", 0x139, 3, 1, 1, 1)
+MUX_CFG_24XX("M21_24XX_KBR3", 0xc9, 3, 1, 1, 1)
+MUX_CFG_24XX("E5__24XX_KBR4", 0x138, 3, 1, 1, 1)
+MUX_CFG_24XX("M18_24XX_KBR5", 0x10e, 3, 1, 1, 1)
+MUX_CFG_24XX("R20_24XX_KBC0", 0x108, 3, 0, 0, 1)
+MUX_CFG_24XX("M14_24XX_KBC1", 0x109, 3, 0, 0, 1)
+MUX_CFG_24XX("H19_24XX_KBC2", 0x114, 3, 0, 0, 1)
+MUX_CFG_24XX("V17_24XX_KBC3", 0x135, 3, 0, 0, 1)
+MUX_CFG_24XX("P21_24XX_KBC4", 0xca, 3, 0, 0, 1)
+MUX_CFG_24XX("L14_24XX_KBC5", 0x10f, 3, 0, 0, 1)
+MUX_CFG_24XX("N19_24XX_KBC6", 0x110, 3, 0, 0, 1)
+
+/* 24xx Menelaus Keypad GPIO */
+MUX_CFG_24XX("B3__24XX_KBR5", 0x30, 3, 1, 1, 1)
+MUX_CFG_24XX("AA4_24XX_KBC2", 0xe7, 3, 0, 0, 1)
+MUX_CFG_24XX("B13_24XX_KBC6", 0x110, 3, 0, 0, 1)
};
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644
index 000000000000..562168fa2b16
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap2/pm.c
+ *
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * 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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/pm.h>
+
+static struct clk *vclk;
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+static void (*saved_idle)(void);
+
+void omap2_pm_idle(void)
+{
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+ /*
+ * Since an interrupt may set up a timer, we don't want to
+ * reprogram the hardware timer with interrupts enabled.
+ * Re-enable interrupts only after returning from idle.
+ */
+ timer_dyn_reprogram();
+
+ omap2_sram_idle();
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+static int omap2_pm_prepare(suspend_state_t state)
+{
+ int error = 0;
+
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return error;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ /* FIXME: Add suspend */
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int omap2_pm_finish(suspend_state_t state)
+{
+ pm_idle = saved_idle;
+ return 0;
+}
+
+static struct pm_ops omap_pm_ops = {
+ .pm_disk_mode = 0,
+ .prepare = omap2_pm_prepare,
+ .enter = omap2_pm_enter,
+ .finish = omap2_pm_finish,
+};
+
+int __init omap2_pm_init(void)
+{
+ printk("Power Management for TI OMAP.\n");
+
+ vclk = clk_get(NULL, "virt_prcm_set");
+ if (IS_ERR(vclk)) {
+ printk(KERN_ERR "Could not get PM vclk\n");
+ return -ENODEV;
+ }
+
+ /*
+ * We copy the assembler sleep/wakeup routines to SRAM.
+ * These routines need to be in SRAM as that's the only
+ * memory the MPU can see when it wakes up.
+ */
+ omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+ omap24xx_idle_loop_suspend_sz);
+
+ omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+ omap24xx_cpu_suspend_sz);
+
+ pm_set_ops(&omap_pm_ops);
+ pm_idle = omap2_pm_idle;
+
+ return 0;
+}
+
+__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm-regs.h
index 2eb89b936c83..22ac7be4f782 100644
--- a/arch/arm/mach-omap2/prcm.h
+++ b/arch/arm/mach-omap2/prcm-regs.h
@@ -1,5 +1,7 @@
/*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/arch/arm/mach-omap2/prcm-reg.h
+ *
+ * OMAP24XX Power Reset and Clock Management (PRCM) registers
*
* Copyright (C) 2005 Texas Instruments, Inc.
*
@@ -18,8 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
-#define __ASM_ARM_ARCH_DPM_PRCM_H
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_H
/* SET_PERFORMANCE_LEVEL PARAMETERS */
#define PRCM_HALF_SPEED 1
@@ -159,54 +161,63 @@
#define CM_FCLKEN_MDM PRCM_REG32(0xC00)
#define CM_ICLKEN_MDM PRCM_REG32(0xC10)
#define CM_IDLEST_MDM PRCM_REG32(0xC20)
+#define CM_AUTOIDLE_MDM PRCM_REG32(0xC30)
#define CM_CLKSEL_MDM PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000)
+#define CM_CLKSTCTRL_MDM PRCM_REG32(0xC48)
+#define RM_RSTCTRL_MDM PRCM_REG32(0xC50)
+#define RM_RSTST_MDM PRCM_REG32(0xC58)
+#define PM_WKEN_MDM PRCM_REG32(0xCA0)
+#define PM_WKST_MDM PRCM_REG32(0xCB0)
+#define PM_WKDEP_MDM PRCM_REG32(0xCC8)
+#define PM_PWSTCTRL_MDM PRCM_REG32(0xCE0)
+#define PM_PWSTST_MDM PRCM_REG32(0xCE4)
+
+#define OMAP24XX_L4_IO_BASE 0x48000000
+
+#define DISP_BASE (OMAP24XX_L4_IO_BASE + 0x50000)
#define DISP_REG32(offset) __REG32(DISP_BASE + (offset))
-#define GPMC_BASE (OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset))
+#define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000)
+#define GPMC_REG32(offset) __REG32(OMAP24XX_GPMC_BASE + (offset))
-#define GPT1_BASE (OMAP24XX_GPT1)
+/* FIXME: Move these to timer code */
+#define GPT1_BASE (0x48028000)
#define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset))
/* Misc sysconfig */
#define DISPC_SYSCONFIG DISP_REG32(0x410)
-#define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000)
+#define SPI_BASE (OMAP24XX_L4_IO_BASE + 0x98000)
#define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG 0x5A000010
-#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG 0x5D000010
-//#define DSP_DMA_SYSCONFIG 0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C)
+#define MCSPI2_SYSCONFIG __REG32(SPI_BASE + 0x2000 + 0x10)
+#define MCSPI3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
+
+#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE + 0x2C10)
+#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE + 0x282C)
+#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE + 0x602C)
#define GPMC_SYSCONFIG GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG 0x5C060010
-#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG 0x67FFFE10
+#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE + 0x10)
+#define OMAP24XX_SMS_BASE (L3_24XX_BASE + 0x8000)
+#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE + 0x10)
+#define SSI_SYSCONFIG __REG32(DISP_BASE + 0x8010)
/* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000)
-
+#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE + 0x2A000)
+#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE + 0x78000)
+#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE + 0x7A000)
+#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE + 0x7C000)
+#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE + 0x7E000)
+#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE + 0x80000)
+#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE + 0x82000)
+#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE + 0x84000)
+#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE + 0x86000)
+#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE + 0x88000)
+#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE + 0x8A000)
+
+/* FIXME: Move these to timer code */
#define GPTIMER1_SYSCONFIG GPT1_REG32(0x010)
#define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10)
#define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10)
@@ -220,12 +231,18 @@
#define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10)
#define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10)
-#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+/* FIXME: Move these to gpio code */
+#define OMAP24XX_GPIO_BASE 0x48018000
+#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
+
+#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1) + 0x10))
+#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2) + 0x10))
+#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3) + 0x10))
+#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4) + 0x10))
-#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10))
+#if defined(CONFIG_ARCH_OMAP243X)
+#define GPIO5_SYSCONFIG __REG32((OMAP24XX_GPIO5_BASE + 0x10))
+#endif
/* GP TIMER 1 */
#define GPTIMER1_TISTAT GPT1_REG32(0x014)
@@ -243,15 +260,15 @@
#define GPTIMER1_TCAR2 GPT1_REG32(0x044)
/* rkw -- base fix up please... */
-#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018)
+#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE + 0x78018)
/* SDRC */
-#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084)
+#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x064)
+#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x068)
+#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x06C)
+#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE + 0x070)
+#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE + 0x084)
/* GPIO 1 */
#define GPIO1_BASE GPIOX_BASE(1)
@@ -278,6 +295,8 @@
#define GPIO2_DATAIN GPIO2_REG32(0x038)
#define GPIO2_OE GPIO2_REG32(0x034)
#define GPIO2_DATAOUT GPIO2_REG32(0x03C)
+#define GPIO2_DEBOUNCENABLE GPIO2_REG32(0x050)
+#define GPIO2_DEBOUNCINGTIME GPIO2_REG32(0x054)
/* GPIO 3 */
#define GPIO3_BASE GPIOX_BASE(3)
@@ -294,6 +313,8 @@
#define GPIO3_DATAOUT GPIO3_REG32(0x03C)
#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
+#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
/* GPIO 4 */
#define GPIO4_BASE GPIOX_BASE(4)
@@ -311,10 +332,26 @@
#define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050)
#define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054)
+#if defined(CONFIG_ARCH_OMAP243X)
+/* GPIO 5 */
+#define GPIO5_REG32(offset) __REG32((OMAP24XX_GPIO5_BASE + (offset)))
+#define GPIO5_IRQENABLE1 GPIO5_REG32(0x01C)
+#define GPIO5_IRQSTATUS1 GPIO5_REG32(0x018)
+#define GPIO5_IRQENABLE2 GPIO5_REG32(0x02C)
+#define GPIO5_IRQSTATUS2 GPIO5_REG32(0x028)
+#define GPIO5_WAKEUPENABLE GPIO5_REG32(0x020)
+#define GPIO5_RISINGDETECT GPIO5_REG32(0x048)
+#define GPIO5_FALLINGDETECT GPIO5_REG32(0x04C)
+#define GPIO5_DATAIN GPIO5_REG32(0x038)
+#define GPIO5_OE GPIO5_REG32(0x034)
+#define GPIO5_DATAOUT GPIO5_REG32(0x03C)
+#define GPIO5_DEBOUNCENABLE GPIO5_REG32(0x050)
+#define GPIO5_DEBOUNCINGTIME GPIO5_REG32(0x054)
+#endif
/* IO CONFIG */
-#define CONTROL_BASE (OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset))
+#define OMAP24XX_CTRL_BASE (L4_24XX_BASE)
+#define CONTROL_REG32(offset) __REG32(OMAP24XX_CTRL_BASE + (offset))
#define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104)
#define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134)
@@ -322,15 +359,18 @@
#define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C)
#define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090)
#define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) /* 2420 */
#define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0)
#define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC)
+#define CONTROL_PADCONF_SYS_NIRQW0 CONTROL_REG32(0x0BC) /* 2430 */
+#define CONTROL_PADCONF_SSI1_FLAG_TX CONTROL_REG32(0x108) /* 2430 */
/* CONTROL */
#define CONTROL_DEVCONF CONTROL_REG32(0x274)
+#define CONTROL_DEVCONF1 CONTROL_REG32(0x2E8)
/* INTERRUPT CONTROLLER */
-#define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_BASE ((L4_24XX_BASE) + 0xfe000)
#define INTC_REG32(offset) __REG32(INTC_BASE + (offset))
#define INTC1_U_BASE INTC_REG32(0x000)
@@ -348,10 +388,12 @@
#define INTC_ISR_CLEAR2 INTC_REG32(0x0D4)
#define INTC_SIR_IRQ INTC_REG32(0x040)
#define INTC_CONTROL INTC_REG32(0x048)
-#define INTC_ILR11 INTC_REG32(0x12C)
+#define INTC_ILR11 INTC_REG32(0x12C) /* PRCM on MPU PIC */
+#define INTC_ILR30 INTC_REG32(0x178)
+#define INTC_ILR31 INTC_REG32(0x17C)
#define INTC_ILR32 INTC_REG32(0x180)
-#define INTC_ILR37 INTC_REG32(0x194)
-#define INTC_SYSCONFIG INTC_REG32(0x010)
+#define INTC_ILR37 INTC_REG32(0x194) /* GPIO4 on MPU PIC */
+#define INTC_SYSCONFIG INTC_REG32(0x010) /* GPT1 on MPU PIC */
/* RAM FIREWALL */
#define RAMFW_BASE (0x68005000)
@@ -373,6 +415,24 @@
#define GPMC_CONFIG6_0 GPMC_REG32(0x074)
#define GPMC_CONFIG7_0 GPMC_REG32(0x078)
+/* GPMC CS1 */
+#define GPMC_CONFIG1_1 GPMC_REG32(0x090)
+#define GPMC_CONFIG2_1 GPMC_REG32(0x094)
+#define GPMC_CONFIG3_1 GPMC_REG32(0x098)
+#define GPMC_CONFIG4_1 GPMC_REG32(0x09C)
+#define GPMC_CONFIG5_1 GPMC_REG32(0x0a0)
+#define GPMC_CONFIG6_1 GPMC_REG32(0x0a4)
+#define GPMC_CONFIG7_1 GPMC_REG32(0x0a8)
+
+/* GPMC CS3 */
+#define GPMC_CONFIG1_3 GPMC_REG32(0x0F0)
+#define GPMC_CONFIG2_3 GPMC_REG32(0x0F4)
+#define GPMC_CONFIG3_3 GPMC_REG32(0x0F8)
+#define GPMC_CONFIG4_3 GPMC_REG32(0x0FC)
+#define GPMC_CONFIG5_3 GPMC_REG32(0x100)
+#define GPMC_CONFIG6_3 GPMC_REG32(0x104)
+#define GPMC_CONFIG7_3 GPMC_REG32(0x108)
+
/* DSS */
#define DSS_CONTROL DISP_REG32(0x040)
#define DISPC_CONTROL DISP_REG32(0x440)
@@ -405,11 +465,15 @@
#define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8)
#define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC)
-/* Wake up define for board */
-#define GPIO97 (1 << 1)
-#define GPIO88 (1 << 24)
+/* HSUSB Suspend */
+#define HSUSB_CTRL __REG8(0x480AC001)
+#define USBOTG_POWER __REG32(0x480AC000)
+
+/* HS MMC */
+#define MMCHS1_SYSCONFIG __REG32(0x4809C010)
+#define MMCHS2_SYSCONFIG __REG32(0x480b4010)
-#endif /* __ASSEMBLER__ */
+#endif /* __ASSEMBLER__ */
#endif
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
new file mode 100644
index 000000000000..8893479dc7e0
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm.c
@@ -0,0 +1,40 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm.c
+ *
+ * OMAP 24xx Power Reset and Clock Management (PRCM) functions
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include "prcm-regs.h"
+
+u32 omap_prcm_get_reset_sources(void)
+{
+ return RM_RSTST_WKUP & 0x7f;
+}
+EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+
+/* Resets clock rates and reboots the system. Only called from system.h */
+void omap_prcm_arch_reset(char mode)
+{
+ u32 rate;
+ struct clk *vclk, *sclk;
+
+ vclk = clk_get(NULL, "virt_prcm_set");
+ sclk = clk_get(NULL, "sys_ck");
+ rate = clk_get_rate(sclk);
+ clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */
+ RM_RSTCTRL_WKUP |= 2;
+}
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644
index 000000000000..00299cbeb911
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep.S
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+#define A_32KSYNC_CR_V IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+#define A_PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+#define A_PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+#define A_CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+#define A_CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+#define A_CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+#define A_CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
+
+#define A_SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+#define A_SDRC_POWER_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+#define A_SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
+#define A_SDRC0_V (0xC0000000)
+#define A_SDRC_MANUAL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+ .text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ * wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap24xx_idle_loop_suspend)
+ stmfd sp!, {r0, lr} @ save registers on stack
+ mov r0, #0 @ clear for mcr setup
+ mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
+ ldmfd sp!, {r0, pc} @ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+ .word . - omap24xx_idle_loop_suspend
+
+/*
+ * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown. Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 : DLL ctrl value pre-Sleep
+ * R1 : Processor+Revision
+ * 2420: 0x21 = 242xES1, 0x26 = 242xES2.2
+ * 2430: 0x31 = 2430ES1, 0x32 = 2430ES2
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't. We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL. Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+ stmfd sp!, {r0 - r12, lr} @ save registers on stack
+ mov r3, #0x0 @ clear for mrc call
+ mcr p15, 0, r3, c7, c10, 4 @ memory barrier, hope SDR/DDR finished
+ nop
+ nop
+ ldr r3, A_SDRC_POWER @ addr of sdrc power
+ ldr r4, [r3] @ value of sdrc power
+ orr r4, r4, #0x40 @ enable self refresh on idle req
+ mov r5, #0x2000 @ set delay (DPLL relock + DLL relock)
+ str r4, [r3] @ make it so
+ mov r2, #0
+ nop
+ mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+ nop
+loop:
+ subs r5, r5, #0x1 @ awake, wait just a bit
+ bne loop
+
+ /* The DPLL has on before we take the DDR out of self refresh */
+ bic r4, r4, #0x40 @ now clear self refresh bit.
+ str r4, [r3] @ put vlaue back.
+ ldr r4, A_SDRC0 @ make a clock happen
+ ldr r4, [r4]
+ nop @ start auto refresh only after clk ok
+ movs r0, r0 @ see if DDR or SDR
+ ldrne r1, A_SDRC_DLLA_CTRL_S @ get addr of DLL ctrl
+ strne r0, [r1] @ rewrite DLLA to force DLL reload
+ addne r1, r1, #0x8 @ move to DLLB
+ strne r0, [r1] @ rewrite DLLB to force DLL reload
+
+ mov r5, #0x1000
+loop2:
+ subs r5, r5, #0x1
+ bne loop2
+ /* resume*/
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+
+A_SDRC_POWER:
+ .word A_SDRC_POWER_V
+A_SDRC0:
+ .word A_SDRC0_V
+A_CM_CLKSEL2_PLL_S:
+ .word A_CM_CLKSEL2_PLL_V
+A_CM_CLKEN_PLL:
+ .word A_CM_CLKEN_PLL_V
+A_SDRC_DLLA_CTRL_S:
+ .word A_SDRC_DLLA_CTRL_V
+A_SDRC_MANUAL_S:
+ .word A_SDRC_MANUAL_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+ .word . - omap24xx_cpu_suspend
+
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
index 2a869e203342..d261e4ff4d9b 100644
--- a/arch/arm/mach-omap2/sram-fn.S
+++ b/arch/arm/mach-omap2/sram-fn.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap1/sram.S
+ * linux/arch/arm/mach-omap2/sram.S
*
* Omap2 specific functions that need to be run in internal SRAM
*
@@ -28,7 +28,7 @@
#include <asm/arch/io.h>
#include <asm/hardware.h>
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index b371d723635f..8a25a1c8019f 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -196,12 +196,9 @@ static int __init corgi_ssp_probe(struct platform_device *dev)
int ret;
/* Chip Select - Disable All */
- GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */
- GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
- GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */
- GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
- GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */
- GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
+ pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH);
+ pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
+ pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index b45560a8f6c4..a042473deedd 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -307,6 +307,10 @@ static void __init fixup_poodle(struct machine_desc *desc,
struct tag *tags, char **cmdline, struct meminfo *mi)
{
sharpsl_save_param();
+ mi->nr_banks=1;
+ mi->bank[0].start = 0xa0000000;
+ mi->bank[0].node = 0;
+ mi->bank[0].size = (32*1024*1024);
}
MACHINE_START(POODLE, "SHARP Poodle")
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index ed07c4149d82..ce7d81000695 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -50,9 +50,15 @@ config MACH_N30
<http://zoo.weinigel.se/n30>.
+config MACH_SMDK
+ bool
+ help
+ Common machine code for SMDK2410 and SMDK2440
+
config ARCH_SMDK2410
bool "SMDK2410/A9M2410"
select CPU_S3C2410
+ select MACH_SMDK
help
Say Y here if you are using the SMDK2410 or the derived module A9M2410
<http://www.fsforth.de>
@@ -60,6 +66,7 @@ config ARCH_SMDK2410
config ARCH_S3C2440
bool "SMDK2440"
select CPU_S3C2440
+ select MACH_SMDK
help
Say Y here if you are using the SMDK2440.
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 1b3b476e5637..3e5712db6b52 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -48,3 +48,5 @@ obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
obj-$(CONFIG_MACH_OTOM) += mach-otom.o
obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+
+obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index fec02c92f95f..6de713ad319a 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -249,7 +249,7 @@ static int s3c24xx_upll_enable(struct clk *clk, int enable)
/* if we started the UPLL, then allow to settle */
- if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF))
+ if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
udelay(200);
return 0;
@@ -367,6 +367,8 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
source = S3C2410_MISCCR_CLK0_UPLL;
else if (parent == &clk_f)
source = S3C2410_MISCCR_CLK0_FCLK;
+ else if (parent == &clk_h)
+ source = S3C2410_MISCCR_CLK0_HCLK;
else if (parent == &clk_p)
source = S3C2410_MISCCR_CLK0_PCLK;
else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
@@ -376,6 +378,8 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
else
return -EINVAL;
+ clk->parent = parent;
+
if (clk == &s3c24xx_dclk0)
mask = S3C2410_MISCCR_CLK0_MASK;
else {
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
new file mode 100644
index 000000000000..c940890f621f
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -0,0 +1,135 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/arch/nand.h>
+
+#include "common-smdk.h"
+#include "devs.h"
+#include "pm.h"
+
+/* NAND parititon from 2.4.18-swl5 */
+
+static struct mtd_partition smdk_default_nand_part[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_16K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "S3C2410 flash partition 1",
+ .offset = 0,
+ .size = SZ_2M,
+ },
+ [2] = {
+ .name = "S3C2410 flash partition 2",
+ .offset = SZ_4M,
+ .size = SZ_4M,
+ },
+ [3] = {
+ .name = "S3C2410 flash partition 3",
+ .offset = SZ_8M,
+ .size = SZ_2M,
+ },
+ [4] = {
+ .name = "S3C2410 flash partition 4",
+ .offset = SZ_1M * 10,
+ .size = SZ_4M,
+ },
+ [5] = {
+ .name = "S3C2410 flash partition 5",
+ .offset = SZ_1M * 14,
+ .size = SZ_1M * 10,
+ },
+ [6] = {
+ .name = "S3C2410 flash partition 6",
+ .offset = SZ_1M * 24,
+ .size = SZ_1M * 24,
+ },
+ [7] = {
+ .name = "S3C2410 flash partition 7",
+ .offset = SZ_1M * 48,
+ .size = SZ_16M,
+ }
+};
+
+static struct s3c2410_nand_set smdk_nand_sets[] = {
+ [0] = {
+ .name = "NAND",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(smdk_default_nand_part),
+ .partitions = smdk_default_nand_part,
+ },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand smdk_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(smdk_nand_sets),
+ .sets = smdk_nand_sets,
+};
+
+/* devices we initialise */
+
+static struct platform_device __initdata *smdk_devs[] = {
+ &s3c_device_nand,
+};
+
+void __init smdk_machine_init(void)
+{
+ /* Configure the LEDs (even if we have no LED support)*/
+
+ s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+ s3c2410_gpio_setpin(S3C2410_GPF4, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF5, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF6, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF7, 1);
+
+ s3c_device_nand.dev.platform_data = &smdk_nand_info;
+
+ platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
+
+ s3c2410_pm_init();
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h
new file mode 100644
index 000000000000..0e3a3be330a3
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 3e327b8e46be..cc97fbf66291 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -232,8 +232,8 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
static struct s3c2410_platform_nand anubis_nand_info = {
.tacls = 25,
- .twrph0 = 80,
- .twrph1 = 80,
+ .twrph0 = 55,
+ .twrph1 = 40,
.nr_sets = ARRAY_SIZE(anubis_nand_sets),
.sets = anubis_nand_sets,
.select_chip = anubis_nand_select,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 0260ed5ab946..306afc1d7cd3 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -32,6 +32,11 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -46,6 +51,7 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
#include <asm/arch/fb.h>
#include "clock.h"
@@ -170,12 +176,39 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
},
};
+static struct mtd_partition rx3715_nand_part[] = {
+ [0] = {
+ .name = "Whole Flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE,
+ }
+};
+
+static struct s3c2410_nand_set rx3715_nand_sets[] = {
+ [0] = {
+ .name = "Internal",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(rx3715_nand_part),
+ .partitions = rx3715_nand_part,
+ },
+};
+
+static struct s3c2410_platform_nand rx3715_nand_info = {
+ .tacls = 25,
+ .twrph0 = 50,
+ .twrph1 = 15,
+ .nr_sets = ARRAY_SIZE(rx3715_nand_sets),
+ .sets = rx3715_nand_sets,
+};
+
static struct platform_device *rx3715_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
+ &s3c_device_nand,
};
static struct s3c24xx_board rx3715_board __initdata = {
@@ -185,6 +218,8 @@ static struct s3c24xx_board rx3715_board __initdata = {
static void __init rx3715_map_io(void)
{
+ s3c_device_nand.dev.platform_data = &rx3715_nand_info;
+
s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
s3c24xx_init_clocks(16934000);
s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 1e76e1fdfcea..2db932d72c5a 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -28,7 +28,8 @@
* Ben Dooks <ben@simtec.co.uk>
*
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- * 20-Sep-2005 BJD Added static to non-exported items
+ * 20-Sep-2005 BJD Added static to non-exported items
+ * 01-Apr-2006 BJD Moved init code to common smdk
*
***********************************************************************/
@@ -54,6 +55,8 @@
#include "devs.h"
#include "cpu.h"
+#include "common-smdk.h"
+
static struct map_desc smdk2410_iodesc[] __initdata = {
/* nothing here yet */
};
@@ -107,11 +110,6 @@ static void __init smdk2410_map_io(void)
s3c24xx_set_board(&smdk2410_board);
}
-static void __init smdk2410_init_irq(void)
-{
- s3c24xx_init_irq();
-}
-
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
@@ -119,7 +117,8 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
- .init_irq = smdk2410_init_irq,
+ .init_irq = s3c24xx_init_irq,
+ .init_machine = smdk_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index f4315721c3b8..5fffd1d51047 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -53,7 +53,8 @@
#include "clock.h"
#include "devs.h"
#include "cpu.h"
-#include "pm.h"
+
+#include "common-smdk.h"
static struct map_desc smdk2440_iodesc[] __initdata = {
/* ISA IO Space map (memory space selected by A24) */
@@ -197,21 +198,9 @@ static void __init smdk2440_map_io(void)
static void __init smdk2440_machine_init(void)
{
- /* Configure the LEDs (even if we have no LED support)*/
-
- s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
-
- s3c2410_gpio_setpin(S3C2410_GPF4, 0);
- s3c2410_gpio_setpin(S3C2410_GPF5, 0);
- s3c2410_gpio_setpin(S3C2410_GPF6, 0);
- s3c2410_gpio_setpin(S3C2410_GPF7, 0);
-
s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
- s3c2410_pm_init();
+ smdk_machine_init();
}
MACHINE_START(S3C2440, "SMDK2440")
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index 57a15974d4b5..d7a30ed6c327 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -139,7 +139,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
clkdivn = __raw_readl(S3C2410_CLKDIVN);
clkdivn |= S3C2440_CLKDIVN_UCLK;
- __raw_writel(camdivn, S3C2410_CLKDIVN);
+ __raw_writel(clkdivn, S3C2410_CLKDIVN);
mutex_unlock(&clocks_mutex);
}
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 102454082474..676b5c5b75bb 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -11,7 +11,8 @@
* published by the Free Software Foundation.
*
* ChangeLog:
- * 03-06-2004 John Lenz <jelenz@wisc.edu>
+ * 2006 Pavel Machek <pavel@suse.cz>
+ * 03-06-2004 John Lenz <lenz@cs.wisc.edu>
* 06-04-2002 Chris Larson <kergoth@digitalnemesis.net>
* 04-16-2001 Lineo Japan,Inc. ...
*/
@@ -87,12 +88,75 @@ static struct mcp_plat_data collie_mcp_data = {
.sclk_rate = 11981000,
};
+#ifdef CONFIG_SHARP_LOCOMO
+/*
+ * low-level UART features.
+ */
+static struct locomo_dev *uart_dev = NULL;
+
+static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (!uart_dev) return;
+
+ if (mctrl & TIOCM_RTS)
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+ else
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+
+ if (mctrl & TIOCM_DTR)
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+ else
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+}
+
+static u_int collie_uart_get_mctrl(struct uart_port *port)
+{
+ int ret = TIOCM_CD;
+ unsigned int r;
+ if (!uart_dev) return ret;
+
+ r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+ if (r & LOCOMO_GPIO_CTS)
+ ret |= TIOCM_CTS;
+ if (r & LOCOMO_GPIO_DSR)
+ ret |= TIOCM_DSR;
+
+ return ret;
+}
static struct sa1100_port_fns collie_port_fns __initdata = {
.set_mctrl = collie_uart_set_mctrl,
.get_mctrl = collie_uart_get_mctrl,
};
+static int collie_uart_probe(struct locomo_dev *dev)
+{
+ uart_dev = dev;
+ return 0;
+}
+
+static int collie_uart_remove(struct locomo_dev *dev)
+{
+ uart_dev = NULL;
+ return 0;
+}
+
+static struct locomo_driver collie_uart_driver = {
+ .drv = {
+ .name = "collie_uart",
+ },
+ .devid = LOCOMO_DEVID_UART,
+ .probe = collie_uart_probe,
+ .remove = collie_uart_remove,
+};
+
+static int __init collie_uart_init(void) {
+ return locomo_driver_register(&collie_uart_driver);
+}
+device_initcall(collie_uart_init);
+
+#endif
+
static struct resource locomo_resources[] = {
[0] = {
@@ -218,6 +282,12 @@ static void __init collie_map_io(void)
{
sa1100_map_io();
iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc));
+
+#ifdef CONFIG_SHARP_LOCOMO
+ sa1100_register_uart_fns(&collie_port_fns);
+#endif
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
}
MACHINE_START(COLLIE, "Sharp-Collie")
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 5c4055b62d97..54e3c5bb5186 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -10,7 +10,7 @@
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/hardware.h>
+#include <asm/memory.h>
#include <asm/page.h>
#include "proc-macros.S"
@@ -46,6 +46,11 @@
*/
#define CACHE_DLIMIT (CACHE_DSIZE * 4)
+ .data
+flush_base:
+ .long FLUSH_BASE
+ .text
+
/*
* flush_user_cache_all()
*
@@ -63,11 +68,21 @@ ENTRY(v4wb_flush_kern_cache_all)
mov ip, #0
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
__flush_whole_cache:
- mov r0, #FLUSH_BASE
- add r1, r0, #CACHE_DSIZE
-1: ldr r2, [r0], #32
- cmp r0, r1
+ ldr r3, =flush_base
+ ldr r1, [r3, #0]
+ eor r1, r1, #CACHE_DSIZE
+ str r1, [r3, #0]
+ add r2, r1, #CACHE_DSIZE
+1: ldr r3, [r1], #32
+ cmp r1, r2
+ blo 1b
+#ifdef FLUSH_BASE_MINICACHE
+ add r2, r2, #FLUSH_BASE_MINICACHE - FLUSH_BASE
+ sub r1, r2, #512 @ only 512 bytes
+1: ldr r3, [r1], #32
+ cmp r1, r2
blo 1b
+#endif
mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
mov pc, lr
@@ -82,6 +97,7 @@ __flush_whole_cache:
* - flags - vma_area_struct flags describing address space
*/
ENTRY(v4wb_flush_user_cache_range)
+ mov ip, #0
sub r3, r1, r0 @ calculate total size
tst r2, #VM_EXEC @ executable region?
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 8a1bfcd50087..50e6b6bfb2e2 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <asm/memory.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/sizes.h>
@@ -272,6 +273,17 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{
+ if (arch_is_coherent()) {
+ void *virt;
+
+ virt = kmalloc(size, gfp);
+ if (!virt)
+ return NULL;
+ *handle = virt_to_dma(dev, virt);
+
+ return virt;
+ }
+
return __dma_alloc(dev, size, handle, gfp,
pgprot_noncached(pgprot_kernel));
}
@@ -350,6 +362,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
WARN_ON(irqs_disabled());
+ if (arch_is_coherent()) {
+ kfree(cpu_addr);
+ return;
+ }
+
size = PAGE_ALIGN(size);
spin_lock_irqsave(&consistent_lock, flags);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 88279124317a..9ea1f87a7079 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -20,6 +20,7 @@
#include <asm/mach-types.h>
#include <asm/setup.h>
+#include <asm/sizes.h>
#include <asm/tlb.h>
#include <asm/mach/arch.h>
@@ -455,14 +456,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
#ifdef FLUSH_BASE
map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
map.virtual = FLUSH_BASE;
- map.length = PGDIR_SIZE;
+ map.length = SZ_1M;
map.type = MT_CACHECLEAN;
create_mapping(&map);
#endif
#ifdef FLUSH_BASE_MINICACHE
- map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + PGDIR_SIZE);
+ map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
map.virtual = FLUSH_BASE_MINICACHE;
- map.length = PGDIR_SIZE;
+ map.length = SZ_1M;
map.type = MT_MINICLEAN;
create_mapping(&map);
#endif
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 5e5d05bcad50..f14b2d0f3690 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -389,6 +389,17 @@ void __init build_mem_type_table(void)
kern_pgprot = user_pgprot = cp->pte;
/*
+ * Enable CPU-specific coherency if supported.
+ * (Only available on XSC3 at the moment.)
+ */
+ if (arch_is_coherent()) {
+ if (cpu_is_xsc3()) {
+ mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+ mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+ }
+ }
+
+ /*
* ARMv6 and above have extended page tables.
*/
if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index c916a6cae404..a2dd5ae1077d 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -26,22 +26,7 @@
* the cache line size of the I and D cache
*/
#define DCACHELINESIZE 32
-#define FLUSH_OFFSET 32768
- .macro flush_110_dcache rd, ra, re
- ldr \rd, =flush_base
- ldr \ra, [\rd]
- eor \ra, \ra, #FLUSH_OFFSET
- str \ra, [\rd]
- add \re, \ra, #16384 @ only necessary for 16k
-1001: ldr \rd, [\ra], #DCACHELINESIZE
- teq \re, \ra
- bne 1001b
- .endm
-
- .data
-flush_base:
- .long FLUSH_BASE
.text
/*
@@ -145,13 +130,11 @@ ENTRY(cpu_sa110_dcache_clean_area)
*/
.align 5
ENTRY(cpu_sa110_switch_mm)
- flush_110_dcache r3, ip, r1
- mov r1, #0
- mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
+ str lr, [sp, #-4]!
+ bl v4wb_flush_kern_cache_all @ clears IP
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
- mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, lr
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ ldr pc, [sp], #4
/*
* cpu_sa110_set_pte(ptep, pte)
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 41f21f2dd8ff..777ad99c1439 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -30,30 +30,6 @@
* the cache line size of the I and D cache
*/
#define DCACHELINESIZE 32
-#define FLUSH_OFFSET 32768
-
- .macro flush_1100_dcache rd, ra, re
- ldr \rd, =flush_base
- ldr \ra, [\rd]
- eor \ra, \ra, #FLUSH_OFFSET
- str \ra, [\rd]
- add \re, \ra, #8192 @ only necessary for 8k
-1001: ldr \rd, [\ra], #DCACHELINESIZE
- teq \re, \ra
- bne 1001b
-#ifdef FLUSH_BASE_MINICACHE
- add \ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
- add \re, \ra, #512 @ only 512 bytes
-1002: ldr \rd, [\ra], #DCACHELINESIZE
- teq \re, \ra
- bne 1002b
-#endif
- .endm
-
- .data
-flush_base:
- .long FLUSH_BASE
- .text
__INIT
@@ -79,9 +55,8 @@ ENTRY(cpu_sa1100_proc_fin)
stmfd sp!, {lr}
mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
- flush_1100_dcache r0, r1, r2 @ clean caches
- mov r0, #0
- mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
+ bl v4wb_flush_kern_cache_all
+ mcr p15, 0, ip, c15, c2, 2 @ Disable clock switching
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
@@ -167,14 +142,12 @@ ENTRY(cpu_sa1100_dcache_clean_area)
*/
.align 5
ENTRY(cpu_sa1100_switch_mm)
- flush_1100_dcache r3, ip, r1
- mov ip, #0
- mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ str lr, [sp, #-4]!
+ bl v4wb_flush_kern_cache_all @ clears IP
mcr p15, 0, ip, c9, c0, 0 @ invalidate RB
- mcr p15, 0, ip, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, lr
+ ldr pc, [sp], #4
/*
* cpu_sa1100_set_pte(ptep, pte)
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index b9dfce57c272..80873b36c3f7 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -371,7 +371,7 @@ ENTRY(cpu_xsc3_switch_mm)
ENTRY(cpu_xsc3_set_pte)
str r1, [r0], #-2048 @ linux version
- bic r2, r1, #0xff0
+ bic r2, r1, #0xdf0 @ Keep C, B, coherency bits
orr r2, r2, #PTE_TYPE_EXT @ extended page
eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 0887bb2a2551..ec49495e651e 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -70,13 +70,13 @@ config OMAP_MPU_TIMER
config OMAP_32K_TIMER
bool "Use 32KHz timer"
- depends on ARCH_OMAP16XX
+ depends on ARCH_OMAP16XX || ARCH_OMAP24XX
help
Select this option if you want to enable the OMAP 32KHz timer.
This timer saves power compared to the OMAP_MPU_TIMER, and has
support for no tick during idle. The 32KHz timer provides less
intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
- currently only available for OMAP-16xx.
+ currently only available for OMAP16XX and 24XX.
endchoice
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9ccf1943fc94..2896b4546411 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,16 +3,16 @@
#
# Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+
# OCPI interconnect support for 1710, 1610 and 5912
obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
-# Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 3c2bfc0efdaf..32ec04c58bcd 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -21,6 +21,7 @@
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/semaphore.h>
@@ -37,17 +38,38 @@ static struct clk_functions *arch_clock;
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
+/*
+ * 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;
@@ -59,6 +81,9 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_enable)
ret = arch_clock->clk_enable(clk);
@@ -72,6 +97,9 @@ void clk_disable(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_disable)
arch_clock->clk_disable(clk);
@@ -84,6 +112,9 @@ int clk_get_usecount(struct clk *clk)
unsigned long flags;
int ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->usecount;
spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -97,6 +128,9 @@ unsigned long clk_get_rate(struct clk *clk)
unsigned long flags;
unsigned long ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->rate;
spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -121,6 +155,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
unsigned long flags;
long ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_round_rate)
ret = arch_clock->clk_round_rate(clk, rate);
@@ -133,7 +170,10 @@ EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_set_rate)
@@ -147,7 +187,10 @@ EXPORT_SYMBOL(clk_set_rate);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
+ return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_set_parent)
@@ -163,6 +206,9 @@ struct clk *clk_get_parent(struct clk *clk)
unsigned long flags;
struct clk * ret = NULL;
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_get_parent)
ret = arch_clock->clk_get_parent(clk);
@@ -199,6 +245,9 @@ __setup("mpurate=", omap_clk_setup);
/* Used for clocks that always have same value as the parent clock */
void followparent_recalc(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
clk->rate = clk->parent->rate;
}
@@ -207,6 +256,9 @@ void propagate_rate(struct clk * tclk)
{
struct clk *clkp;
+ if (tclk == NULL || IS_ERR(tclk))
+ return;
+
list_for_each_entry(clkp, &clocks, node) {
if (likely(clkp->parent != tclk))
continue;
@@ -217,6 +269,9 @@ void propagate_rate(struct clk * tclk)
int clk_register(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
if (clk->init)
@@ -229,6 +284,9 @@ 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);
@@ -239,6 +297,9 @@ void clk_deny_idle(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_deny_idle)
arch_clock->clk_deny_idle(clk);
@@ -250,6 +311,9 @@ void clk_allow_idle(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_allow_idle)
arch_clock->clk_allow_idle(clk);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 9dcce904b608..5d5d6eb222dd 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -24,14 +24,7 @@
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-
-
-void omap_nop_release(struct device *dev)
-{
- /* Nothing */
-}
-
-/*-------------------------------------------------------------------------*/
+#include <asm/arch/menelaus.h>
#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
@@ -58,9 +51,6 @@ static struct resource i2c_resources1[] = {
static struct platform_device omap_i2c_device1 = {
.name = "i2c_omap",
.id = 1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(i2c_resources1),
.resource = i2c_resources1,
};
@@ -98,6 +88,62 @@ static inline void omap_init_i2c(void) {}
#endif
/*-------------------------------------------------------------------------*/
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+static void omap_init_kp(void)
+{
+ if (machine_is_omap_h2() || machine_is_omap_h3()) {
+ omap_cfg_reg(F18_1610_KBC0);
+ omap_cfg_reg(D20_1610_KBC1);
+ omap_cfg_reg(D19_1610_KBC2);
+ omap_cfg_reg(E18_1610_KBC3);
+ omap_cfg_reg(C21_1610_KBC4);
+
+ omap_cfg_reg(G18_1610_KBR0);
+ omap_cfg_reg(F19_1610_KBR1);
+ omap_cfg_reg(H14_1610_KBR2);
+ omap_cfg_reg(E20_1610_KBR3);
+ omap_cfg_reg(E19_1610_KBR4);
+ omap_cfg_reg(N19_1610_KBR5);
+ } else if (machine_is_omap_perseus2()) {
+ omap_cfg_reg(E2_730_KBR0);
+ omap_cfg_reg(J7_730_KBR1);
+ omap_cfg_reg(E1_730_KBR2);
+ omap_cfg_reg(F3_730_KBR3);
+ omap_cfg_reg(D2_730_KBR4);
+
+ omap_cfg_reg(C2_730_KBC0);
+ omap_cfg_reg(D3_730_KBC1);
+ omap_cfg_reg(E4_730_KBC2);
+ omap_cfg_reg(F4_730_KBC3);
+ omap_cfg_reg(E3_730_KBC4);
+ } else if (machine_is_omap_h4()) {
+ omap_cfg_reg(T19_24XX_KBR0);
+ omap_cfg_reg(R19_24XX_KBR1);
+ omap_cfg_reg(V18_24XX_KBR2);
+ omap_cfg_reg(M21_24XX_KBR3);
+ omap_cfg_reg(E5__24XX_KBR4);
+ if (omap_has_menelaus()) {
+ omap_cfg_reg(B3__24XX_KBR5);
+ omap_cfg_reg(AA4_24XX_KBC2);
+ omap_cfg_reg(B13_24XX_KBC6);
+ } else {
+ omap_cfg_reg(M18_24XX_KBR5);
+ omap_cfg_reg(H19_24XX_KBC2);
+ omap_cfg_reg(N19_24XX_KBC6);
+ }
+ omap_cfg_reg(R20_24XX_KBC0);
+ omap_cfg_reg(M14_24XX_KBC1);
+ omap_cfg_reg(V17_24XX_KBC3);
+ omap_cfg_reg(P21_24XX_KBC4);
+ omap_cfg_reg(L14_24XX_KBC5);
+ }
+}
+#else
+static inline void omap_init_kp(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
@@ -130,7 +176,6 @@ static struct platform_device mmc_omap_device1 = {
.name = "mmci-omap",
.id = 1,
.dev = {
- .release = omap_nop_release,
.dma_mask = &mmc1_dmamask,
.platform_data = &mmc1_conf,
},
@@ -160,7 +205,6 @@ static struct platform_device mmc_omap_device2 = {
.name = "mmci-omap",
.id = 2,
.dev = {
- .release = omap_nop_release,
.dma_mask = &mmc2_dmamask,
.platform_data = &mmc2_conf,
},
@@ -240,6 +284,52 @@ static void __init omap_init_mmc(void)
static inline void omap_init_mmc(void) {}
#endif
+/*-------------------------------------------------------------------------*/
+
+/* Numbering for the SPI-capable controllers when used for SPI:
+ * spi = 1
+ * uwire = 2
+ * mmc1..2 = 3..4
+ * mcbsp1..3 = 5..7
+ */
+
+#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE)
+
+#define OMAP_UWIRE_BASE 0xfffb3000
+
+static struct resource uwire_resources[] = {
+ {
+ .start = OMAP_UWIRE_BASE,
+ .end = OMAP_UWIRE_BASE + 0x20,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device omap_uwire_device = {
+ .name = "omap_uwire",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(uwire_resources),
+ .resource = uwire_resources,
+};
+
+static void omap_init_uwire(void)
+{
+ /* FIXME define and use a boot tag; not all boards will be hooking
+ * up devices to the microwire controller, and multi-board configs
+ * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
+ */
+
+ /* board-specific code must configure chipselects (only a few
+ * are normally used) and SCLK/SDI/SDO (each has two choices).
+ */
+ (void) platform_device_register(&omap_uwire_device);
+}
+#else
+static inline void omap_init_uwire(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
#ifdef CONFIG_ARCH_OMAP24XX
@@ -259,9 +349,6 @@ static struct resource wdt_resources[] = {
static struct platform_device omap_wdt_device = {
.name = "omap_wdt",
.id = -1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(wdt_resources),
.resource = wdt_resources,
};
@@ -295,9 +382,6 @@ static struct resource rng_resources[] = {
static struct platform_device omap_rng_device = {
.name = "omap_rng",
.id = -1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(rng_resources),
.resource = rng_resources,
};
@@ -310,40 +394,6 @@ static void omap_init_rng(void)
static inline void omap_init_rng(void) {}
#endif
-#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
-
-static struct omap_lcd_config omap_fb_conf;
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-
-static struct platform_device omap_fb_device = {
- .name = "omapfb",
- .id = -1,
- .dev = {
- .release = omap_nop_release,
- .dma_mask = &omap_fb_dma_mask,
- .coherent_dma_mask = ~(u32)0,
- .platform_data = &omap_fb_conf,
- },
- .num_resources = 0,
-};
-
-static inline void omap_init_fb(void)
-{
- const struct omap_lcd_config *conf;
-
- conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
- if (conf != NULL)
- omap_fb_conf = *conf;
- platform_device_register(&omap_fb_device);
-}
-
-#else
-
-static inline void omap_init_fb(void) {}
-
-#endif
-
/*
* This gets called after board-specific INIT_MACHINE, and initializes most
* on-chip peripherals accessible on this board (except for few like USB):
@@ -369,9 +419,10 @@ static int __init omap_init_devices(void)
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
- omap_init_fb();
omap_init_i2c();
+ omap_init_kp();
omap_init_mmc();
+ omap_init_uwire();
omap_init_wdt();
omap_init_rng();
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index a4e5ac77f6df..5dac4230360d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1258,6 +1258,11 @@ void omap_stop_lcd_dma(void)
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
}
+int omap_lcd_dma_ext_running(void)
+{
+ return lcd_dma.ext_ctrl && lcd_dma.active;
+}
+
/*----------------------------------------------------------------------------*/
static int __init omap_init_dma(void)
@@ -1389,6 +1394,7 @@ EXPORT_SYMBOL(omap_free_lcd_dma);
EXPORT_SYMBOL(omap_enable_lcd_dma);
EXPORT_SYMBOL(omap_setup_lcd_dma);
EXPORT_SYMBOL(omap_stop_lcd_dma);
+EXPORT_SYMBOL(omap_lcd_dma_ext_running);
EXPORT_SYMBOL(omap_set_lcd_dma_b1);
EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 38d7ebf87920..eba3cb52ad87 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -97,6 +97,32 @@ int omap_dm_timers_active(void)
}
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+ int n;
+
+ /* If ARMXOR cannot be idled this function call is unnecessary */
+ if (!(inputmask & (1 << 1)))
+ return inputmask;
+
+ /* If any active timer is using ARMXOR return modified mask */
+ for (n = 0; dm_timers[n].base; ++n)
+ if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)&
+ OMAP_TIMER_CTRL_ST) {
+ if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0)
+ inputmask &= ~(1 << 1);
+ else
+ inputmask &= ~(1 << 2);
+ }
+
+ return inputmask;
+}
+
+
void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
new file mode 100644
index 000000000000..305e9b990b71
--- /dev/null
+++ b/arch/arm/plat-omap/fb.c
@@ -0,0 +1,80 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static struct omapfb_platform_data omapfb_config;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+ .name = "omapfb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &omap_fb_dma_mask,
+ .coherent_dma_mask = ~(u32)0,
+ .platform_data = &omapfb_config,
+ },
+ .num_resources = 0,
+};
+
+/* called from map_io */
+void omapfb_reserve_mem(void)
+{
+ const struct omap_fbmem_config *fbmem_conf;
+
+ omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
+ omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+
+ fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+
+ if (fbmem_conf != NULL) {
+ /* indicate that the bootloader already initialized the
+ * fb device, so we'll skip that part in the fb driver
+ */
+ omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
+ omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
+ if (fbmem_conf->fb_sdram_size) {
+ pr_info("Reserving %u bytes SDRAM for frame buffer\n",
+ fbmem_conf->fb_sdram_size);
+ reserve_bootmem(fbmem_conf->fb_sdram_start,
+ fbmem_conf->fb_sdram_size);
+ }
+ }
+}
+
+static inline int omap_init_fb(void)
+{
+ const struct omap_lcd_config *conf;
+
+ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+ if (conf == NULL)
+ return 0;
+
+ omapfb_config.lcd = *conf;
+
+ return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#else
+
+void omapfb_reserve_mem(void) {}
+
+#endif
+
+
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b4d5b9e4bfce..d3c8ea7eecfd 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -174,7 +174,7 @@ static int gpio_bank_count;
static inline struct gpio_bank *get_gpio_bank(int gpio)
{
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1];
@@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio)
return 0;
}
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510() && gpio < 16)
+ if (cpu_is_omap15xx() && gpio < 16)
return 0;
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
@@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
u32 gpio_bit = 1 << gpio;
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
- trigger & IRQT_LOW);
+ trigger & __IRQT_LOWLVL);
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
- trigger & IRQT_HIGH);
+ trigger & __IRQT_HIGHLVL);
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
- trigger & IRQT_RISING);
+ trigger & __IRQT_RISEDGE);
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
- trigger & IRQT_FALLING);
+ trigger & __IRQT_FALEDGE);
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
* triggering requested. */
}
@@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_INT_EDGE;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
reg += OMAP1610_GPIO_EDGE_CTRL1;
gpio &= 0x07;
/* We allow only edge triggering, i.e. two lowest bits */
- if (trigger & ~IRQT_BOTHEDGE)
+ if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
BUG();
- /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
- trigger &= 0x03;
l = __raw_readl(reg);
l &= ~(3 << (gpio << 1));
- l |= trigger << (gpio << 1);
+ if (trigger & __IRQT_RISEDGE)
+ l |= 2 << (gpio << 1);
+ if (trigger & __IRQT_FALEDGE)
+ l |= 1 << (gpio << 1);
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type)
if (check_gpio(gpio) < 0)
return -EINVAL;
- if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+ if (type & IRQT_PROBE)
+ return -EINVAL;
+ if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
return -EINVAL;
bank = get_gpio_bank(gpio);
@@ -755,13 +758,32 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_24XX)
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
#endif
-
while(1) {
- isr = __raw_readl(isr_reg);
- _enable_gpio_irqbank(bank, isr, 0);
- _clear_gpio_irqbank(bank, isr);
- _enable_gpio_irqbank(bank, isr, 1);
- desc->chip->unmask(irq);
+ u32 isr_saved, level_mask = 0;
+
+ isr_saved = isr = __raw_readl(isr_reg);
+
+ if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
+ isr &= 0x0000ffff;
+
+ if (cpu_is_omap24xx())
+ level_mask =
+ __raw_readl(bank->base +
+ OMAP24XX_GPIO_LEVELDETECT0) |
+ __raw_readl(bank->base +
+ OMAP24XX_GPIO_LEVELDETECT1);
+
+ /* clear edge sensitive interrupts before handler(s) are
+ called so that we don't miss any interrupt occurred while
+ executing them */
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+ _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+
+ /* if there is only edge sensitive GPIO pin interrupts
+ configured, we could unmask GPIO bank interrupt immediately */
+ if (!level_mask)
+ desc->chip->unmask(irq);
if (!isr)
break;
@@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + gpio_irq;
desc_handle_irq(gpio_irq, d, regs);
}
+
+ if (cpu_is_omap24xx()) {
+ /* clear level sensitive interrupts after handler(s) */
+ _enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+ _clear_gpio_irqbank(bank, isr_saved & level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+ }
+
+ /* if bank has any level sensitive GPIO pin interrupt
+ configured, we must unmask the bank interrupt only after
+ handler(s) are executed in order to avoid spurious bank
+ interrupt */
+ if (level_mask)
+ desc->chip->unmask(irq);
}
}
@@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void)
initialized = 1;
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
gpio_ick = clk_get(NULL, "arm_gpio_ck");
if (IS_ERR(gpio_ick))
printk("Could not get arm_gpio_ck\n");
@@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void)
}
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
gpio_bank_count = 2;
gpio_bank = gpio_bank_1510;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 1cd2cace7e1b..196aac3ac329 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -34,7 +34,7 @@
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
#else
-#define DBG(x...) do { } while (0)
+#define DBG(x...) do { } while (0)
#endif
struct omap_mcbsp {
@@ -44,6 +44,7 @@ struct omap_mcbsp {
omap_mcbsp_word_length rx_word_length;
omap_mcbsp_word_length tx_word_length;
+ omap_mcbsp_io_type_t io_type; /* IRQ or poll */
/* IRQ based TX/RX */
int rx_irq;
int tx_irq;
@@ -64,10 +65,19 @@ struct omap_mcbsp {
};
static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+#ifdef CONFIG_ARCH_OMAP1
static struct clk *mcbsp_dsp_ck = 0;
static struct clk *mcbsp_api_ck = 0;
static struct clk *mcbsp_dspxor_ck = 0;
-
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+static struct clk *mcbsp1_ick = 0;
+static struct clk *mcbsp1_fck = 0;
+static struct clk *mcbsp2_ick = 0;
+static struct clk *mcbsp2_fck = 0;
+static struct clk *sys_ck = 0;
+static struct clk *sys_clkout = 0;
+#endif
static void omap_mcbsp_dump_reg(u8 id)
{
@@ -88,7 +98,6 @@ static void omap_mcbsp_dump_reg(u8 id)
DBG("***********************\n");
}
-
static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
@@ -109,7 +118,6 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_re
return IRQ_HANDLED;
}
-
static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
{
struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
@@ -176,7 +184,7 @@ static int omap_mcbsp_check(unsigned int id)
return 0;
}
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
if (id > OMAP_MAX_MCBSP_COUNT) {
printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
return -1;
@@ -187,9 +195,10 @@ static int omap_mcbsp_check(unsigned int id)
return -1;
}
+#ifdef CONFIG_ARCH_OMAP1
static void omap_mcbsp_dsp_request(void)
{
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
clk_enable(mcbsp_dsp_ck);
clk_enable(mcbsp_api_ck);
@@ -207,12 +216,49 @@ static void omap_mcbsp_dsp_request(void)
static void omap_mcbsp_dsp_free(void)
{
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
clk_disable(mcbsp_dspxor_ck);
clk_disable(mcbsp_dsp_ck);
clk_disable(mcbsp_api_ck);
}
}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static void omap2_mcbsp2_mux_setup(void)
+{
+ omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
+ omap_cfg_reg(R14_24XX_MCBSP2_FSX);
+ omap_cfg_reg(W15_24XX_MCBSP2_DR);
+ omap_cfg_reg(V15_24XX_MCBSP2_DX);
+ omap_cfg_reg(V14_24XX_GPIO117);
+ omap_cfg_reg(W14_24XX_SYS_CLKOUT);
+}
+#endif
+
+/*
+ * We can choose between IRQ based or polled IO.
+ * This needs to be called before omap_mcbsp_request().
+ */
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
+{
+ if (omap_mcbsp_check(id) < 0)
+ return -EINVAL;
+
+ spin_lock(&mcbsp[id].lock);
+
+ if (!mcbsp[id].free) {
+ printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+ spin_unlock(&mcbsp[id].lock);
+ return -EINVAL;
+ }
+
+ mcbsp[id].io_type = io_type;
+
+ spin_unlock(&mcbsp[id].lock);
+
+ return 0;
+}
int omap_mcbsp_request(unsigned int id)
{
@@ -221,12 +267,26 @@ int omap_mcbsp_request(unsigned int id)
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
+#ifdef CONFIG_ARCH_OMAP1
/*
* On 1510, 1610 and 1710, McBSP1 and McBSP3
* are DSP public peripherals.
*/
if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
omap_mcbsp_dsp_request();
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+ if (cpu_is_omap24xx()) {
+ if (id == OMAP_MCBSP1) {
+ clk_enable(mcbsp1_ick);
+ clk_enable(mcbsp1_fck);
+ } else {
+ clk_enable(mcbsp2_ick);
+ clk_enable(mcbsp2_fck);
+ }
+ }
+#endif
spin_lock(&mcbsp[id].lock);
if (!mcbsp[id].free) {
@@ -238,30 +298,33 @@ int omap_mcbsp_request(unsigned int id)
mcbsp[id].free = 0;
spin_unlock(&mcbsp[id].lock);
- /* We need to get IRQs here */
- err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
- "McBSP",
- (void *) (&mcbsp[id]));
- if (err != 0) {
- printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
- mcbsp[id].tx_irq, mcbsp[id].id);
- return err;
- }
+ if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+ /* We need to get IRQs here */
+ err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+ "McBSP",
+ (void *) (&mcbsp[id]));
+ if (err != 0) {
+ printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+ mcbsp[id].tx_irq, mcbsp[id].id);
+ return err;
+ }
- init_completion(&(mcbsp[id].tx_irq_completion));
+ init_completion(&(mcbsp[id].tx_irq_completion));
- err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
- "McBSP",
- (void *) (&mcbsp[id]));
- if (err != 0) {
- printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
- mcbsp[id].rx_irq, mcbsp[id].id);
- free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
- return err;
+ err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+ "McBSP",
+ (void *) (&mcbsp[id]));
+ if (err != 0) {
+ printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+ mcbsp[id].rx_irq, mcbsp[id].id);
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ return err;
+ }
+
+ init_completion(&(mcbsp[id].rx_irq_completion));
}
- init_completion(&(mcbsp[id].rx_irq_completion));
return 0;
}
@@ -271,8 +334,24 @@ void omap_mcbsp_free(unsigned int id)
if (omap_mcbsp_check(id) < 0)
return;
- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
- omap_mcbsp_dsp_free();
+#ifdef CONFIG_ARCH_OMAP1
+ if (cpu_class_is_omap1()) {
+ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+ omap_mcbsp_dsp_free();
+ }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+ if (cpu_is_omap24xx()) {
+ if (id == OMAP_MCBSP1) {
+ clk_disable(mcbsp1_ick);
+ clk_disable(mcbsp1_fck);
+ } else {
+ clk_disable(mcbsp2_ick);
+ clk_disable(mcbsp2_fck);
+ }
+ }
+#endif
spin_lock(&mcbsp[id].lock);
if (mcbsp[id].free) {
@@ -284,9 +363,11 @@ void omap_mcbsp_free(unsigned int id)
mcbsp[id].free = 1;
spin_unlock(&mcbsp[id].lock);
- /* Free IRQs */
- free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
- free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+ /* Free IRQs */
+ free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ }
}
/*
@@ -461,6 +542,115 @@ u32 omap_mcbsp_recv_word(unsigned int id)
}
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
+{
+ u32 io_base = mcbsp[id].io_base;
+ omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+ omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+ udelay(10);
+ printk("McBSP transmitter not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Now we can push the data */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+ OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+ udelay(10);
+ printk("McBSP receiver not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, let's read the dummy data */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+ word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+ return 0;
+}
+
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word)
+{
+ u32 io_base = mcbsp[id].io_base, clock_word = 0;
+ omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+ omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+ udelay(10);
+ printk("McBSP transmitter not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* We first need to enable the bus clock */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16);
+ OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+ udelay(10);
+ printk("McBSP receiver not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, there is something for us */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+ word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+ word[0] = (word_lsb | (word_msb << 16));
+
+ return 0;
+}
+
+
/*
* Simple DMA based buffer rx/tx routines.
* Nothing fancy, just a single buffer tx/rx through DMA.
@@ -471,6 +661,9 @@ u32 omap_mcbsp_recv_word(unsigned int id)
int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
{
int dma_tx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
@@ -487,20 +680,27 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
init_completion(&(mcbsp[id].tx_dma_completion));
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = mcbsp[id].dma_tx_sync;
+
omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
OMAP_DMA_DATA_TYPE_S16,
length >> 1, 1,
OMAP_DMA_SYNC_ELEMENT,
- 0, 0);
+ sync_dev, 0);
omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
- OMAP_DMA_PORT_TIPB,
+ src_port,
OMAP_DMA_AMODE_CONSTANT,
mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
0, 0);
omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
- OMAP_DMA_PORT_EMIFF,
+ dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
@@ -514,6 +714,9 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
{
int dma_rx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
@@ -530,20 +733,27 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
init_completion(&(mcbsp[id].rx_dma_completion));
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = mcbsp[id].dma_rx_sync;
+
omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
OMAP_DMA_DATA_TYPE_S16,
length >> 1, 1,
OMAP_DMA_SYNC_ELEMENT,
- 0, 0);
+ sync_dev, 0);
omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
- OMAP_DMA_PORT_TIPB,
+ src_port,
OMAP_DMA_AMODE_CONSTANT,
mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
0, 0);
omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
- OMAP_DMA_PORT_EMIFF,
+ dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
@@ -688,6 +898,23 @@ static const struct omap_mcbsp_info mcbsp_1610[] = {
};
#endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+static const struct omap_mcbsp_info mcbsp_24xx[] = {
+ [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
+ .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
+ .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
+ .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
+ },
+ [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
+ .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
+ .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
+ .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
+ },
+};
+#endif
+
static int __init omap_mcbsp_init(void)
{
int mcbsp_count = 0, i;
@@ -695,6 +922,7 @@ static int __init omap_mcbsp_init(void)
printk("Initializing OMAP McBSP system\n");
+#ifdef CONFIG_ARCH_OMAP1
mcbsp_dsp_ck = clk_get(0, "dsp_ck");
if (IS_ERR(mcbsp_dsp_ck)) {
printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
@@ -710,6 +938,29 @@ static int __init omap_mcbsp_init(void)
printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
return PTR_ERR(mcbsp_dspxor_ck);
}
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+ mcbsp1_ick = clk_get(0, "mcbsp1_ick");
+ if (IS_ERR(mcbsp1_ick)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
+ return PTR_ERR(mcbsp1_ick);
+ }
+ mcbsp1_fck = clk_get(0, "mcbsp1_fck");
+ if (IS_ERR(mcbsp1_fck)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
+ return PTR_ERR(mcbsp1_fck);
+ }
+ mcbsp2_ick = clk_get(0, "mcbsp2_ick");
+ if (IS_ERR(mcbsp2_ick)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
+ return PTR_ERR(mcbsp2_ick);
+ }
+ mcbsp2_fck = clk_get(0, "mcbsp2_fck");
+ if (IS_ERR(mcbsp2_fck)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
+ return PTR_ERR(mcbsp2_fck);
+ }
+#endif
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
@@ -718,7 +969,7 @@ static int __init omap_mcbsp_init(void)
}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
mcbsp_info = mcbsp_1510;
mcbsp_count = ARRAY_SIZE(mcbsp_1510);
}
@@ -729,6 +980,19 @@ static int __init omap_mcbsp_init(void)
mcbsp_count = ARRAY_SIZE(mcbsp_1610);
}
#endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+ if (cpu_is_omap24xx()) {
+ mcbsp_info = mcbsp_24xx;
+ mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
+
+ /* REVISIT: where's the right place? */
+ omap2_mcbsp2_mux_setup();
+ sys_ck = clk_get(0, "sys_ck");
+ sys_clkout = clk_get(0, "sys_clkout");
+ clk_set_parent(sys_clkout, sys_ck);
+ clk_enable(sys_clkout);
+ }
+#endif
for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
if (i >= mcbsp_count) {
mcbsp[i].io_base = 0;
@@ -741,6 +1005,7 @@ static int __init omap_mcbsp_init(void)
mcbsp[i].dma_rx_lch = -1;
mcbsp[i].io_base = mcbsp_info[i].virt_base;
+ mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */
mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
@@ -751,11 +1016,11 @@ static int __init omap_mcbsp_init(void)
return 0;
}
-
arch_initcall(omap_mcbsp_init);
EXPORT_SYMBOL(omap_mcbsp_config);
EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_set_io_type);
EXPORT_SYMBOL(omap_mcbsp_free);
EXPORT_SYMBOL(omap_mcbsp_start);
EXPORT_SYMBOL(omap_mcbsp_stop);
@@ -763,4 +1028,6 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word);
EXPORT_SYMBOL(omap_mcbsp_recv_word);
EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index 5cc6775c789c..37792d43738b 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -62,9 +62,6 @@ int ocpi_enable(void)
if (!cpu_is_omap16xx())
return -ENODEV;
- /* Make sure there's clock for OCPI */
- clk_enable(ocpi_ck);
-
/* Enable access for OHCI in OCPI */
val = omap_readl(OCPI_PROT);
val &= ~0xff;
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
index 093efd786f21..1a24e2c10714 100644
--- a/arch/arm/plat-omap/pm.c
+++ b/arch/arm/plat-omap/pm.c
@@ -38,6 +38,7 @@
#include <linux/pm.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
+#include <linux/pm.h>
#include <linux/interrupt.h>
#include <asm/io.h>
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index ee82763b02b8..b7bf09b1b412 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -16,24 +16,94 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/mach/map.h>
#include <asm/tlb.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
#include <asm/arch/sram.h>
+#include <asm/arch/board.h>
#define OMAP1_SRAM_PA 0x20000000
#define OMAP1_SRAM_VA 0xd0000000
#define OMAP2_SRAM_PA 0x40200000
+#define OMAP2_SRAM_PUB_PA 0x4020f800
#define OMAP2_SRAM_VA 0xd0000000
+#define OMAP2_SRAM_PUB_VA 0xd0000800
+#if defined(CONFIG_ARCH_OMAP24XX)
+#define SRAM_BOOTLOADER_SZ 0x00
+#else
#define SRAM_BOOTLOADER_SZ 0x80
+#endif
+
+#define VA_REQINFOPERM0 IO_ADDRESS(0x68005048)
+#define VA_READPERM0 IO_ADDRESS(0x68005050)
+#define VA_WRITEPERM0 IO_ADDRESS(0x68005058)
+#define VA_CONTROL_STAT IO_ADDRESS(0x480002F8)
+#define GP_DEVICE 0x300
+#define TYPE_MASK 0x700
+
+#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
+unsigned long omap_fb_sram_start;
+unsigned long omap_fb_sram_size;
+
+/* Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies. The default accessable size for all device types is 2k. A GP
+ * device allows ARM11 but not other initators for full size. This
+ * functionality seems ok until some nice security API happens.
+ */
+static int is_sram_locked(void)
+{
+ int type = 0;
+
+ if (cpu_is_omap242x())
+ type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK;
+
+ if (type == GP_DEVICE) {
+ /* RAMFW: R/W access to all initators for all qualifier sets */
+ if (cpu_is_omap242x()) {
+ __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */
+ __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */
+ __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */
+ }
+ return 0;
+ } else
+ return 1; /* assume locked with no PPA or security driver */
+}
+
+void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
+ unsigned long *start, unsigned long *size)
+{
+ const struct omap_fbmem_config *fbmem_conf;
+
+ fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+ if (fbmem_conf != NULL) {
+ *start = fbmem_conf->fb_sram_start;
+ *size = fbmem_conf->fb_sram_size;
+ } else {
+ *size = 0;
+ *start = 0;
+ }
+
+ if (*size && (
+ *start < start_avail ||
+ *start + *size > start_avail + size_avail)) {
+ printk(KERN_ERR "invalid FB SRAM configuration\n");
+ *start = start_avail;
+ *size = size_avail;
+ }
+
+ if (*size)
+ pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
+}
+
/*
* The amount of SRAM depends on the core type.
* Note that we cannot try to test for SRAM here because writes
@@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil;
*/
void __init omap_detect_sram(void)
{
- if (!cpu_is_omap24xx())
+ unsigned long sram_start;
+
+ if (cpu_is_omap24xx()) {
+ if (is_sram_locked()) {
+ omap_sram_base = OMAP2_SRAM_PUB_VA;
+ sram_start = OMAP2_SRAM_PUB_PA;
+ omap_sram_size = 0x800; /* 2K */
+ } else {
+ omap_sram_base = OMAP2_SRAM_VA;
+ sram_start = OMAP2_SRAM_PA;
+ if (cpu_is_omap242x())
+ omap_sram_size = 0xa0000; /* 640K */
+ else if (cpu_is_omap243x())
+ omap_sram_size = 0x10000; /* 64K */
+ }
+ } else {
omap_sram_base = OMAP1_SRAM_VA;
- else
- omap_sram_base = OMAP2_SRAM_VA;
-
- if (cpu_is_omap730())
- omap_sram_size = 0x32000; /* 200K */
- else if (cpu_is_omap15xx())
- omap_sram_size = 0x30000; /* 192K */
- else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
- omap_sram_size = 0x4000; /* 16K */
- else if (cpu_is_omap1611())
- omap_sram_size = 0x3e800; /* 250K */
- else if (cpu_is_omap2420())
- omap_sram_size = 0xa0014; /* 640K */
- else {
- printk(KERN_ERR "Could not detect SRAM size\n");
- omap_sram_size = 0x4000;
+ sram_start = OMAP1_SRAM_PA;
+
+ if (cpu_is_omap730())
+ omap_sram_size = 0x32000; /* 200K */
+ else if (cpu_is_omap15xx())
+ omap_sram_size = 0x30000; /* 192K */
+ else if (cpu_is_omap1610() || cpu_is_omap1621() ||
+ cpu_is_omap1710())
+ omap_sram_size = 0x4000; /* 16K */
+ else if (cpu_is_omap1611())
+ omap_sram_size = 0x3e800; /* 250K */
+ else {
+ printk(KERN_ERR "Could not detect SRAM size\n");
+ omap_sram_size = 0x4000;
+ }
}
-
+ get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
+ omap_sram_size - SRAM_BOOTLOADER_SZ,
+ &omap_fb_sram_start, &omap_fb_sram_size);
+ if (omap_fb_sram_size)
+ omap_sram_size -= sram_start + omap_sram_size -
+ omap_fb_sram_start;
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
@@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = {
*/
void __init omap_map_sram(void)
{
+ unsigned long base;
+
if (omap_sram_size == 0)
return;
if (cpu_is_omap24xx()) {
omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
- omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
+
+ if (is_sram_locked())
+ base = OMAP2_SRAM_PUB_PA;
+ else
+ base = OMAP2_SRAM_PA;
+ base = ROUND_DOWN(base, PAGE_SIZE);
+ omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
}
omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
@@ -93,7 +190,8 @@ void __init omap_map_sram(void)
iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
- omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
+ __pfn_to_phys(omap_sram_io_desc[0].pfn),
+ omap_sram_io_desc[0].virtual,
omap_sram_io_desc[0].length);
/*
@@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size)
printk(KERN_ERR "Not enough space in SRAM\n");
return NULL;
}
+
omap_sram_ceil -= size;
- omap_sram_ceil &= ~0x3;
+ omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
memcpy((void *)omap_sram_ceil, start, size);
return (void *)omap_sram_ceil;
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
new file mode 100644
index 000000000000..b2a943bf11ef
--- /dev/null
+++ b/arch/arm/plat-omap/timer32k.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/arm/plat-omap/timer32k.c
+ *
+ * OMAP 32K Timer
+ *
+ * Copyright (C) 2004 - 2005 Nokia Corporation
+ * Partial timer rewrite and additional dynamic tick timer support by
+ * Tony Lindgen <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * MPU timer code based on the older MPU timer code for OMAP
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+struct sys_timer omap_timer;
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED 0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED 0x48004010
+#else
+#error OMAP 32KHz timer does not currently work on 15XX!
+#endif
+
+/* 16xx specific defines */
+#define OMAP1_32K_TIMER_BASE 0xfffb9000
+#define OMAP1_32K_TIMER_CR 0x08
+#define OMAP1_32K_TIMER_TVR 0x00
+#define OMAP1_32K_TIMER_TCR 0x04
+
+/* 24xx specific defines */
+#define OMAP2_GP_TIMER_BASE 0x48028000
+#define CM_CLKSEL_WKUP 0x48008440
+#define GP_TIMER_TIDR 0x00
+#define GP_TIMER_TISR 0x18
+#define GP_TIMER_TIER 0x1c
+#define GP_TIMER_TCLR 0x24
+#define GP_TIMER_TCRR 0x28
+#define GP_TIMER_TLDR 0x2c
+#define GP_TIMER_TTGR 0x30
+#define GP_TIMER_TSICR 0x40
+
+#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 128, TVR = 255.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
+ (((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+ if (cpu_class_is_omap1())
+ omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+
+ if (cpu_is_omap24xx())
+ omap_writel(val, OMAP2_GP_TIMER_BASE + reg);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+ if (cpu_class_is_omap1())
+ return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+
+ if (cpu_is_omap24xx())
+ return omap_readl(OMAP2_GP_TIMER_BASE + reg);
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+ return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+ if (cpu_class_is_omap1()) {
+ omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+ omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+ }
+
+ if (cpu_is_omap24xx()) {
+ omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR);
+ omap_32k_timer_write((1 << 1), GP_TIMER_TIER);
+ omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR);
+ }
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+ if (cpu_class_is_omap1())
+ omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+
+ if (cpu_is_omap24xx())
+ omap_32k_timer_write(0x0, GP_TIMER_TCLR);
+}
+
+/*
+ * Rounds down to nearest usec. Note that this will overflow for larger values.
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+ return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+/*
+ * Rounds down to nearest nsec.
+ */
+static inline unsigned long long
+omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+{
+ return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+ unsigned long now = omap_32k_sync_timer_read();
+ return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+ return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned long now;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ if (cpu_is_omap24xx()) {
+ u32 status = omap_32k_timer_read(GP_TIMER_TISR);
+ omap_32k_timer_write(status, GP_TIMER_TISR);
+ }
+
+ now = omap_32k_sync_timer_read();
+
+ while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+ omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+ timer_tick(regs);
+ }
+
+ /* Restart timer so we don't drift off due to modulo or dynamic tick.
+ * By default we program the next timer to be continuous to avoid
+ * latencies during high system load. During dynamic tick operation the
+ * continuous timer can be overridden from pm_idle to be longer.
+ */
+ omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. Note that
+ * we can keep the timer continuous, and don't need to set it to run in
+ * one-shot mode. This is because the timer will get reprogrammed again
+ * after next interrupt.
+ */
+void omap_32k_timer_reprogram(unsigned long next_tick)
+{
+ omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+}
+
+static struct irqaction omap_32k_timer_irq;
+extern struct timer_update_handler timer_update;
+
+static int omap_32k_timer_enable_dyn_tick(void)
+{
+ /* No need to reprogram timer, just use the next interrupt */
+ return 0;
+}
+
+static int omap_32k_timer_disable_dyn_tick(void)
+{
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+ return 0;
+}
+
+static struct dyn_tick_timer omap_dyn_tick_timer = {
+ .enable = omap_32k_timer_enable_dyn_tick,
+ .disable = omap_32k_timer_disable_dyn_tick,
+ .reprogram = omap_32k_timer_reprogram,
+ .handler = omap_32k_timer_interrupt,
+};
+#endif /* CONFIG_NO_IDLE_HZ */
+
+static struct irqaction omap_32k_timer_irq = {
+ .name = "32KHz timer",
+ .flags = SA_INTERRUPT | SA_TIMER,
+ .handler = omap_32k_timer_interrupt,
+};
+
+static struct clk * gpt1_ick;
+static struct clk * gpt1_fck;
+
+static __init void omap_init_32k_timer(void)
+{
+#ifdef CONFIG_NO_IDLE_HZ
+ omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
+ if (cpu_class_is_omap1())
+ setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+ if (cpu_is_omap24xx())
+ setup_irq(37, &omap_32k_timer_irq);
+ omap_timer.offset = omap_32k_timer_gettimeoffset;
+ omap_32k_last_tick = omap_32k_sync_timer_read();
+
+ /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+ if (cpu_is_omap24xx()) {
+ omap_32k_timer_write(0, GP_TIMER_TCLR);
+ omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */
+
+ gpt1_ick = clk_get(NULL, "gpt1_ick");
+ if (IS_ERR(gpt1_ick))
+ printk(KERN_ERR "Could not get gpt1_ick\n");
+ else
+ clk_enable(gpt1_ick);
+
+ gpt1_fck = clk_get(NULL, "gpt1_fck");
+ if (IS_ERR(gpt1_fck))
+ printk(KERN_ERR "Could not get gpt1_fck\n");
+ else
+ clk_enable(gpt1_fck);
+
+ mdelay(100); /* Wait for clocks to stabilize */
+
+ omap_32k_timer_write(0x7, GP_TIMER_TISR);
+ }
+
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+ omap_init_32k_timer();
+}
+
+struct sys_timer omap_timer = {
+ .init = omap_timer_init,
+ .offset = NULL, /* Initialized later */
+};
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 9b367a65cb4d..009038c8113e 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -197,7 +197,7 @@ u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exce
dd, d, exceptions);
vfp_put_double(dd, d);
}
- return exceptions & ~VFP_NAN_FLAG;
+ return exceptions;
}
/*
@@ -588,6 +588,7 @@ static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr)
struct vfp_double vdm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
+ int tm;
vfp_double_unpack(&vdm, vfp_get_double(dm));
vfp_double_dump("VDM", &vdm);
@@ -595,10 +596,14 @@ static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr)
/*
* Do we have denormalised number?
*/
- if (vfp_double_type(&vdm) & VFP_DENORMAL)
+ tm = vfp_double_type(&vdm);
+ if (tm & VFP_DENORMAL)
exceptions |= FPSCR_IDC;
- if (vdm.exponent >= 1023 + 32) {
+ if (tm & VFP_NAN) {
+ d = 0;
+ exceptions |= FPSCR_IOC;
+ } else if (vdm.exponent >= 1023 + 32) {
d = 0x7fffffff;
if (vdm.sign)
d = ~d;
@@ -1122,9 +1127,9 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
{
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
- unsigned int dd = vfp_get_sd(inst);
- unsigned int dn = vfp_get_sn(inst);
- unsigned int dm = vfp_get_sm(inst);
+ unsigned int dd = vfp_get_dd(inst);
+ unsigned int dn = vfp_get_dn(inst);
+ unsigned int dm = vfp_get_dm(inst);
unsigned int vecitr, veclen, vecstride;
u32 (*fop)(int, int, s32, u32);
@@ -1141,7 +1146,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
(veclen >> FPSCR_LENGTH_BIT) + 1);
- fop = (op == FOP_EXT) ? fop_extfns[dn] : fop_fns[FOP_TO_IDX(op)];
+ fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
if (!fop)
goto invalid;
@@ -1149,17 +1154,13 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
u32 except;
if (op == FOP_EXT)
- pr_debug("VFP: itr%d (d%u.%u) = op[%u] (d%u.%u)\n",
+ pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd >> 1, dd & 1, dn,
- dm >> 1, dm & 1);
+ dd, dn, dm);
else
- pr_debug("VFP: itr%d (d%u.%u) = (d%u.%u) op[%u] (d%u.%u)\n",
+ pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd >> 1, dd & 1,
- dn >> 1, dn & 1,
- FOP_TO_IDX(op),
- dm >> 1, dm & 1);
+ dd, dn, FOP_TO_IDX(op), dm);
except = fop(dd, dn, dm, fpscr);
pr_debug("VFP: itr%d: exceptions=%08x\n",
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index b7ed57e00cd4..a3f65b47aea9 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -189,11 +189,10 @@ vfp_put_float:
.globl vfp_get_double
vfp_get_double:
- mov r0, r0, lsr #1
add pc, pc, r0, lsl #3
mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- mrrc p10, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr
+ mrrc p11, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr
mov pc, lr
.endr
@@ -204,10 +203,9 @@ vfp_get_double:
.globl vfp_put_double
vfp_put_double:
- mov r0, r0, lsr #1
add pc, pc, r0, lsl #3
mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- mcrr p10, 1, r1, r2, c\dr @ fmrrd r1, r2, d\dr
+ mcrr p11, 1, r1, r2, c\dr @ fmdrr r1, r2, d\dr
mov pc, lr
.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 22f3da4e0829..37ff8145b5b5 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -180,7 +180,7 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
* emulate it.
*/
}
- return exceptions;
+ return exceptions & ~VFP_NAN_FLAG;
}
/*
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 14dd696ddeb1..dae2c2f46052 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -203,7 +203,7 @@ u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exce
vfp_put_float(sd, d);
}
- return exceptions & ~VFP_NAN_FLAG;
+ return exceptions;
}
/*
@@ -632,6 +632,7 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
struct vfp_single vsm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
+ int tm;
vfp_single_unpack(&vsm, m);
vfp_single_dump("VSM", &vsm);
@@ -639,10 +640,14 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
/*
* Do we have a denormalised number?
*/
+ tm = vfp_single_type(&vsm);
if (vfp_single_type(&vsm) & VFP_DENORMAL)
exceptions |= FPSCR_IDC;
- if (vsm.exponent >= 127 + 32) {
+ if (tm & VFP_NAN) {
+ d = 0;
+ exceptions |= FPSCR_IOC;
+ } else if (vsm.exponent >= 127 + 32) {
/*
* m >= 2^31-2^7: invalid
*/
@@ -1188,7 +1193,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
(veclen >> FPSCR_LENGTH_BIT) + 1);
- fop = (op == FOP_EXT) ? fop_extfns[sn] : fop_fns[FOP_TO_IDX(op)];
+ fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
if (!fop)
goto invalid;
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index a6a1b3373444..9d66c27f2724 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -152,7 +152,6 @@ EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(memset);
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index de39725da920..d57859053ce7 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(loops_per_usec);
/* String functions */
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strchr);
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 1d21c8d34d8a..a9b59527a741 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1170,12 +1170,6 @@ __syscall_badsys:
# syscall vector table
#
###############################################################################
-#ifdef CONFIG_MMU
-#define __MMU(X) X
-#else
-#define __MMU(X) sys_ni_syscall
-#endif
-
.section .rodata
ALIGN
.globl sys_call_table
@@ -1305,7 +1299,7 @@ sys_call_table:
.long sys_newuname
.long sys_ni_syscall /* old "cacheflush" */
.long sys_adjtimex
- .long __MMU(sys_mprotect) /* 125 */
+ .long sys_mprotect /* 125 */
.long sys_sigprocmask
.long sys_ni_syscall /* old "create_module" */
.long sys_init_module
@@ -1324,16 +1318,16 @@ sys_call_table:
.long sys_getdents
.long sys_select
.long sys_flock
- .long __MMU(sys_msync)
+ .long sys_msync
.long sys_readv /* 145 */
.long sys_writev
.long sys_getsid
.long sys_fdatasync
.long sys_sysctl
- .long __MMU(sys_mlock) /* 150 */
- .long __MMU(sys_munlock)
- .long __MMU(sys_mlockall)
- .long __MMU(sys_munlockall)
+ .long sys_mlock /* 150 */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
.long sys_sched_setparam
.long sys_sched_getparam /* 155 */
.long sys_sched_setscheduler
@@ -1343,7 +1337,7 @@ sys_call_table:
.long sys_sched_get_priority_min /* 160 */
.long sys_sched_rr_get_interval
.long sys_nanosleep
- .long __MMU(sys_mremap)
+ .long sys_mremap
.long sys_setresuid16
.long sys_getresuid16 /* 165 */
.long sys_ni_syscall /* for vm86 */
@@ -1398,8 +1392,8 @@ sys_call_table:
.long sys_setfsuid /* 215 */
.long sys_setfsgid
.long sys_pivot_root
- .long __MMU(sys_mincore)
- .long __MMU(sys_madvise)
+ .long sys_mincore
+ .long sys_madvise
.long sys_getdents64 /* 220 */
.long sys_fcntl64
.long sys_ni_syscall /* reserved for TUX */
@@ -1437,7 +1431,7 @@ sys_call_table:
.long sys_epoll_create
.long sys_epoll_ctl /* 255 */
.long sys_epoll_wait
- .long __MMU(sys_remap_file_pages)
+ .long sys_remap_file_pages
.long sys_set_tid_address
.long sys_timer_create
.long sys_timer_settime /* 260 */
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 07c8ffa0dd39..0f273a7aca5a 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -27,7 +27,6 @@ EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strchr);
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index b6cd78c972bb..f8d6dee84781 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -25,7 +25,6 @@ extern char h8300_debug_device[];
/* platform dependent support */
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strchr);
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index f17bd1d2707e..c6fe99e57a05 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -53,6 +53,35 @@ source "init/Kconfig"
menu "Processor type and features"
+config SMP
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, like most personal computers, say N. If
+ you have a system with more than one CPU, say Y.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on many, but not all,
+ singleprocessor machines. On a singleprocessor machine, the kernel
+ will run faster if you say N here.
+
+ Note that if you say Y here and choose architecture "586" or
+ "Pentium" under "Processor family", the kernel will not work on 486
+ architectures. Similarly, multiprocessor kernels for the "PPro"
+ architecture may not work on all Pentium based boards.
+
+ People using multiprocessor machines who say Y here should also say
+ Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+ Management" code will be disabled if you say Y here.
+
+ See also the <file:Documentation/smp.txt>,
+ <file:Documentation/i386/IO-APIC.txt>,
+ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you don't know what to do here, say N.
+
choice
prompt "Subarchitecture Type"
default X86_PC
@@ -178,35 +207,6 @@ config HPET_EMULATE_RTC
depends on HPET_TIMER && RTC=y
default y
-config SMP
- bool "Symmetric multi-processing support"
- ---help---
- This enables support for systems with more than one CPU. If you have
- a system with only one CPU, like most personal computers, say N. If
- you have a system with more than one CPU, say Y.
-
- If you say N here, the kernel will run on single and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
- you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
- will run faster if you say N here.
-
- Note that if you say Y here and choose architecture "586" or
- "Pentium" under "Processor family", the kernel will not work on 486
- architectures. Similarly, multiprocessor kernels for the "PPro"
- architecture may not work on all Pentium based boards.
-
- People using multiprocessor machines who say Y here should also say
- Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
- Management" code will be disabled if you say Y here.
-
- See also the <file:Documentation/smp.txt>,
- <file:Documentation/i386/IO-APIC.txt>,
- <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
- <http://www.tldp.org/docs.html#howto>.
-
- If you don't know what to do here, say N.
-
config NR_CPUS
int "Maximum number of CPUs (2-255)"
range 2 255
@@ -467,7 +467,7 @@ endchoice
choice
depends on EXPERIMENTAL && !X86_PAE
- prompt "Memory split"
+ prompt "Memory split" if EMBEDDED
default VMSPLIT_3G
help
Select the desired split between kernel and user memory.
@@ -522,6 +522,12 @@ config NUMA
comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+config NODES_SHIFT
+ int
+ default "4" if X86_NUMAQ
+ default "3"
+ depends on NEED_MULTIPLE_NODES
+
config HAVE_ARCH_BOOTMEM_NODE
bool
depends on NUMA
@@ -750,22 +756,13 @@ config PHYSICAL_START
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER && !X86_PC
+ depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
---help---
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
Say N.
-config DOUBLEFAULT
- default y
- bool "Enable doublefault exception handler" if EMBEDDED
- help
- This option allows trapping of rare doublefault exceptions that
- would otherwise cause a system to silently reboot. Disabling this
- option saves about 4k and might cause you much additional grey
- hair.
-
endmenu
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 79603b3471f9..eb130482ba18 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -311,5 +311,5 @@ config X86_OOSTORE
config X86_TSC
bool
- depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
+ depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ
default y
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index 6e97df6979e8..c92191b1fb67 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -81,4 +81,13 @@ config X86_MPPARSE
depends on X86_LOCAL_APIC && !X86_VISWS
default y
+config DOUBLEFAULT
+ default y
+ bool "Enable doublefault exception handler" if EMBEDDED
+ help
+ This option allows trapping of rare doublefault exceptions that
+ would otherwise cause a system to silently reboot. Disabling this
+ option saves about 4k and might cause you much additional grey
+ hair.
+
endmenu
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 0000a2674537..c9343c3a8082 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -97,6 +97,7 @@
#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
@@ -233,6 +234,10 @@ mopar_gr:
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
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5b9ed21216cf..96fb8a020af2 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
- pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
+ pci-dma.o i386_ksyms.o i387.o bootflag.o \
quirks.o i8237.o topology.o alternative.o
obj-y += cpu/
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 033066176b3e..049a25583793 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -215,7 +215,7 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
{
struct acpi_table_madt *madt = NULL;
- if (!phys_addr || !size)
+ if (!phys_addr || !size || !cpu_has_apic)
return -EINVAL;
madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
@@ -693,6 +693,9 @@ static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
+ if (!cpu_has_apic)
+ return -ENODEV;
+
/*
* Note that the LAPIC address is obtained from the MADT (32-bit value)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
@@ -751,6 +754,9 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return -ENODEV;
}
+ if (!cpu_has_apic)
+ return -ENODEV;
+
/*
* if "noapic" boot option, don't look for IO-APICs
*/
@@ -1096,6 +1102,9 @@ int __init acpi_boot_table_init(void)
dmi_check_system(acpi_dmi_table);
#endif
+ if (!cpu_has_apic)
+ return -ENODEV;
+
/*
* If acpi_disabled, bail out
* One exception: acpi=ht continues far enough to enumerate LAPICs
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 6273bf74c203..254cee9f0b7b 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -62,6 +62,18 @@ int apic_verbosity;
static void apic_pm_activate(void);
+int modern_apic(void)
+{
+ unsigned int lvr, version;
+ /* AMD systems use old APIC versions, so check the CPU */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+ boot_cpu_data.x86 >= 0xf)
+ return 1;
+ lvr = apic_read(APIC_LVR);
+ version = GET_APIC_VERSION(lvr);
+ return version >= 0x14;
+}
+
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@@ -119,10 +131,7 @@ void enable_NMI_through_LVT0 (void * dummy)
int get_physical_broadcast(void)
{
- unsigned int lvr, version;
- lvr = apic_read(APIC_LVR);
- version = GET_APIC_VERSION(lvr);
- if (!APIC_INTEGRATED(version) || version >= 0x14)
+ if (modern_apic())
return 0xff;
else
return 0xf;
@@ -349,9 +358,9 @@ int __init verify_local_APIC(void)
void __init sync_Arb_IDs(void)
{
- /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
- unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
- if (ver >= 0x14) /* P4 or higher */
+ /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
+ And not needed on AMD */
+ if (modern_apic())
return;
/*
* Wait for idle.
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index da30a374dd4e..df0e1745f189 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1079,7 +1079,7 @@ static int apm_console_blank(int blank)
break;
}
- if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
+ if (error == APM_NOT_ENGAGED) {
static int tried;
int eng_error;
if (tried++ == 0) {
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 0810f81f2a05..786d1a57048b 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -207,13 +207,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_K7, c->x86_capability);
break;
}
+ if (c->x86 >= 6)
+ set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
display_cacheinfo(c);
if (cpuid_eax(0x80000000) >= 0x80000008) {
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
- if (c->x86_max_cores & (c->x86_max_cores - 1))
- c->x86_max_cores = 1;
}
if (cpuid_eax(0x80000000) >= 0x80000007) {
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 712a26bd4457..71fffa174425 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -46,7 +46,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.1"
+#define VERSION "version 1.60.2"
#include "powernow-k8.h"
/* serialize freq changes */
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(fidvid_mutex);
static struct powernow_k8_data *powernow_data[NR_CPUS];
#ifndef CONFIG_SMP
-static cpumask_t cpu_core_map[1] = { CPU_MASK_ALL };
+static cpumask_t cpu_core_map[1];
#endif
/* Return a frequency in MHz, given an input fid */
@@ -905,11 +905,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
{
cpumask_t oldmask = CPU_MASK_ALL;
struct powernow_k8_data *data = powernow_data[pol->cpu];
- u32 checkfid = data->currfid;
- u32 checkvid = data->currvid;
+ u32 checkfid;
+ u32 checkvid;
unsigned int newstate;
int ret = -EIO;
+ if (!data)
+ return -EINVAL;
+
+ checkfid = data->currfid;
+ checkvid = data->currvid;
+
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
@@ -969,6 +975,9 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data = powernow_data[pol->cpu];
+ if (!data)
+ return -EINVAL;
+
return cpufreq_frequency_table_verify(pol, data->powernow_table);
}
@@ -977,7 +986,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
cpumask_t oldmask = CPU_MASK_ALL;
- int rc, i;
+ int rc;
if (!cpu_online(pol->cpu))
return -ENODEV;
@@ -1063,8 +1072,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
- for_each_cpu_mask(i, cpu_core_map[pol->cpu])
- powernow_data[i] = data;
+ powernow_data[pol->cpu] = data;
return 0;
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index 9df87b03612c..c8547a6fa7e6 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -642,7 +642,7 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
return;
}
-static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
+static int cacheinfo_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 006141d1c12a..1d9a4abcdfc7 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -168,7 +168,7 @@ static int cpuid_class_device_create(int i)
return err;
}
-static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index e3c5fca0aa8a..2b0cfce24a61 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -69,7 +69,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
* for the data I pass, and I need tags
* on the data to indicate what information I have
* squirrelled away. ELF notes happen to provide
- * all of that that no need to invent something new.
+ * all of that, so there is no need to invent something new.
*/
buf = (u32*)per_cpu_ptr(crash_notes, cpu);
if (!buf)
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 055325056a74..036a9857936f 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -19,7 +19,6 @@ EXPORT_SYMBOL(__put_user_2);
EXPORT_SYMBOL(__put_user_4);
EXPORT_SYMBOL(__put_user_8);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
#ifdef CONFIG_SMP
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f19768789e8a..38806f427849 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -43,7 +43,7 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/* insert a jmp code */
-static inline void set_jmp_op(void *from, void *to)
+static __always_inline void set_jmp_op(void *from, void *to)
{
struct __arch_jmp_op {
char op;
@@ -57,7 +57,7 @@ static inline void set_jmp_op(void *from, void *to)
/*
* returns non-zero if opcodes can be boosted.
*/
-static inline int can_boost(kprobe_opcode_t opcode)
+static __always_inline int can_boost(kprobe_opcode_t opcode)
{
switch (opcode & 0xf0 ) {
case 0x70:
@@ -88,7 +88,7 @@ static inline int can_boost(kprobe_opcode_t opcode)
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
-static inline int is_IF_modifier(kprobe_opcode_t opcode)
+static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
{
switch (opcode) {
case 0xfa: /* cli */
@@ -138,7 +138,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex);
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -146,7 +146,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -154,7 +154,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -164,7 +164,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_eflags &= ~IF_MASK;
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
@@ -242,10 +242,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else {
- if (regs->eflags & VM_MASK) {
- /* We are in virtual-8086 mode. Return 0 */
- goto no_kprobe;
- }
if (*addr != BREAKPOINT_INSTRUCTION) {
/* The breakpoint instruction was removed by
* another cpu right after we hit, no further
@@ -265,11 +261,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
p = get_kprobe(addr);
if (!p) {
- if (regs->eflags & VM_MASK) {
- /* We are in virtual-8086 mode. Return 0 */
- goto no_kprobe;
- }
-
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
* The breakpoint instruction was removed right
@@ -452,10 +443,11 @@ static void __kprobes resume_execution(struct kprobe *p,
*tos &= ~(TF_MASK | IF_MASK);
*tos |= kcb->kprobe_old_eflags;
break;
- case 0xc3: /* ret/lret */
- case 0xcb:
- case 0xc2:
+ case 0xc2: /* iret/ret/lret */
+ case 0xc3:
case 0xca:
+ case 0xcb:
+ case 0xcf:
case 0xea: /* jmp absolute -- eip is correct */
/* eip is already adjusted, no more changes required */
p->ainsn.boostable = 1;
@@ -463,10 +455,13 @@ static void __kprobes resume_execution(struct kprobe *p,
case 0xe8: /* call relative - Fix return addr */
*tos = orig_eip + (*tos - copy_eip);
break;
+ case 0x9a: /* call absolute -- same as call absolute, indirect */
+ *tos = orig_eip + (*tos - copy_eip);
+ goto no_change;
case 0xff:
if ((p->ainsn.insn[1] & 0x30) == 0x10) {
- /* call absolute, indirect */
/*
+ * call absolute, indirect
* Fix return addr; eip is correct.
* But this is not boostable
*/
@@ -507,7 +502,7 @@ no_change:
* Interrupts are disabled on entry as trap1 is an interrupt gate and they
* remain disabled thoroughout this function.
*/
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -543,7 +538,7 @@ out:
return 1;
}
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 8d8aa9d1796d..34d21e21e012 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -38,12 +38,6 @@
int smp_found_config;
unsigned int __initdata maxcpus = NR_CPUS;
-#ifdef CONFIG_HOTPLUG_CPU
-#define CPU_HOTPLUG_ENABLED (1)
-#else
-#define CPU_HOTPLUG_ENABLED (0)
-#endif
-
/*
* Various Linux-internal data structures created from the
* MP-table.
@@ -110,21 +104,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
-#ifdef CONFIG_X86_NUMAQ
-static int MP_valid_apicid(int apicid, int version)
-{
- return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
-}
-#else
-static int MP_valid_apicid(int apicid, int version)
-{
- if (version >= 0x14)
- return apicid < 0xff;
- else
- return apicid < 0xf;
-}
-#endif
-
static void __devinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
@@ -190,12 +169,6 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
ver = m->mpc_apicver;
- if (!MP_valid_apicid(apicid, ver)) {
- printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
- m->mpc_apicid, MAX_APICS);
- return;
- }
-
/*
* Validate version
*/
@@ -225,7 +198,14 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
cpu_set(num_processors, cpu_possible_map);
num_processors++;
- if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
+ /*
+ * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+ * but we need to work other dependencies like SMP_SUSPEND etc
+ * before this can be done without some confusion.
+ * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+ * - Ashok Raj <ashok.raj@intel.com>
+ */
+ if (num_processors > 8) {
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
if (!APIC_XAPIC(ver)) {
@@ -249,6 +229,13 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+ if (m->mpc_busid >= MAX_MP_BUSSES) {
+ printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+ " is too large, max. supported is %d\n",
+ m->mpc_busid, str, MAX_MP_BUSSES - 1);
+ return;
+ }
+
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 1d0a55e68760..7a328230e540 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -251,7 +251,7 @@ static int msr_class_device_create(int i)
return err;
}
-static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 10e21a4773dd..99aab41a05b0 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -51,7 +51,5 @@ void mach_reboot_fixups(void)
cur->reboot_fixup(dev);
}
-
- printk(KERN_WARNING "No reboot fixup found for your hardware\n");
}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index eacc3f0a2ea4..80cb3b2d0997 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -963,6 +963,36 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
return 0;
}
+ /*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init
+e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+{
+ int i;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+ if (type && ei->type != type)
+ continue;
+ /* is the region (part) in overlap with the current region ?*/
+ if (ei->addr >= end || ei->addr + ei->size <= start)
+ continue;
+ /* if the region is at the beginning of <start,end> we move
+ * start to the end of the region since it's ok until there
+ */
+ if (ei->addr <= start)
+ start = ei->addr + ei->size;
+ /* if start is now at or beyond end, we're done, full
+ * coverage */
+ if (start >= end)
+ return 1; /* we're done */
+ }
+ return 0;
+}
+
/*
* Find the highest page frame number we have available
*/
@@ -1317,8 +1347,8 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
/*
* Request address space for all standard resources
*
- * This is called just before pcibios_assign_resources(), which is also
- * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c).
+ * This is called just before pcibios_init(), which is also a
+ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
*/
static int __init request_standard_resources(void)
{
@@ -1339,7 +1369,7 @@ static int __init request_standard_resources(void)
return 0;
}
-fs_initcall(request_standard_resources);
+subsys_initcall(request_standard_resources);
static void __init register_memory(void)
{
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index a6969903f2d6..825b2b4ca721 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -313,7 +313,9 @@ static void __init synchronize_tsc_bp (void)
if (tsc_values[i] < avg)
realdelta = -realdelta;
- printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
+ if (realdelta > 0)
+ printk(KERN_INFO "CPU#%d had %ld usecs TSC "
+ "skew, fixed it up.\n", i, realdelta);
}
sum += delta;
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 4f58b9c0efe3..f48bef15b4f0 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -314,3 +314,4 @@ ENTRY(sys_call_table)
.long sys_get_robust_list
.long sys_splice
.long sys_sync_file_range
+ .long sys_tee /* 315 */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index e38527994590..2d22f5761b1d 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -365,6 +365,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (++die.lock_owner_depth < 3) {
int nl = 0;
+ unsigned long esp;
+ unsigned short ss;
+
handle_BUG(regs);
printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
@@ -387,8 +390,19 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("\n");
if (notify_die(DIE_OOPS, str, regs, err,
current->thread.trap_no, SIGSEGV) !=
- NOTIFY_STOP)
+ NOTIFY_STOP) {
show_registers(regs);
+ /* Executive summary in case the oops scrolled away */
+ esp = (unsigned long) (&regs->esp);
+ savesegment(ss, ss);
+ if (user_mode(regs)) {
+ esp = regs->esp;
+ ss = regs->xss & 0xffff;
+ }
+ printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
+ print_symbol("%s", regs->eip);
+ printk(" SS:ESP %04x:%08lx\n", ss, esp);
+ }
else
regs = NULL;
} else
diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c
index 23967fe658d3..10d21df14531 100644
--- a/arch/i386/mach-voyager/voyager_cat.c
+++ b/arch/i386/mach-voyager/voyager_cat.c
@@ -106,15 +106,20 @@ voyager_module_t *voyager_cat_list;
/* the I/O port assignments for the VIC and QIC */
static struct resource vic_res = {
- "Voyager Interrupt Controller", 0xFC00, 0xFC6F };
+ .name = "Voyager Interrupt Controller",
+ .start = 0xFC00,
+ .end = 0xFC6F
+};
static struct resource qic_res = {
- "Quad Interrupt Controller", 0xFC70, 0xFCFF };
+ .name = "Quad Interrupt Controller",
+ .start = 0xFC70,
+ .end = 0xFCFF
+};
/* This function is used to pack a data bit stream inside a message.
* It writes num_bits of the data buffer in msg starting at start_bit.
* Note: This function assumes that any unused bit in the data stream
* is set to zero so that the ors will work correctly */
-#define BITS_PER_BYTE 8
static void
cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits)
{
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 9f66ac582a8b..ae6534ad8161 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -651,6 +651,7 @@ void __init mem_init(void)
* Specifically, in the case of x86, we will always add
* memory to the highmem for now.
*/
+#ifdef CONFIG_HOTPLUG_MEMORY
#ifndef CONFIG_NEED_MULTIPLE_NODES
int add_memory(u64 start, u64 size)
{
@@ -667,6 +668,7 @@ int remove_memory(u64 start, u64 size)
return -EINVAL;
}
#endif
+#endif
kmem_cache_t *pgd_cache;
kmem_cache_t *pmd_cache;
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 99012b93bd12..5d81fb510375 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -4,6 +4,7 @@
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/dmi.h>
#include "pci.h"
/*
@@ -18,8 +19,10 @@ int pci_conf1_read(unsigned int seg, unsigned int bus,
{
unsigned long flags;
- if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+ if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+ *value = -1;
return -EINVAL;
+ }
spin_lock_irqsave(&pci_config_lock, flags);
@@ -91,8 +94,10 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus,
unsigned long flags;
int dev, fn;
- if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+ if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+ *value = -1;
return -EINVAL;
+ }
dev = PCI_SLOT(devfn);
fn = PCI_FUNC(devfn);
@@ -188,6 +193,10 @@ static int __init pci_sanity_check(struct pci_raw_ops *o)
if (pci_probe & PCI_NO_CHECKS)
return 1;
+ /* Assume Type 1 works for newer systems.
+ This handles machines that don't have anything on PCI Bus 0. */
+ if (dmi_get_year(DMI_BIOS_DATE) >= 2001)
+ return 1;
for (devfn = 0; devfn < 0x100; devfn++) {
if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 3ca59cad05f3..06dab00aaadc 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -588,7 +588,9 @@ static __init int via_router_probe(struct irq_router *r,
case PCI_DEVICE_ID_VIA_82C596:
case PCI_DEVICE_ID_VIA_82C686:
case PCI_DEVICE_ID_VIA_8231:
+ case PCI_DEVICE_ID_VIA_8233A:
case PCI_DEVICE_ID_VIA_8235:
+ case PCI_DEVICE_ID_VIA_8237:
/* FIXME: add new ones for 8233/5 */
r->name = "VIA";
r->get = pirq_via_get;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 613789071f30..6b1ea0c9a570 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,14 +12,20 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <asm/e820.h>
#include "pci.h"
+#define MMCONFIG_APER_SIZE (256*1024*1024)
+
+/* Assume systems with more busses have correct MCFG */
+#define MAX_CHECK_BUS 16
+
#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
/* The base address of the last MMCONFIG device accessed */
static u32 mmcfg_last_accessed_device;
-static DECLARE_BITMAP(fallback_slots, 32);
+static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
/*
* Functions for accessing PCI configuration space with MMCONFIG accesses
@@ -29,8 +35,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;
- if (seg == 0 && bus == 0 &&
- test_bit(PCI_SLOT(devfn), fallback_slots))
+ if (seg == 0 && bus < MAX_CHECK_BUS &&
+ test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
return 0;
while (1) {
@@ -74,8 +80,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
unsigned long flags;
u32 base;
- if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
+ if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
+ *value = -1;
return -EINVAL;
+ }
base = get_base_addr(seg, bus, devfn);
if (!base)
@@ -146,29 +154,34 @@ static struct pci_raw_ops pci_mmcfg = {
Normally this can be expressed in the MCFG by not listing them
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
- and fallback for them.
- We only do this for bus 0/seg 0 */
+ and fallback for them. */
static __init void unreachable_devices(void)
{
- int i;
+ int i, k;
unsigned long flags;
- for (i = 0; i < 32; i++) {
- u32 val1;
- u32 addr;
-
- pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
- if (val1 == 0xffffffff)
- continue;
-
- /* Locking probably not needed, but safer */
- spin_lock_irqsave(&pci_config_lock, flags);
- addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
- if (addr != 0)
- pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
- if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
- set_bit(i, fallback_slots);
- spin_unlock_irqrestore(&pci_config_lock, flags);
+ for (k = 0; k < MAX_CHECK_BUS; k++) {
+ for (i = 0; i < 32; i++) {
+ u32 val1;
+ u32 addr;
+
+ pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
+ if (val1 == 0xffffffff)
+ continue;
+
+ /* Locking probably not needed, but safer */
+ spin_lock_irqsave(&pci_config_lock, flags);
+ addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
+ if (addr != 0)
+ pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
+ if (addr == 0 ||
+ readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
+ set_bit(i, fallback_slots);
+ printk(KERN_NOTICE
+ "PCI: No mmconfig possible on %x:%x\n", k, i);
+ }
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+ }
}
}
@@ -183,6 +196,14 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
+ if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+ pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+ E820_RESERVED)) {
+ printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+ return;
+ }
+
printk(KERN_INFO "PCI: Using MMCONFIG\n");
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index edffe25a477a..0f3076a820c3 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -260,15 +260,6 @@ config NR_CPUS
than 64 will cause the use of a CPU mask array, causing a small
performance hit.
-config IA64_NR_NODES
- int "Maximum number of NODEs (256-1024)" if (IA64_SGI_SN2 || IA64_GENERIC)
- range 256 1024
- depends on IA64_SGI_SN2 || IA64_GENERIC
- default "256"
- help
- This option specifies the maximum number of nodes in your SSI system.
- If in doubt, use the default.
-
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
depends on SMP && EXPERIMENTAL
@@ -352,6 +343,16 @@ config NUMA
Access). This option is for configuring high-end multiprocessor
server systems. If in doubt, say N.
+config NODES_SHIFT
+ int "Max num nodes shift(3-10)"
+ range 3 10
+ default "8"
+ depends on NEED_MULTIPLE_NODES
+ help
+ This option specifies the maximum number of nodes in your SSI system.
+ MAX_NUMNODES will be 2^(This value).
+ If in doubt, use the default.
+
# VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
# VIRTUAL_MEM_MAP has been retained for historical reasons.
config VIRTUAL_MEM_MAP
@@ -412,6 +413,8 @@ config IA64_PALINFO
config SGI_SN
def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
+source "drivers/sn/Kconfig"
+
source "drivers/firmware/Kconfig"
source "fs/Kconfig.binfmt"
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index a718034d68d0..f6a8853cd1b4 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc5
-# Mon Feb 27 16:06:38 2006
+# Linux kernel version: 2.6.17-rc3
+# Thu Apr 27 11:48:23 2006
#
#
@@ -24,6 +24,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_CPUSETS=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -38,10 +39,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -53,7 +50,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -62,6 +58,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -84,8 +81,10 @@ CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_SWIOTLB=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
@@ -116,7 +115,6 @@ CONFIG_IA64_SGI_SN_XP=m
CONFIG_FORCE_MAX_ZONEORDER=17
CONFIG_SMP=y
CONFIG_NR_CPUS=1024
-CONFIG_IA64_NR_NODES=256
# CONFIG_HOTPLUG_CPU is not set
CONFIG_SCHED_SMT=y
CONFIG_PREEMPT=y
@@ -136,6 +134,7 @@ CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=8
CONFIG_VIRTUAL_MEM_MAP=y
CONFIG_HOLES_IN_ZONE=y
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
@@ -187,7 +186,6 @@ CONFIG_ACPI_SYSTEM=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -231,6 +229,7 @@ CONFIG_SYN_COOKIES=y
# 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_DIAG=m
CONFIG_INET_TCP_DIAG=m
@@ -238,9 +237,11 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -468,9 +469,14 @@ CONFIG_SCSI_SATA_VITESSE=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLA_FC is not set
+CONFIG_SCSI_QLA_FC=y
+CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
+# CONFIG_SCSI_QLA21XX is not set
+CONFIG_SCSI_QLA22XX=y
+CONFIG_SCSI_QLA2300=y
+CONFIG_SCSI_QLA2322=y
+# CONFIG_SCSI_QLA24XX is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
@@ -486,6 +492,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=y
# CONFIG_MD_FAULTY is not set
@@ -694,6 +701,7 @@ CONFIG_EFI_RTC=y
# Ftape, the floppy tape device driver
#
CONFIG_AGP=y
+# CONFIG_AGP_VIA is not set
CONFIG_AGP_SGI_TIOCA=y
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=m
@@ -735,10 +743,6 @@ CONFIG_MMTIMER=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -747,6 +751,7 @@ CONFIG_MMTIMER=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -757,6 +762,7 @@ CONFIG_MMTIMER=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
CONFIG_DUMMY_CONSOLE=y
#
@@ -769,6 +775,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -829,9 +836,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -846,15 +851,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -905,15 +901,29 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=m
# CONFIG_INFINIBAND_USER_MAD is not set
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
CONFIG_INFINIBAND_SRP=m
#
@@ -923,8 +933,13 @@ CONFIG_SGI_IOC4=y
CONFIG_SGI_IOC3=y
#
-# EDAC - error detection and reporting (RAS)
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -997,7 +1012,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 4e7a6a1ec6c7..da03c06744f1 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -35,6 +35,9 @@ extern void ia64_elf32_init (struct pt_regs *regs);
static void elf32_set_personality (void);
+static unsigned long __attribute ((unused))
+randomize_stack_top(unsigned long stack_top);
+
#define setup_arg_pages(bprm,tos,exec) ia32_setup_arg_pages(bprm,exec)
#define elf_map elf32_map
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 95fe04400f6b..a32cd59b81ed 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -334,7 +334,7 @@ ia32_syscall_table:
data8 sys_setdomainname
data8 sys32_newuname
data8 sys32_modify_ldt
- data8 sys_ni_syscall /* adjtimex */
+ data8 compat_sys_adjtimex
data8 sys32_mprotect /* 125 */
data8 compat_sys_sigprocmask
data8 sys_ni_syscall /* create_module */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 59e871dae742..09a0dbc17fb6 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
- unwind.o mca.o mca_asm.o topology.o dmi_scan.o
+ unwind.o mca.o mca_asm.o topology.o
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
@@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
-dmi_scan-y += ../../i386/kernel/dmi_scan.o
# The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 4a5574ff007b..fff82929d225 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -1,105 +1,104 @@
/*
- * arch/ia64/kernel/acpi-ext.c
+ * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
+ * Alex Williamson <alex.williamson@hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*
- * Copyright (C) 2003 Hewlett-Packard
- * Copyright (C) Alex Williamson
- * Copyright (C) Bjorn Helgaas
- *
- * Vendor specific extensions to ACPI.
+ * 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/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/acpi.h>
-#include <linux/efi.h>
#include <asm/acpi-ext.h>
-struct acpi_vendor_descriptor {
- u8 guid_id;
- efi_guid_t guid;
-};
+/*
+ * Device CSRs that do not appear in PCI config space should be described
+ * via ACPI. This would normally be done with Address Space Descriptors
+ * marked as "consumer-only," but old versions of Windows and Linux ignore
+ * the producer/consumer flag, so HP invented a vendor-defined resource to
+ * describe the location and size of CSR space.
+ */
-struct acpi_vendor_info {
- struct acpi_vendor_descriptor *descriptor;
- u8 *data;
- u32 length;
+struct acpi_vendor_uuid hp_ccsr_uuid = {
+ .subtype = 2,
+ .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
+ 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
};
-acpi_status
-acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
+static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
{
- struct acpi_vendor_info *info = (struct acpi_vendor_info *)context;
- struct acpi_resource_vendor *vendor;
- struct acpi_vendor_descriptor *descriptor;
- u32 byte_length;
-
- if (resource->type != ACPI_RESOURCE_TYPE_VENDOR)
- return AE_OK;
-
- vendor = (struct acpi_resource_vendor *)&resource->data;
- descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data;
- if (vendor->byte_length <= sizeof(*info->descriptor) ||
- descriptor->guid_id != info->descriptor->guid_id ||
- efi_guidcmp(descriptor->guid, info->descriptor->guid))
- return AE_OK;
-
- byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor);
- info->data = acpi_os_allocate(byte_length);
- if (!info->data)
- return AE_NO_MEMORY;
-
- memcpy(info->data,
- vendor->byte_data + sizeof(struct acpi_vendor_descriptor),
- byte_length);
- info->length = byte_length;
- return AE_CTRL_TERMINATE;
-}
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_resource *resource;
+ struct acpi_resource_vendor_typed *vendor;
-acpi_status
-acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id,
- u8 ** data, u32 * byte_length)
-{
- struct acpi_vendor_info info;
+ status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
+ &buffer);
- info.descriptor = id;
- info.data = NULL;
+ resource = buffer.pointer;
+ vendor = &resource->data.vendor_typed;
- acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match,
- &info);
- if (!info.data)
- return AE_NOT_FOUND;
+ if (ACPI_FAILURE(status) || vendor->byte_length < 16) {
+ status = AE_NOT_FOUND;
+ goto exit;
+ }
- *data = info.data;
- *byte_length = info.length;
- return AE_OK;
+ memcpy(base, vendor->byte_data, sizeof(*base));
+ memcpy(length, vendor->byte_data + 8, sizeof(*length));
+
+ exit:
+ acpi_os_free(buffer.pointer);
+ return status;
}
-struct acpi_vendor_descriptor hp_ccsr_descriptor = {
- .guid_id = 2,
- .guid =
- EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01,
- 0x37, 0x0e, 0xad)
+struct csr_space {
+ u64 base;
+ u64 length;
};
-acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length)
+static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
{
+ struct csr_space *space = data;
+ struct acpi_resource_address64 addr;
acpi_status status;
- u8 *data;
- u32 length;
- status =
- acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
+ status = acpi_resource_to_address64(resource, &addr);
+ if (ACPI_SUCCESS(status) &&
+ addr.resource_type == ACPI_MEMORY_RANGE &&
+ addr.address_length &&
+ addr.producer_consumer == ACPI_CONSUMER) {
+ space->base = addr.minimum;
+ space->length = addr.address_length;
+ return AE_CTRL_TERMINATE;
+ }
+ return AE_OK; /* keep looking */
+}
- if (ACPI_FAILURE(status) || length != 16)
- return AE_NOT_FOUND;
+static acpi_status hp_crs_locate(acpi_handle obj, u64 *base, u64 *length)
+{
+ struct csr_space space = { 0, 0 };
- memcpy(csr_base, data, sizeof(*csr_base));
- memcpy(csr_length, data + 8, sizeof(*csr_length));
- acpi_os_free(data);
+ acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space);
+ if (!space.length)
+ return AE_NOT_FOUND;
+ *base = space.base;
+ *length = space.length;
return AE_OK;
}
+acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
+{
+ acpi_status status;
+
+ status = hp_ccsr_locate(obj, csr_base, csr_length);
+ if (ACPI_SUCCESS(status))
+ return status;
+
+ return hp_crs_locate(obj, csr_base, csr_length);
+}
EXPORT_SYMBOL(hp_acpi_csr_space);
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 750e8e7fbdc3..bcb80ca5cf40 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1606,5 +1606,10 @@ sys_call_table:
data8 sys_ni_syscall // 1295 reserved for ppoll
data8 sys_unshare
data8 sys_splice
+ data8 sys_set_robust_list
+ data8 sys_get_robust_list
+ data8 sys_sync_file_range // 1300
+ data8 sys_tee
+ data8 sys_vmsplice
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 789881ca83d4..f9039f88d01d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -251,7 +251,7 @@ static void __kprobes prepare_break_inst(uint template, uint slot,
update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
}
-static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
unsigned long *kprobe_inst, uint *major_opcode)
{
unsigned long kprobe_inst_p0, kprobe_inst_p1;
@@ -278,7 +278,7 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
}
/* Returns non-zero if the addr is in the Interrupt Vector Table */
-static inline int in_ivt_functions(unsigned long addr)
+static int __kprobes in_ivt_functions(unsigned long addr)
{
return (addr >= (unsigned long)__start_ivt_text
&& addr < (unsigned long)__end_ivt_text);
@@ -308,19 +308,19 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
return 0;
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
}
-static inline void set_current_kprobe(struct kprobe *p,
+static void __kprobes set_current_kprobe(struct kprobe *p,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 8963171788d5..6a0880639bc9 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -581,10 +581,12 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
{
unsigned long flags;
int cpu = smp_processor_id();
+ struct ia64_mca_notify_die nd =
+ { .sos = NULL, .monarch_cpu = &monarch_cpu };
/* Mask all interrupts */
local_irq_save(flags);
- if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -594,7 +596,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
*/
ia64_sal_mc_rendez();
- if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -602,7 +604,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
while (monarch_cpu != -1)
cpu_relax(); /* spin until monarch leaves */
- if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -961,7 +963,7 @@ no_mod:
*/
static void
-ia64_wait_for_slaves(int monarch)
+ia64_wait_for_slaves(int monarch, const char *type)
{
int c, wait = 0, missing = 0;
for_each_online_cpu(c) {
@@ -987,7 +989,7 @@ ia64_wait_for_slaves(int monarch)
}
if (!missing)
goto all_in;
- printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
+ printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
for_each_online_cpu(c) {
if (c == monarch)
continue;
@@ -998,7 +1000,7 @@ ia64_wait_for_slaves(int monarch)
return;
all_in:
- printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
+ printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
return;
}
@@ -1023,6 +1025,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
&sos->proc_state_param;
int recover, cpu = smp_processor_id();
task_t *previous_current;
+ struct ia64_mca_notify_die nd =
+ { .sos = sos, .monarch_cpu = &monarch_cpu };
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
console_loglevel = 15; /* make sure printks make it to console */
@@ -1031,10 +1035,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
monarch_cpu = cpu;
- if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- ia64_wait_for_slaves(cpu);
+ ia64_wait_for_slaves(cpu, "MCA");
/* Wakeup all the processors which are spinning in the rendezvous loop.
* They will leave SAL, then spin in the OS with interrupts disabled
@@ -1043,7 +1047,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
* spinning in SAL does not work.
*/
ia64_mca_wakeup_all();
- if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -1064,7 +1068,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
sos->os_status = IA64_MCA_CORRECTED;
}
- if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover)
+ if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -1351,10 +1355,14 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
static atomic_t monarchs;
task_t *previous_current;
int cpu = smp_processor_id();
+ struct ia64_mca_notify_die nd =
+ { .sos = sos, .monarch_cpu = &monarch_cpu };
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
console_loglevel = 15; /* make sure printks make it to console */
+ (void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
+
printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
sos->proc_state_param, cpu, sos->monarch);
salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
@@ -1390,15 +1398,15 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
while (monarch_cpu == -1)
cpu_relax(); /* spin until monarch enters */
- if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
while (monarch_cpu != -1)
cpu_relax(); /* spin until monarch leaves */
- if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
printk("Slave on cpu %d returning to normal service.\n", cpu);
@@ -1409,7 +1417,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
}
monarch_cpu = cpu;
- if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -1421,15 +1429,15 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
*/
printk("Delaying for 5 seconds...\n");
udelay(5*1000000);
- ia64_wait_for_slaves(cpu);
+ ia64_wait_for_slaves(cpu, "INIT");
/* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
* to default_monarch_init_process() above and just print all the
* tasks.
*/
- if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
@@ -1631,6 +1639,7 @@ ia64_mca_init(void)
printk(KERN_INFO "Increasing MCA rendezvous timeout from "
"%ld to %ld milliseconds\n", timeout, isrv.v0);
timeout = isrv.v0;
+ (void) notify_die(DIE_MCA_NEW_TIMEOUT, "MCA", NULL, timeout, 0, 0);
continue;
}
printk(KERN_ERR "Failed to register rendezvous interrupt "
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 60a464bfd9e2..6dff024cd62b 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -827,7 +827,7 @@ ia64_state_restore:
ld8 r9=[temp2],16 // sal_gp
;;
ld8 r22=[temp1],16 // pal_min_state, virtual
- ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT
+ ld8 r13=[temp2],16 // prev_IA64_KR_CURRENT
;;
ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK
ld8 r20=[temp2],16 // prev_task
@@ -848,7 +848,7 @@ ia64_state_restore:
mov cr.iim=temp3
mov cr.iha=temp4
dep r22=0,r22,62,1 // pal_min_state, physical, uncached
- mov IA64_KR(CURRENT)=r21
+ mov IA64_KR(CURRENT)=r13
ld8 r8=[temp1] // os_status
ld8 r10=[temp2] // context
@@ -856,7 +856,7 @@ ia64_state_restore:
* avoid any dependencies on the algorithm in ia64_switch_to(), just
* purge any existing CURRENT_STACK mapping and insert the new one.
*
- * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains
+ * r16 contains prev_IA64_KR_CURRENT_STACK, r13 contains
* prev_IA64_KR_CURRENT, these values may have been changed by the C
* code. Do not use r8, r9, r10, r22, they contain values ready for
* the return to SAL.
@@ -873,7 +873,7 @@ ia64_state_restore:
;;
srlz.d
- extr.u r19=r21,61,3 // r21 = prev_IA64_KR_CURRENT
+ extr.u r19=r13,61,3 // r13 = prev_IA64_KR_CURRENT
shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK
movl r21=PAGE_KERNEL // page properties
;;
@@ -883,7 +883,7 @@ ia64_state_restore:
(p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:(
;;
mov cr.itir=r18
- mov cr.ifa=r21
+ mov cr.ifa=r13
mov r20=IA64_TR_CURRENT_STACK
;;
itr.d dtr[r20]=r21
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 37c88eb55873..ca6666b51ccb 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -62,6 +62,11 @@ typedef enum {
ISOLATE_NONE
} isolate_status_t;
+typedef enum {
+ MCA_NOT_RECOVERED = 0,
+ MCA_RECOVERED = 1
+} recovery_status_t;
+
/*
* This pool keeps pointers to the section part of SAL error record
*/
@@ -71,6 +76,18 @@ static struct {
int max_idx; /* Maximum index of section pointer list pool */
} slidx_pool;
+static int
+fatal_mca(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vprintk(fmt, args);
+ va_end(args);
+
+ return MCA_NOT_RECOVERED;
+}
+
/**
* mca_page_isolate - isolate a poisoned page in order not to use it later
* @paddr: poisoned memory location
@@ -424,7 +441,7 @@ recover_from_read_error(slidx_table_t *slidx,
/* Is target address valid? */
if (!pbci->tv)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: target address not valid\n");
/*
* cpu read or memory-mapped io read
@@ -442,7 +459,7 @@ recover_from_read_error(slidx_table_t *slidx,
/* Is minstate valid? */
if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: minstate not valid\n");
psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
@@ -476,12 +493,13 @@ recover_from_read_error(slidx_table_t *slidx,
psr2->bn = 1;
psr2->i = 0;
- return 1;
+ return MCA_RECOVERED;
}
}
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: kernel context not recovered,"
+ " iip 0x%lx\n", pmsa->pmsa_iip);
}
/**
@@ -567,13 +585,13 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
* The machine check is corrected.
*/
if (psp->cm == 1)
- return 1;
+ return MCA_RECOVERED;
/*
* The error was not contained. Software must be reset.
*/
if (psp->us || psp->ci == 0)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: error not contained\n");
/*
* The cache check and bus check bits have four possible states
@@ -584,20 +602,22 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
* 1 1 Memory error, attempt recovery
*/
if (psp->bc == 0 || pbci == NULL)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: No bus check\n");
/*
* Sorry, we cannot handle so many.
*/
if (peidx_bus_check_num(peidx) > 1)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: Too many bus checks\n");
/*
* Well, here is only one bus error.
*/
- if (pbci->ib || pbci->cc)
- return 0;
+ if (pbci->ib)
+ return fatal_mca(KERN_ALERT "MCA: Internal Bus error\n");
+ if (pbci->cc)
+ return fatal_mca(KERN_ALERT "MCA: Cache-cache error\n");
if (pbci->eb && pbci->bsi > 0)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: External bus check fatal status\n");
/*
* This is a local MCA and estimated as recoverble external bus error.
@@ -609,7 +629,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
/*
* On account of strange SAL error record, we cannot recover.
*/
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: Strange SAL record\n");
}
/**
@@ -638,12 +658,10 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
/* Now, OS can recover when there is one processor error section */
if (n_proc_err > 1)
- return 0;
- else if (n_proc_err == 0) {
+ return fatal_mca(KERN_ALERT "MCA: Too Many Errors\n");
+ else if (n_proc_err == 0)
/* Weird SAL record ... We need not to recover */
-
- return 1;
- }
+ return fatal_mca(KERN_ALERT "MCA: Weird SAL record\n");
/* Make index of processor error section */
mca_make_peidx((sal_log_processor_info_t*)
@@ -654,7 +672,7 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
/* Check whether MCA is global or not */
if (is_mca_global(&peidx, &pbci, sos))
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: global MCA\n");
/* Try to recover a processor error */
return recover_from_processor_error(platform_err, &slidx, &peidx,
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 7a2f0a798d12..3a30cfc9574f 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -947,7 +947,7 @@ void
percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
{
unsigned int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
memcpy(pcpudst + __per_cpu_offset[i], src, size);
}
}
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 6386f63c413e..859fb37ff49b 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -959,7 +959,7 @@ remove_palinfo_proc_entries(unsigned int hcpu)
}
}
-static int __devinit palinfo_cpu_callback(struct notifier_block *nfb,
+static int palinfo_cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 9d5a823479a3..663a186ad194 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -572,7 +572,7 @@ static struct file_operations salinfo_data_fops = {
};
#ifdef CONFIG_HOTPLUG_CPU
-static int __devinit
+static int
salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
{
unsigned int i, cpu = (unsigned long)hcpu;
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index b47476d655f1..4f3a16b37f8f 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -305,13 +305,10 @@ static struct kobj_type cache_ktype_percpu_entry = {
static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu)
{
- if (all_cpu_cache_info[cpu].cache_leaves) {
- kfree(all_cpu_cache_info[cpu].cache_leaves);
- all_cpu_cache_info[cpu].cache_leaves = NULL;
- }
+ kfree(all_cpu_cache_info[cpu].cache_leaves);
+ all_cpu_cache_info[cpu].cache_leaves = NULL;
all_cpu_cache_info[cpu].num_cache_leaves = 0;
memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
-
return;
}
@@ -429,7 +426,7 @@ static int __cpuinit cache_remove_dev(struct sys_device * sys_dev)
* When a cpu is hot-plugged, do a check and initiate
* cache kobject if necessary
*/
-static int __cpuinit cache_cpu_callback(struct notifier_block *nfb,
+static int cache_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index ec9eeb89975d..b6bcc9fa3603 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -519,6 +519,68 @@ void __cpuinit *per_cpu_init(void)
}
#endif /* CONFIG_SMP */
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
+{
+ unsigned long end_address, hole_next_pfn;
+ unsigned long stop_address;
+
+ end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
+ end_address = PAGE_ALIGN(end_address);
+
+ stop_address = (unsigned long) &vmem_map[
+ pgdat->node_start_pfn + pgdat->node_spanned_pages];
+
+ do {
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = pgd_offset_k(end_address);
+ if (pgd_none(*pgd)) {
+ end_address += PGDIR_SIZE;
+ continue;
+ }
+
+ pud = pud_offset(pgd, end_address);
+ if (pud_none(*pud)) {
+ end_address += PUD_SIZE;
+ continue;
+ }
+
+ pmd = pmd_offset(pud, end_address);
+ if (pmd_none(*pmd)) {
+ end_address += PMD_SIZE;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, end_address);
+retry_pte:
+ if (pte_none(*pte)) {
+ end_address += PAGE_SIZE;
+ pte++;
+ if ((end_address < stop_address) &&
+ (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
+ goto retry_pte;
+ continue;
+ }
+ /* Found next valid vmem_map page */
+ break;
+ } while (end_address < stop_address);
+
+ end_address = min(end_address, stop_address);
+ end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
+ hole_next_pfn = end_address / sizeof(struct page);
+ return hole_next_pfn - pgdat->node_start_pfn;
+}
+#else
+static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
+{
+ return i + 1;
+}
+#endif
+
/**
* show_mem - give short summary of memory stats
*
@@ -547,8 +609,10 @@ void show_mem(void)
struct page *page;
if (pfn_valid(pgdat->node_start_pfn + i))
page = pfn_to_page(pgdat->node_start_pfn + i);
- else
+ else {
+ i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1;
continue;
+ }
if (PageReserved(page))
reserved++;
else if (PageSwapCache(page))
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index af7eb087dca7..d98ec49570b8 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -60,6 +60,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
struct siginfo si;
unsigned long mask;
+ /* mmap_sem is performance critical.... */
+ prefetchw(&mm->mmap_sem);
+
/*
* If we're in an interrupt or have no user context, we must not take the fault..
*/
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 9ba32b2d96d0..ab829a22f8a4 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -31,7 +31,6 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
-
/*
* Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another
@@ -707,7 +706,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
*
* Simply writes @size bytes of @val to @port.
*/
-int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
+int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
{
int ret = size;
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index d917afa30b27..739c948dc504 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -284,6 +284,8 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb
/* find nearest node with cpus and nearest memory */
for (router=NULL, j=0; j < op->ports; j++) {
dest = sn_hwperf_findobj_id(objbuf, nobj, ptdata[j].conn_id);
+ if (dest && SN_HWPERF_IS_ROUTER(dest))
+ router = dest;
if (!dest || SN_HWPERF_FOREIGN(dest) ||
!SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) {
continue;
@@ -299,8 +301,6 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb
*near_mem_node = c;
found_mem++;
}
- if (SN_HWPERF_IS_ROUTER(dest))
- router = dest;
}
if (router && (!found_cpu || !found_mem)) {
@@ -493,7 +493,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
* numalink ports
*/
sz = obj->ports * sizeof(struct sn_hwperf_port_info);
- if ((ptdata = vmalloc(sz)) == NULL)
+ if ((ptdata = kmalloc(sz, GFP_KERNEL)) == NULL)
return -ENOMEM;
e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
SN_HWPERF_ENUM_PORTS, obj->id, sz,
@@ -541,7 +541,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
(SN_HWPERF_IS_NL3ROUTER(obj) ||
SN_HWPERF_IS_NL3ROUTER(p)) ? "LLP3" : "LLP4");
}
- vfree(ptdata);
+ kfree(ptdata);
}
return 0;
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index d0abddd9ffe6..8255a9be4632 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -1831,7 +1831,7 @@ xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
{
struct xpc_partition *part = &xpc_partitions[partid];
enum xpc_retval ret = xpcUnknownReason;
- struct xpc_msg *msg;
+ struct xpc_msg *msg = NULL;
DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 94211429fd0c..2a89cfce4954 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -136,9 +136,7 @@ xpc_get_rsvd_page_pa(int nasid)
}
if (L1_CACHE_ALIGN(len) > buf_len) {
- if (buf_base != NULL) {
- kfree(buf_base);
- }
+ kfree(buf_base);
buf_len = L1_CACHE_ALIGN(len);
buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
GFP_KERNEL, &buf_base);
@@ -159,9 +157,7 @@ xpc_get_rsvd_page_pa(int nasid)
}
}
- if (buf_base != NULL) {
- kfree(buf_base);
- }
+ kfree(buf_base);
if (status != SALRET_OK) {
rp_pa = 0;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index fa073cc4b565..833295624e5d 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -682,9 +682,6 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
int ate_index, last_ate, ps;
struct tioce *ce_mmr;
- if (!TIOCE_M32_ADDR(base))
- return;
-
ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
ps = ce_kern->ce_ate3240_pagesize;
ate_index = ATE_PAGE(base, ps);
@@ -693,6 +690,9 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
if (ate_index < 64)
ate_index = 64;
+ if (last_ate >= TIOCE_NUM_M3240_ATES)
+ last_ate = TIOCE_NUM_M3240_ATES - 1;
+
while (ate_index <= last_ate) {
u64 ate;
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 05c864c6c2d9..41fd490af3b4 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -285,6 +285,11 @@ config NUMA
depends on SMP && BROKEN
default n
+config NODES_SHIFT
+ int
+ default "1"
+ depends on NEED_MULTIPLE_NODES
+
# turning this on wastes a bunch of space.
# Summit needs it only when NUMA is on
config BOOT_IOREMAP
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 3871b65f0c82..920bb742b7a2 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -20,7 +20,7 @@
* Stack layout in 'ret_from_system_call':
* ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be
- * updated in fork.c:copy_process, signal.c:do_signal,
+ * updated in fork.c:copy_thread, signal.c:do_signal,
* ptrace.c and ptrace.h
*
* M32Rx/M32R2 M32R
@@ -41,18 +41,17 @@
* @(0x38,sp) - syscall_nr ditto
* @(0x3c,sp) - acc0h @(0x3c,sp) - acch
* @(0x40,sp) - acc0l @(0x40,sp) - accl
- * @(0x44,sp) - acc1h @(0x44,sp) - psw
- * @(0x48,sp) - acc1l @(0x48,sp) - bpc
- * @(0x4c,sp) - psw @(0x4c,sp) - bbpsw
- * @(0x50,sp) - bpc @(0x50,sp) - bbpc
- * @(0x54,sp) - bbpsw @(0x54,sp) - spu (cr3)
- * @(0x58,sp) - bbpc @(0x58,sp) - fp (r13)
- * @(0x5c,sp) - spu (cr3) @(0x5c,sp) - lr (r14)
- * @(0x60,sp) - fp (r13) @(0x60,sp) - spi (cr12)
- * @(0x64,sp) - lr (r14) @(0x64,sp) - orig_r0
- * @(0x68,sp) - spi (cr2)
- * @(0x6c,sp) - orig_r0
- *
+ * @(0x44,sp) - acc1h @(0x44,sp) - dummy_acc1h
+ * @(0x48,sp) - acc1l @(0x48,sp) - dummy_acc1l
+ * @(0x4c,sp) - psw ditto
+ * @(0x50,sp) - bpc ditto
+ * @(0x54,sp) - bbpsw ditto
+ * @(0x58,sp) - bbpc ditto
+ * @(0x5c,sp) - spu (cr3) ditto
+ * @(0x60,sp) - fp (r13) ditto
+ * @(0x64,sp) - lr (r14) ditto
+ * @(0x68,sp) - spi (cr2) ditto
+ * @(0x6c,sp) - orig_r0 ditto
*/
#include <linux/config.h>
@@ -102,6 +101,12 @@
#define ACC0L(reg) @(0x40,reg)
#define ACC1H(reg) @(0x44,reg)
#define ACC1L(reg) @(0x48,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg) @(0x3C,reg)
+#define ACCL(reg) @(0x40,reg)
+#else
+#error unknown isa configuration
+#endif
#define PSW(reg) @(0x4C,reg)
#define BPC(reg) @(0x50,reg)
#define BBPSW(reg) @(0x54,reg)
@@ -111,21 +116,6 @@
#define LR(reg) @(0x64,reg)
#define SP(reg) @(0x68,reg)
#define ORIG_R0(reg) @(0x6C,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg) @(0x3C,reg)
-#define ACCL(reg) @(0x40,reg)
-#define PSW(reg) @(0x44,reg)
-#define BPC(reg) @(0x48,reg)
-#define BBPSW(reg) @(0x4C,reg)
-#define BBPC(reg) @(0x50,reg)
-#define SPU(reg) @(0x54,reg)
-#define FP(reg) @(0x58,reg) /* FP = R13 */
-#define LR(reg) @(0x5C,reg)
-#define SP(reg) @(0x60,reg)
-#define ORIG_R0(reg) @(0x64,reg)
-#else
-#error unknown isa configuration
-#endif
CF_MASK = 0x00000001
TF_MASK = 0x00000100
@@ -142,7 +132,7 @@ VM_MASK = 0x00020000
#endif
ENTRY(ret_from_fork)
- ld r0, @sp+
+ pop r0
bl schedule_tail
GET_THREAD_INFO(r8)
bra syscall_exit
@@ -231,7 +221,7 @@ restore_all:
RESTORE_ALL
# perform work that needs to be done immediately before resumption
- # r9 : frags
+ # r9 : flags
ALIGN
work_pending:
and3 r4, r9, #_TIF_NEED_RESCHED
@@ -320,7 +310,7 @@ ENTRY(ei_handler)
; GET_ICU_STATUS;
seth r0, #shigh(M32R_ICU_ISTS_ADDR)
ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
- st r0, @-sp
+ push r0
#if defined(CONFIG_SMP)
/*
* If IRQ == 0 --> Nothing to do, Not write IMASK
@@ -557,7 +547,7 @@ check_end:
#endif /* CONFIG_PLAT_M32104UT */
bl do_IRQ
#endif /* CONFIG_SMP */
- ld r14, @sp+
+ pop r14
seth r0, #shigh(M32R_ICU_IMASK_ADDR)
st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
#else
@@ -1015,4 +1005,3 @@ ENTRY(sys_call_table)
.long sys_waitid
syscall_table_size=(.-sys_call_table)
-
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index be8b711367ec..c50330fa83b9 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -23,9 +23,6 @@ EXPORT_SYMBOL(boot_cpu_data);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__down_interruptible);
@@ -38,13 +35,6 @@ EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__delay);
EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__get_user_1);
-EXPORT_SYMBOL(__get_user_2);
-EXPORT_SYMBOL(__get_user_4);
-
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
-
EXPORT_SYMBOL(strncpy_from_user);
EXPORT_SYMBOL(__strncpy_from_user);
EXPORT_SYMBOL(clear_user);
@@ -59,11 +49,8 @@ extern void *dcache_dummy;
EXPORT_SYMBOL(dcache_dummy);
#endif
EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_callout_map);
/* Global SMP stuff */
-EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(smp_call_function);
/* TLB flushing */
@@ -83,27 +70,11 @@ EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);
/* memory and string operations */
-EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(memcpy);
-/* EXPORT_SYMBOL(memcpy_fromio); // not implement yet */
-/* EXPORT_SYMBOL(memcpy_toio); // not implement yet */
EXPORT_SYMBOL(memset);
-/* EXPORT_SYMBOL(memset_io); // not implement yet */
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(clear_page);
-
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(_inb);
EXPORT_SYMBOL(_inw);
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 5dfc7ea45cf7..065f5e719058 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -116,6 +116,10 @@ void cpu_idle (void)
void machine_restart(char *__unused)
{
+#if defined(CONFIG_PLAT_MAPPI3)
+ outw(1, (unsigned long)PLD_REBOOT);
+#endif
+
printk("Please push reset button!\n");
while (1)
cpu_relax();
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 0d78942b4c76..3cd3c2988a48 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/fs.h>
#include <linux/sched.h>
@@ -219,8 +220,6 @@ static unsigned long __init setup_memory(void)
extern unsigned long setup_memory(void);
#endif /* CONFIG_DISCONTIGMEM */
-#define M32R_PCC_PCATCR 0x00ef7014 /* will move to m32r.h */
-
void __init setup_arch(char **cmdline_p)
{
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
@@ -269,15 +268,14 @@ void __init setup_arch(char **cmdline_p)
paging_init();
}
-static struct cpu cpu[NR_CPUS];
+static struct cpu cpu_devices[NR_CPUS];
static int __init topology_init(void)
{
- int cpu_id;
+ int i;
- for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
- if (cpu_possible(cpu_id))
- register_cpu(&cpu[cpu_id], cpu_id, NULL);
+ for_each_present_cpu(i)
+ register_cpu(&cpu_devices[i], i, NULL);
return 0;
}
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index cb33097fefc4..6498ee70bb73 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -118,6 +118,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
COPY(acch);
COPY(accl);
+ COPY(dummy_acc1h);
+ COPY(dummy_acc1l);
#else
#error unknown isa configuration
#endif
@@ -203,6 +205,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
COPY(acch);
COPY(accl);
+ COPY(dummy_acc1h);
+ COPY(dummy_acc1l);
#else
#error unknown isa configuration
#endif
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index d7ec16e7fb25..840b4348bf0c 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -39,8 +39,10 @@
* Martin J. Bligh : Added support for multi-quad systems
*/
+#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/irq.h>
@@ -72,11 +74,15 @@ physid_mask_t phys_cpu_present_map;
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
cpumask_t cpu_bootout_map;
cpumask_t cpu_bootin_map;
-cpumask_t cpu_callout_map;
static cpumask_t cpu_callin_map;
+cpumask_t cpu_callout_map;
+EXPORT_SYMBOL(cpu_callout_map);
+cpumask_t cpu_possible_map = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_possible_map);
/* Per CPU bogomips and other parameters */
struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
@@ -110,7 +116,6 @@ static unsigned int calibration_result;
void smp_prepare_boot_cpu(void);
void smp_prepare_cpus(unsigned int);
-static void smp_tune_scheduling(void);
static void init_ipi_lock(void);
static void do_boot_cpu(int);
int __cpu_up(unsigned int);
@@ -177,6 +182,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
physid_set(phys_id, phys_cpu_present_map);
+#ifndef CONFIG_HOTPLUG_CPU
+ cpu_present_map = cpu_possible_map;
+#endif
show_mp_info(nr_cpu);
@@ -186,7 +194,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
* Setup boot CPU information
*/
smp_store_cpu_info(0); /* Final full version of the data */
- smp_tune_scheduling();
/*
* If SMP should be disabled, then really disable it!
@@ -230,11 +237,6 @@ smp_done:
Dprintk("Boot done.\n");
}
-static void __init smp_tune_scheduling(void)
-{
- /* Nothing to do. */
-}
-
/*
* init_ipi_lock : Initialize IPI locks.
*/
@@ -629,4 +631,3 @@ static void __init unmap_cpu_to_physid(int cpu_id, int phys_id)
physid_2_cpu[phys_id] = -1;
cpu_2_physid[cpu_id] = -1;
}
-
diff --git a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile
index e632d10c7d78..d16b4e40d1ae 100644
--- a/arch/m32r/lib/Makefile
+++ b/arch/m32r/lib/Makefile
@@ -2,6 +2,6 @@
# Makefile for M32R-specific library files..
#
-lib-y := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
- putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
+lib-y := checksum.o ashxdi3.o memset.o memcpy.o \
+ delay.o strlen.o usercopy.o csum_partial_copy.o
diff --git a/arch/m32r/lib/getuser.S b/arch/m32r/lib/getuser.S
deleted file mode 100644
index 58a0db055c5c..000000000000
--- a/arch/m32r/lib/getuser.S
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * __get_user functions.
- *
- * (C) Copyright 2001 Hirokazu Takata
- *
- * These functions have a non-standard call interface
- * to make them more efficient, especially as they
- * return an error value in addition to the "real"
- * return value.
- */
-
-#include <linux/config.h>
-
-/*
- * __get_user_X
- *
- * Inputs: r0 contains the address
- *
- * Outputs: r0 is error code (0 or -EFAULT)
- * r1 contains zero-extended value
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-#ifdef CONFIG_ISA_DUAL_ISSUE
-
- .text
- .balign 4
- .globl __get_user_1
-__get_user_1:
-1: ldub r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_2
-__get_user_2:
-2: lduh r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_4
-__get_user_4:
-3: ld r1, @r0 || ldi r0, #0
- jmp r14
-
-bad_get_user:
- ldi r1, #0 || ldi r0, #-14
- jmp r14
-
-#else /* not CONFIG_ISA_DUAL_ISSUE */
-
- .text
- .balign 4
- .globl __get_user_1
-__get_user_1:
-1: ldub r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_2
-__get_user_2:
-2: lduh r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_4
-__get_user_4:
-3: ld r1, @r0
- ldi r0, #0
- jmp r14
-
-bad_get_user:
- ldi r1, #0
- ldi r0, #-14
- jmp r14
-
-#endif /* not CONFIG_ISA_DUAL_ISSUE */
-
-.section __ex_table,"a"
- .long 1b,bad_get_user
- .long 2b,bad_get_user
- .long 3b,bad_get_user
-.previous
-
- .end
diff --git a/arch/m32r/lib/putuser.S b/arch/m32r/lib/putuser.S
deleted file mode 100644
index 218154cc3890..000000000000
--- a/arch/m32r/lib/putuser.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * __put_user functions.
- *
- * (C) Copyright 1998 Linus Torvalds
- * (C) Copyright 2001 Hirokazu Takata
- *
- * These functions have a non-standard call interface
- * to make them more efficient.
- */
-
-#include <linux/config.h>
-
-/*
- * __put_user_X
- *
- * Inputs: r0 contains the address
- * r1 contains the value
- *
- * Outputs: r0 is error code (0 or -EFAULT)
- * r1 is corrupted (will contain "current_task").
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-#ifdef CONFIG_ISA_DUAL_ISSUE
-
- .text
- .balign 4
- .globl __put_user_1
-__put_user_1:
-1: stb r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_2
-__put_user_2:
-2: sth r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_4
-__put_user_4:
-3: st r1, @r0 || ldi r0, #0
- jmp r14
-
-bad_put_user:
- ldi r0, #-14 || jmp r14
-
-#else /* not CONFIG_ISA_DUAL_ISSUE */
-
- .text
- .balign 4
- .globl __put_user_1
-__put_user_1:
-1: stb r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_2
-__put_user_2:
-2: sth r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_4
-__put_user_4:
-3: st r1, @r0
- ldi r0, #0
- jmp r14
-
-bad_put_user:
- ldi r0, #-14
- jmp r14
-
-#endif /* not CONFIG_ISA_DUAL_ISSUE */
-
-.section __ex_table,"a"
- .long 1b,bad_put_user
- .long 2b,bad_put_user
- .long 3b,bad_put_user
-.previous
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index c3319514a85e..5b7952ea2bae 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -57,7 +57,6 @@ EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index f9b4ea16c099..4320d5dcc9cb 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -26,7 +26,6 @@ EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strchr);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e15709ce8866..ee5fbb02b28f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -816,6 +816,10 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+ bool
+ default y
+
#
# Select some configuration options automatically based on user selections.
#
@@ -1063,6 +1067,7 @@ choice
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
@@ -1080,6 +1085,7 @@ config CPU_MIPS32_R1
config CPU_MIPS32_R2
bool "MIPS32 Release 2"
depends on SYS_HAS_CPU_MIPS32_R2
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
@@ -1093,6 +1099,7 @@ config CPU_MIPS32_R2
config CPU_MIPS64_R1
bool "MIPS64 Release 1"
depends on SYS_HAS_CPU_MIPS64_R1
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1111,6 +1118,7 @@ config CPU_MIPS64_R1
config CPU_MIPS64_R2
bool "MIPS64 Release 2"
depends on SYS_HAS_CPU_MIPS64_R2
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1125,6 +1133,7 @@ config CPU_MIPS64_R2
config CPU_R3000
bool "R3000"
depends on SYS_HAS_CPU_R3000
+ select CPU_HAS_WB
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
help
@@ -1154,6 +1163,7 @@ config CPU_VR41XX
config CPU_R4300
bool "R4300"
depends on SYS_HAS_CPU_R4300
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1162,6 +1172,7 @@ config CPU_R4300
config CPU_R4X00
bool "R4x00"
depends on SYS_HAS_CPU_R4X00
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1171,6 +1182,7 @@ config CPU_R4X00
config CPU_TX49XX
bool "R49XX"
depends on SYS_HAS_CPU_TX49XX
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1178,6 +1190,7 @@ config CPU_TX49XX
config CPU_R5000
bool "R5000"
depends on SYS_HAS_CPU_R5000
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1186,12 +1199,14 @@ config CPU_R5000
config CPU_R5432
bool "R5432"
depends on SYS_HAS_CPU_R5432
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
config CPU_R6000
bool "R6000"
depends on EXPERIMENTAL
+ select CPU_HAS_LLSC
depends on SYS_HAS_CPU_R6000
select CPU_SUPPORTS_32BIT_KERNEL
help
@@ -1201,6 +1216,7 @@ config CPU_R6000
config CPU_NEVADA
bool "RM52xx"
depends on SYS_HAS_CPU_NEVADA
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1210,6 +1226,7 @@ config CPU_R8000
bool "R8000"
depends on EXPERIMENTAL
depends on SYS_HAS_CPU_R8000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1219,6 +1236,7 @@ config CPU_R8000
config CPU_R10000
bool "R10000"
depends on SYS_HAS_CPU_R10000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1229,6 +1247,7 @@ config CPU_R10000
config CPU_RM7000
bool "RM7000"
depends on SYS_HAS_CPU_RM7000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1237,6 +1256,7 @@ config CPU_RM7000
config CPU_RM9000
bool "RM9000"
depends on SYS_HAS_CPU_RM9000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1245,6 +1265,7 @@ config CPU_RM9000
config CPU_SB1
bool "SB1"
depends on SYS_HAS_CPU_SB1
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
@@ -1443,6 +1464,12 @@ choice
prompt "MIPS MT options"
depends on MIPS_MT
+config MIPS_MT_SMTC
+ bool "SMTC: Use all TCs on all VPEs for SMP"
+ select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_SRS
+ select SMP
+
config MIPS_MT_SMP
bool "Use 1 TC on each available VPE for SMP"
select SMP
@@ -1456,6 +1483,11 @@ config MIPS_VPE_LOADER
endchoice
+config MIPS_MT_FPAFF
+ bool "Dynamic FPU affinity for FP-intensive threads"
+ depends on MIPS_MT
+ default y
+
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
depends on MIPS_VPE_LOADER
@@ -1472,6 +1504,16 @@ config MIPS_VPE_APSP_API
depends on MIPS_VPE_LOADER
help
+config MIPS_APSP_KSPD
+ bool "Enable KSPD"
+ depends on MIPS_VPE_APSP_API
+ default y
+ help
+ KSPD is a kernel daemon that accepts syscall requests from the SP
+ side, actions them and returns the results. It also handles the
+ "exit" syscall notifying other kernel modules the SP program is
+ exiting. You probably want to say yes here.
+
config SB1_PASS_1_WORKAROUNDS
bool
depends on CPU_SB1_PASS_1
@@ -1491,38 +1533,15 @@ config 64BIT_PHYS_ADDR
bool "Support for 64-bit physical address space"
depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && 32BIT
-config CPU_ADVANCED
- bool "Override CPU Options"
- depends on 32BIT
- help
- Saying yes here allows you to select support for various features
- your CPU may or may not have. Most people should say N here.
-
config CPU_HAS_LLSC
- bool "ll/sc Instructions available" if CPU_ADVANCED
- default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX
- help
- MIPS R4000 series and later provide the Load Linked (ll)
- and Store Conditional (sc) instructions. More information is
- available at <http://www.go-ecs.com/mips/miptek1.htm>.
-
- Say Y here if your CPU has the ll and sc instructions. Say Y here
- for better performance, N if you don't know. You must say Y here
- for multiprocessor machines.
+ bool
config CPU_HAS_WB
- bool "Writeback Buffer available" if CPU_ADVANCED
- default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION
- help
- Say N here for slightly better performance. You must say Y here for
- machines which require flushing of write buffers in software. Saying
- Y is the safe option; N may result in kernel malfunction and crashes.
-
-menu "MIPSR2 Interrupt handling"
- depends on CPU_MIPSR2 && CPU_ADVANCED
+ bool
config CPU_MIPSR2_IRQ_VI
bool "Vectored interrupt mode"
+ depends on CPU_MIPSR2
help
Vectored interrupt mode allowing faster dispatching of interrupts.
The board support code needs to be written to take advantage of this
@@ -1532,6 +1551,7 @@ config CPU_MIPSR2_IRQ_VI
config CPU_MIPSR2_IRQ_EI
bool "External interrupt controller mode"
+ depends on CPU_MIPSR2
help
Extended interrupt mode takes advantage of an external interrupt
controller to allow fast dispatching from many possible interrupt
@@ -1545,7 +1565,6 @@ config CPU_MIPSR2_SRS
Allow the kernel to use shadow register sets for fast interrupts.
Interrupt handlers must be specially written to use shadow sets.
Say N unless you know that shadow register set upport is needed.
-endmenu
config CPU_HAS_SYNC
bool
@@ -1590,11 +1609,16 @@ config ARCH_FLATMEM_ENABLE
def_bool y
depends on !NUMA
+config NODES_SHIFT
+ int
+ default "6"
+ depends on NEED_MULTIPLE_NODES
+
source "mm/Kconfig"
config SMP
bool "Multi-Processing support"
- depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP
+ depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP || MIPS_MT_SMTC
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index d3c5cc3b9c9d..515f9e611307 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -6,7 +6,13 @@ config CROSSCOMPILE
bool "Are you using a crosscompiler"
help
Say Y here if you are compiling the kernel on a different
- architecture than the one it is intended to run on.
+ architecture than the one it is intended to run on. This is just a
+ convenience option which will select the appropriate value for
+ the CROSS_COMPILE make variable which otherwise has to be passed on
+ the command line from mips-linux-, mipsel-linux-, mips64-linux- and
+ mips64el-linux- as appropriate for a particular kernel configuration.
+ You will have to pass the value for CROSS_COMPILE manually if the
+ name prefix for your tools is different.
config CMDLINE
string "Default kernel command string"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 9a69e0f0ab76..133900aca992 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -105,18 +105,18 @@ 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_MIPS32_R1) += $(call cc-option,-march=mips32,-mips2 -mtune=r4600) \
+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,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32r2 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips2 -mtune=r4600 ) \
+cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64r2 -Wa,--trap
cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap
-cflags-$(CONFIG_CPU_R5432) += $(call cc-options,-march=r5400,-march=r5000) \
+cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \
-Wa,--trap
-cflags-$(CONFIG_CPU_NEVADA) += $(call cc-options,-march=rm5200,-march=r5000) \
+cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
-Wa,--trap
cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \
-Wa,--trap
@@ -615,7 +615,10 @@ LDFLAGS += -m $(ld-emul)
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \
egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \
- sed -e 's/^\#define /-D/' -e 's/ /="/' -e 's/$$/"/')
+ sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
+ifdef CONFIG_64BIT
+CHECKFLAGS += -m64
+endif
endif
OBJCOPYFLAGS += --remove-section=.reginfo
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
index a1edfd1f643c..bf682f50b859 100644
--- a/arch/mips/au1000/common/Makefile
+++ b/arch/mips/au1000/common/Makefile
@@ -6,7 +6,7 @@
# Makefile for the Alchemy Au1000 CPU, generic files.
#
-obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
+obj-y += prom.o irq.o puts.o time.o reset.o \
au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
sleeper.o cputable.o dma.o dbdma.o gpio.o
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
deleted file mode 100644
index 1c4ca883321e..000000000000
--- a/arch/mips/au1000/common/int-handler.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: ppopov@mvista.com
- *
- * Interrupt dispatcher for Au1000 boards.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .set macro
- .set noat
- .align 5
-
-NESTED(au1000_IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI # Important: mark KERNEL mode !
-
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
-
- andi t0,0xff00 # isolate pending bits
- beqz t0, 3f # spurious interrupt
-
- andi a0, t0, CAUSEF_IP7
- beq a0, zero, 1f
- move a0, sp
- jal mips_timer_interrupt
- j ret_from_irq
-
-1:
- andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0
- beq a0, zero, 2f
- move a0,sp
- jal intc0_req0_irqdispatch
- j ret_from_irq
-2:
- andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1
- beq a0, zero, 3f
- move a0,sp
- jal intc0_req1_irqdispatch
- j ret_from_irq
-3:
- andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0
- beq a0, zero, 4f
- move a0,sp
- jal intc1_req0_irqdispatch
- j ret_from_irq
-4:
- andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1
- beq a0, zero, 5f
- move a0, sp
- jal intc1_req1_irqdispatch
- j ret_from_irq
-
-5:
- move a0, sp
- j spurious_interrupt
-END(au1000_IRQ)
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 1339a0979f66..da61de776154 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -66,7 +66,6 @@
#define EXT_INTC1_REQ1 5 /* IP 5 */
#define MIPS_TIMER_IP 7 /* IP 7 */
-extern asmlinkage void au1000_IRQ(void);
extern void set_debug_traps(void);
extern irq_cpustat_t irq_stat [NR_CPUS];
@@ -446,7 +445,6 @@ void __init arch_init_irq(void)
extern int au1xxx_ic0_nr_irqs;
cp0_status = read_c0_status();
- set_except_vector(0, au1000_IRQ);
/* Initialize interrupt controllers to a safe state.
*/
@@ -661,3 +659,21 @@ restore_au1xxx_intctl(void)
au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
}
#endif /* CONFIG_PM */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ mips_timer_interrupt(regs);
+ else if (pending & CAUSEF_IP2)
+ intc0_req0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP3)
+ intc0_req1_irqdispatch(regs);
+ else if (pending & CAUSEF_IP4)
+ intc1_req0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP5)
+ intc1_req1_irqdispatch(regs);
+ else
+ spurious_interrupt(regs);
+}
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 720e757b2b64..225ac8f34ccd 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Cobalt micro systems family specific parts of the kernel
#
-obj-y := irq.o int-handler.o reset.o setup.o
+obj-y := irq.o reset.o setup.o
obj-$(CONFIG_EARLY_PRINTK) += console.o
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
deleted file mode 100644
index e75d5e3ca868..000000000000
--- a/arch/mips/cobalt/int-handler.S
+++ /dev/null
@@ -1,25 +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) 1995, 1996, 1997, 2003 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/mach-cobalt/cobalt.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .align 5
- NESTED(cobalt_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
- PTR_LA ra, ret_from_irq
- move a0, sp
- j cobalt_irq
-
- END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index f9a108820d6e..0b75f4fb7195 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -20,8 +20,6 @@
#include <asm/mach-cobalt/cobalt.h>
-extern void cobalt_handle_int(void);
-
/*
* We have two types of interrupts that we handle, ones that come in through
* the CPU interrupt lines, and ones that come in on the via chip. The CPU
@@ -79,7 +77,7 @@ static inline void via_pic_irq(struct pt_regs *regs)
do_IRQ(irq, regs);
}
-asmlinkage void cobalt_irq(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned pending;
@@ -122,8 +120,6 @@ void __init arch_init_irq(void)
*/
GALILEO_OUTL(0, GT_INTRMASK_OFS);
- set_except_vector(0, cobalt_handle_int);
-
init_i8259_irqs(); /* 0 ... 15 */
mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 9e1ae953e966..4b080bcb258f 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:52 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:55 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -127,11 +129,11 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED 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
@@ -149,7 +151,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -165,6 +166,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -178,10 +180,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -193,7 +191,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -202,6 +199,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -221,7 +220,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -249,6 +247,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -281,6 +280,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -322,9 +322,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -348,11 +351,14 @@ 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_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_PHYSDEV=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -376,20 +382,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=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_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -407,6 +412,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -427,12 +433,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -478,6 +482,11 @@ CONFIG_IP_SCTP=m
# 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=m
CONFIG_VLAN_8021Q=m
@@ -492,11 +501,6 @@ CONFIG_IPDDP_ENCAP=y
CONFIG_IPDDP_DECAP=y
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -556,6 +560,9 @@ 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
@@ -694,9 +701,8 @@ CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -715,6 +721,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -921,6 +928,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=m
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -930,6 +938,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -988,10 +997,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -1022,6 +1027,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -1039,13 +1045,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1120,7 +1144,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1140,7 +1163,6 @@ CONFIG_VXFS_FS=m
# CONFIG_QNX4FS_FS is not set
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1232,6 +1254,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 32984100a75e..d85cda58d650 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:53 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:55 2006
#
CONFIG_MIPS=y
@@ -80,6 +80,8 @@ CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_CPU_BIG_ENDIAN=y
@@ -154,7 +156,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -172,6 +173,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -186,10 +188,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -201,7 +199,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -210,6 +207,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -230,7 +228,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_DEBUG=y
CONFIG_MMU=y
@@ -249,6 +246,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_BUILD_ELF64=y
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -263,6 +261,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -284,12 +283,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -301,6 +303,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -310,11 +317,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -377,7 +379,7 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -575,6 +577,7 @@ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -637,7 +640,6 @@ CONFIG_I2C_ALGO_SIBYTE=y
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
CONFIG_I2C_SIBYTE=y
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -656,9 +658,7 @@ CONFIG_SENSORS_EEPROM=y
CONFIG_SENSORS_PCF8574=y
CONFIG_SENSORS_PCA9539=y
CONFIG_SENSORS_PCF8591=y
-CONFIG_SENSORS_RTC8564=y
CONFIG_SENSORS_MAX6875=y
-# CONFIG_RTC_X1205_I2C is not set
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
@@ -686,10 +686,6 @@ CONFIG_I2C_DEBUG_CHIP=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -714,6 +710,7 @@ CONFIG_I2C_DEBUG_CHIP=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -731,13 +728,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -785,7 +800,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 6c2961affbd6..ca0af1683a00 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:54 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:06 2006
#
CONFIG_MIPS=y
@@ -72,6 +72,8 @@ CONFIG_ZAO_CAPCELLA=y
CONFIG_PCI_VR41XX=y
# CONFIG_VRC4173 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -90,7 +92,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# 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_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -103,18 +105,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+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 is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -179,7 +180,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -187,6 +187,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -206,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -224,6 +226,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -233,6 +236,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -255,12 +259,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -272,6 +279,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -281,11 +293,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -302,10 +309,7 @@ CONFIG_TCP_CONG_BIC=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 is not set
#
# Device Drivers
@@ -348,10 +352,12 @@ CONFIG_CONNECTOR=m
# 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_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -578,6 +584,11 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -601,6 +612,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
#
@@ -636,10 +648,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -670,6 +678,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -687,13 +696,48 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
#
# File systems
@@ -712,7 +756,7 @@ CONFIG_EXT2_FS=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
@@ -735,10 +779,9 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -805,44 +848,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=32M console=ttyVR0,38400"
#
# 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_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=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_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -852,8 +871,6 @@ CONFIG_CRYPTO_CRC32C=m
# Library routines
#
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 8336b21d3db2..7d269e609282 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:55 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:57 2006
#
CONFIG_MIPS=y
@@ -63,7 +63,10 @@ CONFIG_MIPS_COBALT=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_EARLY_PRINTK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -113,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -135,7 +137,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +152,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,6 +180,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -201,7 +201,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -229,6 +228,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -247,12 +247,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -264,6 +267,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -273,11 +281,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -298,6 +301,9 @@ 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
@@ -343,7 +349,7 @@ 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_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -593,6 +599,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -602,6 +609,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -660,10 +668,6 @@ CONFIG_COBALT_LCD=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -694,6 +698,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -711,13 +716,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -765,7 +788,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -828,6 +850,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 7f071403c8e3..579b665e3339 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:56 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:57 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1000=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +153,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +167,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -190,6 +187,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -245,6 +244,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -267,7 +267,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -278,6 +279,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -294,10 +297,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -321,6 +327,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -330,11 +341,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -356,6 +362,9 @@ 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
@@ -412,7 +421,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -434,7 +442,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -471,7 +478,7 @@ 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_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -722,10 +729,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -756,6 +759,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
@@ -773,12 +777,30 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -836,7 +858,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -945,6 +966,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 98590cac1ec5..e5eb53867422 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:57 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:58 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1100=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +153,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +167,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -190,6 +187,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -234,6 +233,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -256,7 +256,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -267,6 +268,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -283,10 +286,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -310,6 +316,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -319,11 +330,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -345,6 +351,9 @@ 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
@@ -401,7 +410,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -423,7 +431,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -460,7 +467,7 @@ 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_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -690,10 +697,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -711,6 +714,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_S1D13XXX is not set
@@ -755,6 +759,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
@@ -772,12 +777,30 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -835,7 +858,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -944,6 +966,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 92888472dca0..a43fb2329fd5 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:58 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:58 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1200=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -244,6 +243,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -263,7 +263,8 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -274,6 +275,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -288,10 +291,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -315,6 +321,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -324,11 +335,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -403,7 +409,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -425,7 +430,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -763,10 +767,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -784,6 +784,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_S1D13XXX is not set
@@ -794,6 +795,7 @@ CONFIG_FB_AU1200=y
# 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
@@ -816,6 +818,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -832,6 +835,7 @@ CONFIG_USB_GADGET=m
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_LH7A40X is not set
# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
# CONFIG_USB_GADGET_DUALSPEED is not set
@@ -844,12 +848,30 @@ CONFIG_MMC_BLOCK=y
CONFIG_MMC_AU1X=y
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -913,7 +935,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1027,6 +1048,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=48M"
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 5a415b1d4af0..ad632d87c4ef 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:59 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:59 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1500=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,11 +118,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -138,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,7 +181,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -192,6 +189,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -211,7 +210,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -253,6 +251,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -275,7 +274,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -302,10 +304,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -338,11 +348,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@ 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
@@ -420,7 +428,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -486,7 +492,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -714,6 +720,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -725,6 +732,7 @@ CONFIG_SERIAL_8250_AU1X00=y
#
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
@@ -790,10 +798,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -802,6 +806,7 @@ CONFIG_SYNCLINK_CS=m
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -825,9 +830,11 @@ 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_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
@@ -846,6 +853,7 @@ CONFIG_SND_MTPAV=m
# 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
@@ -877,6 +885,7 @@ CONFIG_SND_MTPAV=m
# 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
@@ -905,34 +914,22 @@ CONFIG_SND_AU1X00=m
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-CONFIG_OBSOLETE_OSS_DRIVER=y
# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_AU1000 is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 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
@@ -958,7 +955,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
@@ -985,9 +981,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -1001,15 +995,6 @@ CONFIG_USB_YEALINK=m
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1059,13 +1044,31 @@ CONFIG_USB_LD=m
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1123,7 +1126,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1232,6 +1234,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 8dc1f18badfe..8130e23dc255 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:00 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:00 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1550=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -137,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -252,6 +250,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -274,7 +273,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -285,6 +285,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -301,10 +303,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -328,6 +333,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -337,11 +347,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -363,6 +368,9 @@ 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
@@ -419,7 +427,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -442,7 +449,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -489,7 +495,7 @@ 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_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -754,6 +760,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -765,6 +772,7 @@ CONFIG_SERIAL_8250_AU1X00=y
#
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
@@ -830,10 +838,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -858,6 +862,7 @@ CONFIG_SYNCLINK_CS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -875,13 +880,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -939,7 +962,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1048,6 +1070,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
index 8fae63e47e5e..8d88ac1bbfeb 100644
--- a/arch/mips/configs/ddb5476_defconfig
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:02 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:00 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_DDB5476=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -136,7 +137,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +152,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,6 +180,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -202,7 +201,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_ISA=y
CONFIG_MMU=y
@@ -231,6 +229,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -252,12 +251,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -269,6 +271,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -278,11 +285,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -303,6 +305,9 @@ 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
@@ -348,7 +353,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -571,6 +576,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -580,6 +586,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -638,10 +645,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -659,6 +662,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -670,7 +674,6 @@ CONFIG_FB=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -708,6 +711,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -725,13 +729,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -776,7 +798,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -840,6 +861,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE="ip=any"
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index a0fcd44e7709..8c911b671415 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:02 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:01 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_DDB5477=y
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_DDB5477_BUS_FREQUENCY=0
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -136,7 +137,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +152,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,6 +180,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -202,7 +201,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -230,6 +228,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -251,12 +250,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -268,6 +270,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -277,11 +284,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -302,6 +304,9 @@ 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
@@ -346,7 +351,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -556,6 +561,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -565,6 +571,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -623,10 +630,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -657,6 +660,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -674,13 +678,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -725,7 +747,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -792,6 +813,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE="ip=any"
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 5a181eadd437..d838496e114f 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:03 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:01 2006
#
CONFIG_MIPS=y
@@ -63,11 +63,13 @@ CONFIG_MACH_DECSTATION=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_EARLY_PRINTK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_EARLY_PRINTK=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
@@ -113,7 +115,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_WB=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +136,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +151,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -180,7 +177,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -189,6 +185,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -233,11 +231,10 @@ 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_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -254,12 +251,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -271,6 +271,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -280,11 +285,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -305,6 +305,9 @@ 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
@@ -345,7 +348,7 @@ CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -567,10 +570,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -588,6 +587,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_S1D13XXX is not set
@@ -617,6 +617,7 @@ CONFIG_LOGO_DEC_CLUT224=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -633,12 +634,30 @@ CONFIG_LOGO_DEC_CLUT224=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -686,7 +705,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -705,7 +723,6 @@ CONFIG_RELAYFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=y
-CONFIG_UFS_FS_WRITE=y
#
# Network File Systems
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 8fbfc06a6a2a..0760f4318910 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:04 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:20 2006
#
CONFIG_MIPS=y
@@ -70,6 +70,8 @@ CONFIG_CASIO_E55=y
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -88,7 +90,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# 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_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -101,18 +103,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+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 is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -144,11 +148,10 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -162,10 +165,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -177,7 +176,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -185,6 +183,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -219,85 +220,12 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# 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_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_TUNNEL=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 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
-# 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
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_NET_DIVERT 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_NET is not set
#
# Device Drivers
@@ -313,7 +241,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
#
# Memory Technology Devices (MTD)
@@ -335,11 +262,11 @@ CONFIG_CONNECTOR=m
#
# 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_RAM is not set
+CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# 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
@@ -398,81 +325,8 @@ CONFIG_IDE_GENERIC=y
#
#
-# 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
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII 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
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# 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_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
@@ -508,11 +362,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -531,6 +381,10 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -565,6 +419,7 @@ CONFIG_WATCHDOG=y
#
# Ftape, the floppy tape device driver
#
+CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
#
@@ -600,10 +455,6 @@ CONFIG_WATCHDOG=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -611,7 +462,6 @@ CONFIG_WATCHDOG=y
#
# Digital Video Broadcasting Devices
#
-# CONFIG_DVB is not set
#
# Graphics support
@@ -635,6 +485,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -651,12 +502,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -669,13 +538,12 @@ CONFIG_EXT2_FS=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_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_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
@@ -698,10 +566,9 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -722,29 +589,6 @@ CONFIG_RELAYFS_FS=m
# CONFIG_UFS_FS is not set
#
-# Network File Systems
-#
-CONFIG_NFS_FS=m
-# CONFIG_NFS_V3 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_LOCKD=m
-CONFIG_EXPORTFS=m
-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_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
@@ -767,44 +611,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
#
# 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_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=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_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -814,8 +634,6 @@ CONFIG_CRYPTO_CRC32C=m
# Library routines
#
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index f2d43be69007..7067f608b22c 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:05 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:02 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_MIPS_EV64120=y
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_EVB_PCI1 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,7 +118,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -138,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +179,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_KMOD is not set
@@ -191,6 +187,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +208,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -238,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -258,12 +256,15 @@ CONFIG_IP_PNP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -275,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -284,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -309,6 +310,9 @@ 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
@@ -352,7 +356,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -550,6 +554,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -559,6 +564,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -617,10 +623,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -651,6 +653,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -668,13 +671,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -719,7 +740,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -783,6 +803,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
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::"
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index ac5841c4b698..00b56ed0e638 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:06 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:03 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_EV96100=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -119,7 +121,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -142,7 +143,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -158,6 +158,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -171,10 +172,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_KMOD is not set
@@ -195,6 +191,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -240,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -260,12 +259,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -277,6 +279,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -286,11 +293,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -311,6 +313,9 @@ 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
@@ -349,7 +354,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -567,10 +572,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -601,6 +602,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -617,12 +619,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -667,7 +687,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -731,6 +750,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 42d5cd7927cb..607e2985ffe3 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:54 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SGI_IP22=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
@@ -121,7 +123,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_IP22_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -143,7 +144,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -188,7 +185,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -197,6 +193,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -242,6 +240,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -264,6 +263,7 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -305,9 +305,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -330,11 +333,14 @@ 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_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_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -357,20 +363,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=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_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -388,6 +393,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -408,12 +414,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -435,6 +439,11 @@ CONFIG_IP_SCTP=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -444,11 +453,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -508,6 +512,9 @@ 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
@@ -546,7 +553,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -812,10 +819,6 @@ CONFIG_MAX_RAW_DEVS=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -857,6 +860,7 @@ CONFIG_LOGO_SGI_CLUT224=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -873,12 +877,30 @@ CONFIG_LOGO_SGI_CLUT224=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -944,7 +966,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -963,7 +984,6 @@ CONFIG_EFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1078,6 +1098,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 8c40590737e1..f724b4b2ecf2 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc4
-# Tue Feb 21 13:44:31 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:04 2006
#
CONFIG_MIPS=y
@@ -70,6 +70,8 @@ CONFIG_NUMA=y
# CONFIG_REPLICATE_KTEXT is not set
# CONFIG_REPLICATE_EXHANDLERS is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_IP27=y
@@ -123,6 +125,7 @@ CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_NODES_SHIFT=6
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
CONFIG_DISCONTIGMEM_MANUAL=y
@@ -162,6 +165,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -175,10 +179,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -190,7 +190,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -199,6 +198,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -219,7 +219,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -237,6 +236,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -274,12 +274,15 @@ CONFIG_IP_PNP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -363,6 +366,9 @@ 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
@@ -407,7 +413,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -473,7 +479,6 @@ CONFIG_SCSI_SAS_ATTRS=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
CONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -491,6 +496,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -654,6 +660,7 @@ CONFIG_SERIO_RAW=m
#
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=y
@@ -727,10 +734,6 @@ CONFIG_SGI_IP27_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -755,6 +758,7 @@ CONFIG_SGI_IP27_RTC=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -772,17 +776,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -840,7 +858,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -922,6 +939,7 @@ CONFIG_SGI_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 7fdcaf51face..8f11d3565b2d 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:09 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:05 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SGI_IP32=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_IP32=y
@@ -142,7 +144,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -159,6 +160,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -172,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -189,6 +187,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -208,7 +207,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -226,6 +224,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -240,6 +239,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -261,12 +261,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -278,6 +281,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -287,11 +295,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -312,6 +315,9 @@ 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
@@ -357,7 +363,7 @@ 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_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -428,7 +434,6 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -615,6 +620,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -624,6 +630,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -682,10 +689,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -716,6 +719,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -733,13 +737,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -784,7 +806,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -861,6 +882,8 @@ CONFIG_SGI_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index c716996d9eca..757adf23853d 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:10 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:05 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_MIPS_ITE8172=y
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_IT8172_REVC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,7 +117,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -137,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +154,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -192,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -237,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -258,12 +257,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -275,6 +277,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -284,11 +291,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -309,6 +311,9 @@ 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
@@ -387,7 +392,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -424,7 +428,7 @@ 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_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -666,10 +670,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -704,7 +704,6 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-# CONFIG_OBSOLETE_OSS_DRIVER is not set
CONFIG_SOUND_IT8172=y
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
@@ -714,6 +713,7 @@ CONFIG_SOUND_IT8172=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -730,12 +730,30 @@ CONFIG_SOUND_IT8172=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -780,7 +798,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -846,6 +863,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index a8376d125e11..021761a8a237 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:06 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_IVR=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -112,7 +114,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -134,7 +135,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +151,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +165,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -179,7 +176,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -188,6 +184,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -207,7 +205,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -235,6 +232,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -256,12 +254,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -273,6 +274,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -282,11 +288,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -307,6 +308,9 @@ 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
@@ -350,7 +354,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -565,6 +569,7 @@ CONFIG_IT8172_SCR1=y
#
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
@@ -574,6 +579,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -631,10 +637,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -665,6 +667,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -682,13 +685,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -733,7 +754,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -797,6 +817,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 316015379dbc..08f6c30b0abc 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:12 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:06 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_MOMENCO_JAGUAR_ATX=y
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_JAGUAR_DMALOW=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -122,7 +124,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
@@ -172,10 +173,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -195,6 +191,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -214,7 +212,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -241,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -260,16 +258,19 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
# CONFIG_NETFILTER is not set
@@ -338,10 +339,9 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# 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
#
@@ -423,6 +423,7 @@ CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
# CONFIG_E100 is not set
@@ -446,6 +447,7 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
@@ -514,6 +516,7 @@ CONFIG_MV643XX_ETH_2=y
#
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
@@ -523,6 +526,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -579,10 +583,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -607,6 +607,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -624,12 +625,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
#
@@ -672,7 +690,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
#
# Miscellaneous filesystems
@@ -718,6 +735,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 53fbef1ac25d..38b1e026e10d 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:13 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:07 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_TOSHIBA_JMR3927=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -111,7 +113,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +134,6 @@ CONFIG_RTC_DS1742=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -149,6 +149,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -162,10 +163,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -180,6 +177,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -199,7 +198,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -227,6 +225,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -248,12 +247,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -265,6 +267,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -274,11 +281,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -299,6 +301,9 @@ 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
@@ -343,7 +348,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -551,7 +556,12 @@ CONFIG_SERIAL_NONSTANDARD=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_TXX9=y
CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_TXX9_CONSOLE is not set
+# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+# CONFIG_SERIAL_JSM is not set
# CONFIG_UNIX98_PTYS is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -610,10 +620,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -631,6 +637,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -642,7 +649,6 @@ CONFIG_FB=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -679,6 +685,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -696,13 +703,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -745,7 +770,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -809,6 +833,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index ef0fa9fc79d6..4d25990a0a05 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:14 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:07 2006
#
CONFIG_MIPS=y
@@ -68,6 +68,8 @@ CONFIG_PICVUE_PROC=y
CONFIG_DS1603=y
CONFIG_LASAT_SYSCTL=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -119,7 +121,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_R5000_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -141,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -157,6 +157,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -170,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -195,6 +191,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -214,7 +212,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -242,6 +239,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -259,12 +257,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -276,6 +277,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -285,11 +291,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -310,6 +311,9 @@ 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
@@ -366,7 +370,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -389,7 +392,6 @@ CONFIG_MTD_LASAT=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -430,7 +432,7 @@ CONFIG_MTD_LASAT=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -672,6 +674,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -681,6 +684,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -739,10 +743,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -773,6 +773,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -790,13 +791,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -847,7 +866,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -914,6 +932,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 367d279efdd9..977f52be51dc 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:15 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:08 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_MALTA=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_DMA_NONCOHERENT=y
@@ -128,16 +130,21 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_MT_SMP is not set
CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_FPAFF=y
CONFIG_MIPS_VPE_LOADER_TOM=y
CONFIG_MIPS_VPE_APSP_API=y
+CONFIG_MIPS_APSP_KSPD=y
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_MIPSR2_IRQ_VI is not set
+# CONFIG_CPU_MIPSR2_IRQ_EI is not set
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
@@ -155,7 +162,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -171,6 +177,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -184,10 +191,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -199,7 +202,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -208,6 +210,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -227,7 +231,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -255,6 +258,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -287,6 +291,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -328,9 +333,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -354,11 +362,14 @@ 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_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_PHYSDEV is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -382,20 +393,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=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_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -413,6 +423,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -433,12 +444,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -484,6 +493,11 @@ CONFIG_IP_SCTP=m
# 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=m
CONFIG_VLAN_8021Q=m
@@ -498,11 +512,6 @@ CONFIG_IPDDP_ENCAP=y
CONFIG_IPDDP_DECAP=y
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -562,6 +571,9 @@ 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
@@ -734,7 +746,6 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -753,6 +764,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -956,6 +968,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -965,6 +978,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -1022,10 +1036,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -1056,6 +1066,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -1073,13 +1084,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1154,7 +1183,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1174,7 +1202,6 @@ CONFIG_VXFS_FS=m
# CONFIG_QNX4FS_FS is not set
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1266,6 +1293,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index fe78961762b8..00560e0143f1 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:16 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:09 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_SIM=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,16 +116,19 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_MT_SMP is not set
CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_FPAFF=y
CONFIG_MIPS_VPE_LOADER_TOM=y
CONFIG_MIPS_VPE_APSP_API=y
+CONFIG_MIPS_APSP_KSPD=y
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED 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
@@ -141,7 +146,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -157,6 +161,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -171,10 +176,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +187,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -195,6 +195,7 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -238,6 +239,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -268,12 +270,15 @@ CONFIG_SYN_COOKIES=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -290,6 +295,11 @@ CONFIG_IP_SCTP=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -299,11 +309,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -397,7 +402,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -532,7 +537,7 @@ CONFIG_SERIO_SERPORT=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -596,10 +601,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -624,6 +625,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -640,12 +642,30 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -690,8 +710,6 @@ CONFIG_PROC_FS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
-# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index e4620e7f0a5e..286a018375b2 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:17 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:09 2006
#
CONFIG_MIPS=y
@@ -72,6 +72,8 @@ CONFIG_VICTOR_MPC30X=y
CONFIG_PCI_VR41XX=y
CONFIG_VRC4173=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -90,7 +92,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# 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_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -103,18 +105,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+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 is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -179,7 +180,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -187,6 +187,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -206,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -225,6 +227,7 @@ CONFIG_PCMCIA_IOCTL=y
# CONFIG_YENTA is not set
# CONFIG_PD6729 is not set
# CONFIG_I82092 is not set
+# CONFIG_PCMCIA_VRC4173 is not set
#
# PCI Hotplug Support
@@ -236,6 +239,7 @@ CONFIG_PCMCIA_IOCTL=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -245,6 +249,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -264,12 +269,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -281,6 +289,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -290,11 +303,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -316,6 +324,9 @@ CONFIG_IEEE80211=m
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
#
# Device Drivers
@@ -360,7 +371,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
@@ -475,6 +486,7 @@ CONFIG_MII=m
# Wireless LAN (non-hamradio)
#
CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Obsolete Wireless cards support (pre-802.11)
@@ -513,6 +525,7 @@ CONFIG_PCMCIA_HERMES=m
#
# CONFIG_PRISM54 is not set
# CONFIG_HOSTAP is not set
+# CONFIG_BCM43XX is not set
CONFIG_NET_WIRELESS=y
#
@@ -604,6 +617,8 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_VR41XX is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -634,6 +649,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_SYNCLINK_CS is not set
# CONFIG_CARDMAN_4000 is not set
# CONFIG_CARDMAN_4040 is not set
+# CONFIG_GPIO_VR41XX is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -669,10 +685,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -681,6 +693,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -703,6 +716,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -756,9 +770,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -772,15 +784,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -832,13 +835,31 @@ CONFIG_USB_PEGASUS=m
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -883,7 +904,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -946,6 +966,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 925d8adef88d..1ce4310fd92a 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:18 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:10 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT_3=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -120,7 +122,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -161,6 +161,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -174,10 +175,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -189,7 +186,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -198,6 +194,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -217,7 +215,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -245,6 +242,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -266,6 +264,7 @@ CONFIG_IP_PNP_BOOTP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -278,9 +277,12 @@ CONFIG_TCP_CONG_BIC=y
# 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_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
@@ -299,10 +301,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -332,6 +337,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -341,11 +351,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -367,6 +372,9 @@ 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
@@ -411,7 +419,7 @@ 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_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
@@ -475,7 +483,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -690,6 +697,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -699,6 +707,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -756,10 +765,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -777,6 +782,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -788,7 +794,6 @@ CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -832,6 +837,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -849,13 +855,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -914,7 +938,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1025,6 +1048,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="ip=any root=nfs"
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index ee1cf9b9eb9a..8a6aa5012f89 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:19 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:10 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT_C=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -139,7 +141,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -155,6 +156,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -168,10 +170,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -185,6 +183,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -204,7 +203,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -222,6 +220,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -236,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -256,12 +256,15 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -273,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -282,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -307,6 +310,9 @@ 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
@@ -351,7 +357,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -542,6 +548,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -551,6 +558,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -609,10 +617,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -643,6 +647,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -660,13 +665,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -711,7 +734,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -778,6 +800,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index d80ff278f2af..f9ee35eeb762 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:20 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:11 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -121,7 +123,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -191,6 +188,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -236,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -256,12 +256,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -273,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -282,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -307,6 +310,9 @@ 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
@@ -346,7 +352,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -563,10 +569,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -597,6 +599,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -613,12 +616,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -663,7 +684,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -730,6 +750,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index c0f508d180c4..b48bdee2411f 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:21 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:11 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT_G=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -142,7 +144,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -158,6 +159,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -171,10 +173,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -188,6 +186,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -207,7 +206,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -225,6 +223,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -239,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -259,12 +259,15 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -276,6 +279,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -285,11 +293,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -310,6 +313,9 @@ 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
@@ -354,7 +360,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -545,6 +551,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -554,6 +561,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -612,10 +620,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -646,6 +650,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -663,13 +668,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -714,7 +737,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -781,6 +803,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 194b3c772bb7..01aac40634b4 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:22 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:12 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_PB1100=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,11 +118,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -138,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,7 +181,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -192,6 +189,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -247,6 +246,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -269,7 +269,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -280,6 +281,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -296,10 +299,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -323,6 +329,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -332,11 +343,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -358,6 +364,9 @@ 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
@@ -414,7 +423,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -436,7 +444,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -473,7 +480,7 @@ 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_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -716,10 +723,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -750,6 +753,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
@@ -767,12 +771,30 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -830,7 +852,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -939,6 +960,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 8985725e6a98..398c3c265b9f 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:24 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:13 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_PB1500=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -137,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -253,6 +251,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -275,7 +274,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -302,10 +304,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -338,11 +348,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@ 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
@@ -420,7 +428,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -485,7 +491,7 @@ 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_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -750,6 +756,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -761,6 +768,7 @@ CONFIG_SERIAL_8250_AU1X00=y
#
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
@@ -826,10 +834,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -854,6 +858,7 @@ CONFIG_SYNCLINK_CS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -871,13 +876,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -935,7 +958,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1044,6 +1066,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index adbf997b540e..ea282a53bb66 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:25 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:13 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_PB1550=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED 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
@@ -137,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -253,6 +251,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -275,7 +274,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -302,10 +304,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -338,11 +348,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@ 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
@@ -420,7 +428,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -485,7 +491,7 @@ 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_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -742,6 +748,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -753,6 +760,7 @@ CONFIG_SERIAL_8250_AU1X00=y
#
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
@@ -818,10 +826,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -846,6 +850,7 @@ CONFIG_SYNCLINK_CS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -863,13 +868,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -927,7 +950,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1036,6 +1058,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index b5db700450ba..4c57e564db0b 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:26 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:14 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_PNX8550_JBS=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED 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
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -190,6 +187,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -209,7 +208,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_MMU=y
@@ -238,6 +236,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -257,12 +256,15 @@ CONFIG_IP_PNP_BOOTP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -274,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -283,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -469,7 +471,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -671,6 +672,7 @@ CONFIG_HW_CONSOLE=y
# Non-8250 serial port support
#
# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -723,6 +725,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -730,10 +733,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -742,6 +741,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -764,6 +764,7 @@ CONFIG_DUMMY_CONSOLE=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
@@ -827,9 +828,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -844,15 +843,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -902,13 +892,31 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -956,7 +964,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1067,6 +1074,7 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index 4187287f0763..3c8f35162fec 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:28 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:14 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_PNX8550_V2PCI=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,12 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_ADVANCED=y
CONFIG_CPU_HAS_LLSC=y
-# CONFIG_CPU_HAS_WB is not set
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
@@ -137,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +154,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +178,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -190,6 +186,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -209,7 +207,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_MMU=y
#
@@ -237,6 +234,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -256,6 +254,7 @@ CONFIG_IP_PNP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -268,9 +267,12 @@ CONFIG_TCP_CONG_BIC=y
# 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_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
@@ -287,10 +289,12 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -320,6 +324,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -329,11 +338,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -521,7 +525,6 @@ CONFIG_AIC7XXX_DEBUG_MASK=0
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -757,6 +760,7 @@ CONFIG_SERIAL_NONSTANDARD=y
# Non-8250 serial port support
#
# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -816,7 +820,6 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -835,9 +838,7 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -867,6 +868,7 @@ CONFIG_HWMON=y
# 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
@@ -901,10 +903,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -913,6 +911,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -922,6 +921,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -933,7 +933,6 @@ CONFIG_FB=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -970,6 +969,7 @@ CONFIG_DUMMY_CONSOLE=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
@@ -1030,9 +1030,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -1047,15 +1045,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1106,13 +1095,31 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1171,7 +1178,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1280,6 +1286,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 31f5afabafa8..4bcc01dea041 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Sun Feb 12 19:18:55 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:15 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_QEMU=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_GENERIC_ISA_DMA=y
@@ -115,16 +117,17 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED 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_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_SMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -147,6 +150,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
@@ -159,10 +163,6 @@ CONFIG_ELF_CORE=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SHMEM is not set
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
@@ -177,6 +177,8 @@ CONFIG_BASE_SMALL=1
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -196,6 +198,7 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
CONFIG_ISA=y
CONFIG_MMU=y
+CONFIG_I8253=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -241,12 +244,15 @@ CONFIG_IP_PNP_BOOTP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -308,7 +314,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -530,10 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -552,6 +554,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
@@ -565,6 +568,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -581,15 +585,28 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
#
@@ -632,7 +649,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
#
# Miscellaneous filesystems
@@ -680,6 +696,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index b126f763cf51..3d441932e43a 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.16-rc1
-# Fri Jan 27 15:40:30 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:16 2006
#
CONFIG_MIPS=y
@@ -71,6 +71,8 @@ CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61=y
# CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND is not set
# CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -121,10 +123,9 @@ 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_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_ADVANCED=y
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_WB=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -145,7 +146,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -162,6 +162,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -175,10 +176,6 @@ CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -190,7 +187,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -199,6 +195,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -218,7 +216,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_ISA=y
CONFIG_MMU=y
@@ -247,6 +244,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -267,6 +265,7 @@ CONFIG_IP_PNP_BOOTP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -279,9 +278,12 @@ CONFIG_TCP_CONG_BIC=y
# 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_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
@@ -300,10 +302,12 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+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_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -333,6 +337,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
@@ -342,11 +351,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -369,6 +373,9 @@ CONFIG_IEEE80211=m
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
#
# Device Drivers
@@ -425,7 +432,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -447,7 +453,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -702,6 +707,7 @@ CONFIG_NET_PCI=y
# Wireless LAN (non-hamradio)
#
CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Obsolete Wireless cards support (pre-802.11)
@@ -715,6 +721,8 @@ CONFIG_NET_RADIO=y
#
# CONFIG_IPW2100 is not set
CONFIG_IPW2200=m
+# CONFIG_IPW2200_MONITOR is not set
+# CONFIG_IPW_QOS is not set
# CONFIG_IPW2200_DEBUG is not set
# CONFIG_HERMES is not set
# CONFIG_ATMEL is not set
@@ -724,6 +732,7 @@ CONFIG_IPW2200=m
#
# CONFIG_PRISM54 is not set
# CONFIG_HOSTAP is not set
+# CONFIG_BCM43XX is not set
CONFIG_NET_WIRELESS=y
#
@@ -821,7 +830,12 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_TXX9=y
CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_TXX9_CONSOLE is not set
+# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -874,6 +888,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -881,10 +896,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -893,6 +904,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -902,6 +914,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -913,7 +926,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
CONFIG_FB_ATY=y
@@ -934,6 +946,7 @@ CONFIG_FB_ATY_CT=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE is not set
@@ -954,6 +967,7 @@ CONFIG_DUMMY_CONSOLE=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
@@ -1003,9 +1017,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -1019,15 +1031,6 @@ CONFIG_USB_YEALINK=m
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1078,13 +1081,31 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1148,7 +1169,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1266,6 +1286,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 463ed3dbf6ae..edfb9679a25a 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:31 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:16 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SNI_RM200_PCI=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
@@ -122,7 +124,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -145,7 +146,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -163,6 +163,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -176,10 +177,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -191,7 +188,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -200,6 +196,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -220,10 +218,10 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_HW_HAS_EISA=y
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_ISA=y
# CONFIG_EISA is not set
CONFIG_MMU=y
+CONFIG_I8253=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -250,6 +248,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=m
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -272,6 +271,7 @@ CONFIG_IP_PIMSM_V2=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -284,9 +284,12 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -309,11 +312,14 @@ CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=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_PHYSDEV=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -337,20 +343,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=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_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -368,6 +373,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -388,12 +394,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -439,21 +443,22 @@ CONFIG_BRIDGE_EBT_ULOG=m
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
# CONFIG_ATM is not set
CONFIG_BRIDGE=m
# CONFIG_VLAN_8021Q is not set
CONFIG_DECNET=m
# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
# 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
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -533,6 +538,9 @@ 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
@@ -620,6 +628,7 @@ CONFIG_BLK_DEV_UB=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -700,12 +709,11 @@ CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_IPR 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_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -731,6 +739,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -965,6 +974,7 @@ CONFIG_HW_CONSOLE=y
# Serial drivers
#
CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
@@ -977,6 +987,7 @@ CONFIG_SERIAL_8250_RSA=y
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=m
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -1027,12 +1038,19 @@ CONFIG_RTC=m
# Dallas's 1-wire bus
#
CONFIG_W1=m
-CONFIG_W1_MATROX=m
-CONFIG_W1_DS9490=m
-# CONFIG_W1_DS9490_BRIDGE is not set
-CONFIG_W1_THERM=m
-CONFIG_W1_SMEM=m
-# CONFIG_W1_DS2433 is not set
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+# CONFIG_W1_MASTER_DS9490 is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
#
# Hardware Monitoring support
@@ -1045,10 +1063,6 @@ CONFIG_W1_SMEM=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -1057,6 +1071,7 @@ CONFIG_W1_SMEM=m
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+CONFIG_USB_DABUSB=m
#
# Graphics support
@@ -1067,6 +1082,7 @@ CONFIG_W1_SMEM=m
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
@@ -1080,6 +1096,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -1151,9 +1168,7 @@ CONFIG_USB_WACOM=m
# CONFIG_USB_ACECAD is not set
CONFIG_USB_KBTAB=m
CONFIG_USB_POWERMATE=m
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-CONFIG_USB_EGALAX=m
+# CONFIG_USB_TOUCHSCREEN is not set
CONFIG_USB_YEALINK=m
CONFIG_USB_XPAD=m
# CONFIG_USB_ATI_REMOTE is not set
@@ -1168,15 +1183,6 @@ CONFIG_USB_MDC800=m
CONFIG_USB_MICROTEK=m
#
-# USB Multimedia devices
-#
-CONFIG_USB_DABUSB=m
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
CONFIG_USB_CATC=m
@@ -1213,6 +1219,7 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
CONFIG_USB_SERIAL_VISOR=m
CONFIG_USB_SERIAL_IPAQ=m
CONFIG_USB_SERIAL_IR=m
@@ -1237,6 +1244,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_HP4X=m
CONFIG_USB_SERIAL_SAFE=m
@@ -1281,13 +1289,31 @@ CONFIG_USB_TEST=m
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1358,7 +1384,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1379,7 +1404,6 @@ CONFIG_HPFS_FS=m
CONFIG_QNX4FS_FS=m
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1500,6 +1524,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index da68c3f72050..e388a3dae0a9 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:32 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:17 2006
#
CONFIG_MIPS=y
@@ -81,6 +81,8 @@ CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_CPU_BIG_ENDIAN=y
@@ -158,7 +160,6 @@ CONFIG_PREEMPT_BKL=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -175,6 +176,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_CPUSETS=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -188,10 +190,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -203,7 +201,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -212,6 +209,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -231,7 +229,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -249,6 +246,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -263,6 +261,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -284,12 +283,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -301,6 +303,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -310,11 +317,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -335,6 +337,9 @@ 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
@@ -589,6 +594,7 @@ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -647,10 +653,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -675,6 +677,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -692,13 +695,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -746,7 +767,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -812,6 +832,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
# CONFIG_SB1XXX_CORELIS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 9a936d7b7c0c..6b8a6a416a25 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:33 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:17 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_SEAD=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -118,11 +120,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED 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
@@ -140,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +155,7 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -185,6 +183,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -296,12 +296,6 @@ CONFIG_RAID_ATTRS=y
#
#
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
# ISDN subsystem
#
@@ -397,10 +391,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -424,6 +414,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -440,12 +431,30 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -489,7 +498,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -543,6 +551,8 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAGIC_SYSRQ 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_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index c2dee0d1c72c..dba0bdcdcf29 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:34 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:41 2006
#
CONFIG_MIPS=y
@@ -68,12 +68,14 @@ CONFIG_MACH_VR41XX=y
# CONFIG_NEC_CMBVR4133 is not set
CONFIG_TANBAC_TB022X=y
CONFIG_TANBAC_TB0226=y
-CONFIG_TANBAC_TB0287=y
+# CONFIG_TANBAC_TB0287 is not set
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_PCI_VR41XX=y
# CONFIG_VRC4173 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -92,7 +94,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# 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_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -105,18 +107,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+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 is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +157,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +182,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -189,6 +189,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -208,7 +211,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_MMU=y
#
@@ -226,6 +228,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -235,11 +238,10 @@ 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_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -263,12 +265,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -280,6 +285,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -289,11 +299,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -310,10 +315,7 @@ CONFIG_TCP_CONG_BIC=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 is not set
#
# Device Drivers
@@ -358,11 +360,12 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -397,14 +400,14 @@ CONFIG_SCSI_MULTI_LUN=y
# SCSI Transport Attributes
#
# CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS 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
@@ -424,7 +427,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -507,8 +509,8 @@ CONFIG_NET_PCI=y
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 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
@@ -625,6 +627,11 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -685,10 +692,6 @@ CONFIG_GPIO_VR41XX=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -697,6 +700,7 @@ CONFIG_GPIO_VR41XX=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -719,6 +723,7 @@ CONFIG_DUMMY_CONSOLE=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
@@ -756,7 +761,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# may also be needed; see USB_STORAGE Help for more information
#
-CONFIG_USB_STORAGE=m
+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
@@ -783,9 +788,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -800,15 +803,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -816,7 +810,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
+# CONFIG_USB_MON is not set
#
# USB port drivers
@@ -860,13 +854,48 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
#
# File systems
@@ -911,7 +940,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -952,9 +980,7 @@ 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=y
-CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -970,46 +996,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# 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=m
-# 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=m
-# 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
#
# Profiling support
@@ -1023,44 +1010,20 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=32M console=ttyVR0,115200"
#
# 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_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=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_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -1069,9 +1032,8 @@ CONFIG_CRYPTO_CRC32C=m
#
# Library routines
#
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index be99261d7997..5a924c1a5803 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:35 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:59 2006
#
CONFIG_MIPS=y
@@ -68,12 +68,14 @@ CONFIG_MACH_VR41XX=y
# CONFIG_NEC_CMBVR4133 is not set
CONFIG_TANBAC_TB022X=y
# CONFIG_TANBAC_TB0226 is not set
-CONFIG_TANBAC_TB0287=y
+# CONFIG_TANBAC_TB0287 is not set
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_PCI_VR41XX=y
# CONFIG_VRC4173 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -92,7 +94,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# 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_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -105,18 +107,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+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 is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +157,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +182,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -189,6 +189,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -208,7 +211,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_MMU=y
#
@@ -226,6 +228,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -235,11 +238,10 @@ 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_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -264,12 +266,15 @@ CONFIG_SYN_COOKIES=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -281,6 +286,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -290,11 +300,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -311,10 +316,7 @@ CONFIG_TCP_CONG_BIC=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 is not set
#
# Device Drivers
@@ -325,12 +327,12 @@ CONFIG_IEEE80211_CRYPT_CCMP=m
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+# CONFIG_FW_LOADER is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
@@ -363,10 +365,8 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# 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
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -443,30 +443,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=y
-# 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=y
-# 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_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_PCI is not set
#
# Ethernet (1000 Mbit)
@@ -483,7 +460,6 @@ 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
@@ -510,19 +486,8 @@ CONFIG_R8169=y
# 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_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
+# 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
@@ -583,6 +548,11 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -607,6 +577,7 @@ CONFIG_TANBAC_TB0219=y
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
#
@@ -642,10 +613,6 @@ CONFIG_TANBAC_TB0219=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -654,6 +621,7 @@ CONFIG_TANBAC_TB0219=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -676,6 +644,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -731,9 +700,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -747,15 +714,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -807,13 +765,48 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
#
# File systems
@@ -821,32 +814,16 @@ CONFIG_USB_MON=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=y
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
+# CONFIG_EXT3_FS is not set
# CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-# CONFIG_JFS_POSIX_ACL is not set
-# CONFIG_JFS_SECURITY is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
+# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-CONFIG_XFS_QUOTA=y
-# CONFIG_XFS_SECURITY is not set
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=m
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
-CONFIG_QUOTACTL=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
@@ -855,20 +832,14 @@ CONFIG_FUSE_FS=m
#
# CD-ROM/DVD Filesystems
#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
+# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -880,7 +851,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -921,9 +891,7 @@ 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=y
-CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -939,46 +907,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# 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=m
-# 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=m
-# 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
#
# Profiling support
@@ -992,44 +921,20 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
#
# 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_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=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_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -1038,9 +943,8 @@ CONFIG_CRYPTO_CRC32C=m
#
# Library routines
#
-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_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
new file mode 100644
index 000000000000..9f215ea350dc
--- /dev/null
+++ b/arch/mips/configs/tb0287_defconfig
@@ -0,0 +1,1132 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:09:17 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# 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_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 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_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_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU 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_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_CMBVR4133 is not set
+CONFIG_TANBAC_TB022X=y
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0287=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=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=y
+# 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_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_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 is not set
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# 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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+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_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_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
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=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 is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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
+# 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_NET_DIVERT 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 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# 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=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# 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=4096
+# 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
+#
+CONFIG_IDE=y
+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_BLK_DEV_IDESCSI 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_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_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX 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
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA 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_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_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
+
+#
+# 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_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
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# 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
+
+#
+# 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_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=y
+# CONFIG_R8169_NAPI 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
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# 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_NET_FC 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
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_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_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_TANBAC_TB0219 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK 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
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# 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 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=y
+# 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 is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND 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=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# 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=m
+# 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_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV 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 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem 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
+
+#
+# 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 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 is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# 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_CRAMFS=m
+# 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_ROOT_NFS=y
+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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 7132e296d40a..ac7765eb8da7 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:36 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:09:33 2006
#
CONFIG_MIPS=y
@@ -70,6 +70,8 @@ CONFIG_IBM_WORKPAD=y
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -88,7 +90,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# 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_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -101,18 +103,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+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 is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -149,6 +153,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -162,10 +167,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -177,7 +178,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -185,6 +185,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -220,6 +223,7 @@ CONFIG_PCMCIA_IOCTL=y
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
CONFIG_PCMCIA_PROBE=y
+CONFIG_PCMCIA_VRC4171=y
#
# PCI Hotplug Support
@@ -230,6 +234,7 @@ CONFIG_PCMCIA_PROBE=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -239,6 +244,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -258,12 +264,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -275,6 +284,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -284,11 +298,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -305,10 +314,8 @@ CONFIG_TCP_CONG_BIC=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 is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -347,10 +354,12 @@ CONFIG_CONNECTOR=m
# 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_RAM is not set
+CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -468,7 +477,38 @@ CONFIG_MII=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
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
#
# PCMCIA network device support
@@ -512,10 +552,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
@@ -533,11 +570,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -556,6 +589,10 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -568,20 +605,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-
-#
-# ISA-based Watchdog Cards
-#
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_WDT is not set
+# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
@@ -597,6 +621,7 @@ CONFIG_WATCHDOG=y
# CONFIG_SYNCLINK_CS is not set
# CONFIG_CARDMAN_4000 is not set
# CONFIG_CARDMAN_4040 is not set
+# CONFIG_GPIO_VR41XX is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -632,10 +657,6 @@ CONFIG_WATCHDOG=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -667,6 +688,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -683,12 +705,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -710,7 +750,7 @@ CONFIG_FS_POSIX_ACL=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
@@ -733,10 +773,9 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -802,44 +841,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
#
# 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_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=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_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -849,8 +864,6 @@ CONFIG_CRYPTO_CRC32C=m
# Library routines
#
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 67457850941d..b52d709de962 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:37 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:20 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_PMC_YOSEMITE=y
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_HYPERTRANSPORT is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_CPU_BIG_ENDIAN=y
@@ -116,7 +118,6 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -140,7 +141,6 @@ CONFIG_PREEMPT_BKL=y
# Code maturity level options
#
# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -157,6 +157,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
@@ -170,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -184,7 +181,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -194,6 +190,8 @@ CONFIG_STOP_MACHINE=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -213,7 +211,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
CONFIG_MMU=y
@@ -241,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=m
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -261,16 +259,19 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
# CONFIG_NETFILTER is not set
@@ -340,10 +341,9 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# 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
#
@@ -433,6 +433,7 @@ CONFIG_MII=y
# CONFIG_HAMACHI is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -497,6 +498,7 @@ CONFIG_TITAN_GE=y
#
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
@@ -506,6 +508,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -563,10 +566,6 @@ CONFIG_GEN_RTC_X=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -591,6 +590,7 @@ CONFIG_GEN_RTC_X=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -608,12 +608,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
#
@@ -656,7 +673,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
#
# Miscellaneous filesystems
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
index 488206b8d94e..304c02107b46 100644
--- a/arch/mips/ddb5xxx/ddb5074/Makefile
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -3,6 +3,6 @@
# under Linux.
#
-obj-y += setup.o irq.o int-handler.o nile4_pic.o
+obj-y += setup.o irq.o nile4_pic.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
deleted file mode 100644
index a78644150b37..000000000000
--- a/arch/mips/ddb5xxx/ddb5074/int-handler.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
- *
- * Based on arch/mips/sgi/kernel/indyIRQ.S
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- * Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Local IRQ level zero
- * 3 Local IRQ level one
- * 4 8254 Timer zero
- * 5 8254 Timer one
- * 6 Bus Error
- * 7 R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Local IRQ zero
- * Local IRQ one
- * Bus Error
- * 8254 Timer zero
- * Lowest ---- 8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(ddbIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 s0, CP0_CAUSE # get irq mask
-
-#if 1
- mfc0 t2,CP0_STATUS # get enabled interrupts
- and s0,t2 # isolate allowed ones
-#endif
- /* First we check for r4k counter/timer IRQ. */
- andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
-
- /* Wheee, local level zero interrupt. */
- jal ddb_local0_irqdispatch
- move a0, sp # delay slot
-
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
-
- /* Wheee, local level one interrupt. */
- move a0, sp
- jal ddb_local1_irqdispatch
- nop
-
- j ret_from_irq
- nop
-
-1:
- beq a0, zero, 1f
- nop
-
- /* Wheee, an asynchronous bus error... */
- move a0, sp
- jal ddb_buserror_irq
- nop
-
- j ret_from_irq
- nop
-
-1:
- /* Here by mistake? This is possible, what can happen
- * is that by the time we take the exception the IRQ
- * pin goes low, so just leave if this is the case.
- */
- andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
- beq a0, zero, 1f
-
- /* Must be one of the 8254 timers... */
- move a0, sp
- jal ddb_8254timer_irq
- nop
-1:
- j ret_from_irq
- nop
- END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
index 45088a1be414..60c087b7738c 100644
--- a/arch/mips/ddb5xxx/ddb5074/irq.c
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -21,8 +21,6 @@
#include <asm/ddb5xxx/ddb5074.h>
-extern asmlinkage void ddbIRQ(void);
-
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
@@ -90,7 +88,7 @@ static void m1543_irq_setup(void)
}
-void ddb_local0_irqdispatch(struct pt_regs *regs)
+static void ddb_local0_irqdispatch(struct pt_regs *regs)
{
u32 mask;
int nile4_irq;
@@ -118,29 +116,41 @@ void ddb_local0_irqdispatch(struct pt_regs *regs)
}
}
-void ddb_local1_irqdispatch(void)
+static void ddb_local1_irqdispatch(void)
{
printk("ddb_local1_irqdispatch called\n");
}
-void ddb_buserror_irq(void)
+static void ddb_buserror_irq(void)
{
printk("ddb_buserror_irq called\n");
}
-void ddb_8254timer_irq(void)
+static void ddb_8254timer_irq(void)
{
printk("ddb_8254timer_irq called\n");
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & CAUSEF_IP2)
+ ddb_local0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP3)
+ ddb_local1_irqdispatch();
+ else if (pending & CAUSEF_IP6)
+ ddb_buserror_irq();
+ else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+ ddb_8254timer_irq();
+}
+
void __init arch_init_irq(void)
{
/* setup cascade interrupts */
setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
- set_except_vector(0, ddbIRQ);
-
nile4_irq_setup(NILE4_IRQ_BASE);
m1543_irq_setup();
init_i8259_irqs();
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
index 61eec363cb02..ab0312cb47b4 100644
--- a/arch/mips/ddb5xxx/ddb5476/Makefile
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -3,7 +3,7 @@
# under Linux.
#
-obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-y += setup.o irq.o nile4_pic.o vrc5476_irq.o
obj-$(CONFIG_KGDB) += dbg_io.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
deleted file mode 100644
index 12c292e189ba..000000000000
--- a/arch/mips/ddb5xxx/ddb5476/int-handler.S
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5476
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#include <asm/ddb5xxx/ddb5476.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ddb5476_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cpu_ip7
- andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */
- bnez t1, ll_cpu_ip2
- andi t1, t0, STATUSF_IP3
- bnez t1, ll_cpu_ip3
- andi t1, t0, STATUSF_IP4
- bnez t1, ll_cpu_ip4
- andi t1, t0, STATUSF_IP5
- bnez t1, ll_cpu_ip5
- andi t1, t0, STATUSF_IP6
- bnez t1, ll_cpu_ip6
- andi t1, t0, STATUSF_IP0 /* software int 0 */
- bnez t1, ll_cpu_ip0
- andi t1, t0, STATUSF_IP1 /* software int 1 */
- bnez t1, ll_cpu_ip1
- nop
-
- .set reorder
-
- /* wrong alarm or masked ... */
- // j spurious_interrupt
- move a0, sp
- jal vrc5476_irq_dispatch
- j ret_from_irq
- nop
-
- .align 5
-
-ll_cpu_ip0:
- li a0, CPU_IRQ_BASE + 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip1:
- li a0, CPU_IRQ_BASE + 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip2: /* jump to second-level dispatching */
- move a0, sp
- jal vrc5476_irq_dispatch
- j ret_from_irq
-
-ll_cpu_ip3:
- li a0, CPU_IRQ_BASE + 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip4:
- li a0, CPU_IRQ_BASE + 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip5:
- li a0, CPU_IRQ_BASE + 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip6:
- li a0, CPU_IRQ_BASE + 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip7:
- li a0, CPU_IRQ_BASE + 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
- END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
index 5388b5868c4a..7583a1f30711 100644
--- a/arch/mips/ddb5xxx/ddb5476/irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -110,11 +110,36 @@ static void nile4_irq_setup(void)
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
-extern asmlinkage void ddb5476_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
extern void mips_cpu_irq_init(u32 irq_base);
extern void vrc5476_irq_init(u32 irq_base);
+extern void vrc5476_irq_dispatch(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(CPU_IRQ_BASE + 7, regs);
+ else if (pending & STATUSF_IP2)
+ vrc5476_irq_dispatch(regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(CPU_IRQ_BASE + 3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(CPU_IRQ_BASE + 4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(CPU_IRQ_BASE + 5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(CPU_IRQ_BASE + 6, regs);
+ else if (pending & STATUSF_IP0)
+ do_IRQ(CPU_IRQ_BASE, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(CPU_IRQ_BASE + 1, regs);
+
+ vrc5476_irq_dispatch(regs);
+}
+
void __init arch_init_irq(void)
{
/* hardware initialization */
@@ -137,7 +162,4 @@ void __init arch_init_irq(void)
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-
- /* setup the grandpa intr vector */
- set_except_vector(0, ddb5476_handle_int);
}
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
index f66fe5b58636..a3c5e7b18018 100644
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -77,11 +77,9 @@ vrc5476_irq_init(u32 base)
}
-asmlinkage void
+void
vrc5476_irq_dispatch(struct pt_regs *regs)
{
- extern void spurious_interrupt(void);
-
u32 mask;
int nile4_irq;
@@ -107,5 +105,5 @@ vrc5476_irq_dispatch(struct pt_regs *regs)
return;
}
}
- spurious_interrupt();
+ spurious_interrupt(regs);
}
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index b79b43c9f93b..ea68815ad17a 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,7 @@
# Makefile for NEC DDB-Vrc5477 board
#
-obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+obj-y += 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/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
deleted file mode 100644
index a2502a14400e..000000000000
--- a/arch/mips/ddb5xxx/ddb5477/int-handler.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5477
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/ddb5xxx/ddb5477.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ddb5477_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
- andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
- bnez t1, ll_vrc5477_irq
- andi t1, t0, STATUSF_IP0 /* software int 0 */
- bnez t1, ll_cpu_ip0
- andi t1, t0, STATUSF_IP1 /* software int 1 */
- bnez t1, ll_cpu_ip1
- nop
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ddb5477_handle_int)
-
- .align 5
-
-ll_vrc5477_irq:
- move a0, sp
- jal vrc5477_irq_dispatch
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, CPU_IRQ_BASE + 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-
-ll_cpu_ip0:
- li a0, CPU_IRQ_BASE + 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip1:
- li a0, CPU_IRQ_BASE + 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 9ffe1a9142ca..de433cf9fb50 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -75,7 +75,6 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
extern void vrc5477_irq_init(u32 base);
extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
@@ -135,9 +134,6 @@ void __init arch_init_irq(void)
/* setup cascade interrupts */
setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
-
- /* hook up the first-level interrupt handler */
- set_except_vector(0, ddb5477_handle_int);
}
u8 i8259_interrupt_ack(void)
@@ -159,7 +155,7 @@ u8 i8259_interrupt_ack(void)
* the first level int-handler will jump here if it is a vrc5477 irq
*/
#define NUM_5477_IRQS 32
-asmlinkage void
+static void
vrc5477_irq_dispatch(struct pt_regs *regs)
{
u32 intStatus;
@@ -197,3 +193,21 @@ vrc5477_irq_dispatch(struct pt_regs *regs)
}
}
}
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(CPU_IRQ_BASE + 7, regs);
+ else if (pending & VR5477INTS)
+ vrc5477_irq_dispatch(regs);
+ else if (pending & STATUSF_IP0)
+ do_IRQ(CPU_IRQ_BASE, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(CPU_IRQ_BASE + 1, regs);
+ else
+ spurious_interrupt(regs);
+}
diff --git a/arch/mips/dec/boot/decstation.c b/arch/mips/dec/boot/decstation.c
index 56fd4277555e..4db8bacaf22d 100644
--- a/arch/mips/dec/boot/decstation.c
+++ b/arch/mips/dec/boot/decstation.c
@@ -1,6 +1,7 @@
/*
* arch/mips/dec/decstation.c
*/
+#include <asm/sections.h>
#define RELOC
#define INITRD
@@ -24,7 +25,7 @@
#define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-extern int _ftext, _end; /* begin and end of kernel image */
+extern int _ftext; /* begin and end of kernel image */
extern void kernel_entry(int, char **, unsigned long, int *);
void * memcpy(void * dest, const void *src, unsigned int count)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 41fa372007bf..e8ec93e33fe6 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -36,7 +36,7 @@
.text
.set noreorder
/*
- * decstation_handle_int: Interrupt handler for DECstations
+ * plat_irq_dispatch: Interrupt handler for DECstations
*
* We follow the model in the Indy interrupt code by David Miller, where he
* says: a lot of complication here is taken away because:
@@ -125,11 +125,7 @@
* just take another exception, big deal.
*/
.align 5
- NESTED(decstation_handle_int, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI # TEST: interrupts should be off
- .set at
+ NESTED(plat_irq_dispatch, PT_SIZE, ra)
.set noreorder
/*
@@ -282,9 +278,11 @@ fpu:
#endif
spurious:
- j spurious_interrupt
+ jal spurious_interrupt
nop
- END(decstation_handle_int)
+ j ret_from_irq
+ nop
+ END(plat_irq_dispatch)
/*
* Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 7c1ca8f6330e..ad5d436d80c1 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -48,8 +48,6 @@ extern void dec_machine_halt(void);
extern void dec_machine_power_off(void);
extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
-extern asmlinkage void decstation_handle_int(void);
-
unsigned long dec_kn_slot_base, dec_kn_slot_size;
EXPORT_SYMBOL(dec_kn_slot_base);
@@ -744,7 +742,6 @@ void __init arch_init_irq(void)
panic("Don't know how to set this up!");
break;
}
- set_except_vector(0, decstation_handle_int);
/* Free the FPU interrupt if the exception is present. */
if (!cpu_has_nofpuex) {
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 42d5cd7927cb..607e2985ffe3 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:54 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SGI_IP22=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
@@ -121,7 +123,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_IP22_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -143,7 +144,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -188,7 +185,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -197,6 +193,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -242,6 +240,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -264,6 +263,7 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -305,9 +305,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -330,11 +333,14 @@ 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_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_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -357,20 +363,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=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_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -388,6 +393,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -408,12 +414,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -435,6 +439,11 @@ CONFIG_IP_SCTP=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -444,11 +453,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -508,6 +512,9 @@ 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
@@ -546,7 +553,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -812,10 +819,6 @@ CONFIG_MAX_RAW_DEVS=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -857,6 +860,7 @@ CONFIG_LOGO_SGI_CLUT224=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -873,12 +877,30 @@ CONFIG_LOGO_SGI_CLUT224=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -944,7 +966,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -963,7 +984,6 @@ CONFIG_EFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1078,6 +1098,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
index 58c02f9db69d..cd868ec78cbc 100644
--- a/arch/mips/galileo-boards/ev96100/Makefile
+++ b/arch/mips/galileo-boards/ev96100/Makefile
@@ -6,4 +6,4 @@
# Makefile for the Galileo EV96100 board.
#
-obj-y += init.o irq.o puts.o reset.o time.o int-handler.o setup.o
+obj-y += init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S
deleted file mode 100644
index ff4d10a38859..000000000000
--- a/arch/mips/galileo-boards/ev96100/int-handler.S
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .set noat
- .align 5
-
-NESTED(ev96100IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI # Important: mark KERNEL mode !
-
- mfc0 t0, CP0_CAUSE # get pending interrupts
- mfc0 t1, CP0_STATUS # get enabled interrupts
- and t0, t1 # isolate allowed ones
-
- # FIX ME add R7000 extensions
- andi t0,0xff00 # isolate pending bits
- andi a0, t0, CAUSEF_IP7
- beq a0, zero, 1f
- move a0, sp
- jal mips_timer_interrupt
- j ret_from_irq
-
-1: beqz t0, 3f # spurious interrupt
-
- move a0, t0
- move a1, sp
- jal ev96100_cpu_irq
- j ret_from_irq
-
-3: j spurious_interrupt
- END(ev96100IRQ)
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
index 97bf094da4fe..ee5d6720f23b 100644
--- a/arch/mips/galileo-boards/ev96100/irq.c
+++ b/arch/mips/galileo-boards/ev96100/irq.c
@@ -40,8 +40,6 @@
#include <linux/interrupt.h>
#include <asm/irq_cpu.h>
-extern asmlinkage void ev96100IRQ(void);
-
static inline unsigned int ffz8(unsigned int word)
{
unsigned long k;
@@ -54,13 +52,26 @@ static inline unsigned int ffz8(unsigned int word)
return k;
}
-asmlinkage void ev96100_cpu_irq(unsigned int pendin)
+extern void mips_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
{
do_IRQ(ffz8(pending >> 8), regs);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ mips_timer_interrupt(regs);
+ else if (pending)
+ ev96100_cpu_irq(pending, regs);
+ else
+ spurious_interrupt(regs);
+}
+
void __init arch_init_irq(void)
{
- set_except_vector(0, ev96100IRQ);
mips_cpu_irq_init(0);
}
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
index ebe91c57e173..b2c53a8f8718 100644
--- a/arch/mips/gt64120/ev64120/Makefile
+++ b/arch/mips/gt64120/ev64120/Makefile
@@ -6,6 +6,6 @@
# Makefile for the Galileo EV64120 board.
#
-obj-y += int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+obj-y += irq.o promcon.o reset.o serialGT.o setup.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S
deleted file mode 100644
index 752435faf2de..000000000000
--- a/arch/mips/gt64120/ev64120/int-handler.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * int-handler.S
- *
- * Based on the cobalt handler.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * galileo_handle_int -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- .set reorder
- .set noat
- NESTED(galileo_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0,CP0_CAUSE
- mfc0 t2,CP0_STATUS
-
- and t0,t2
-
- andi t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
- bnez t1,ll_gt64120_irq
- andi t1,t0,STATUSF_IP2 /* int0 hardware line */
- bnez t1,ll_pci_intA
- andi t1,t0,STATUSF_IP5 /* int3 hardware line */
- bnez t1,ll_pci_intD
- andi t1,t0,STATUSF_IP6 /* int4 hardware line */
- bnez t1,ll_serial_irq
- andi t1,t0,STATUSF_IP7 /* compare int */
- bnez t1,ll_compare_irq
- nop
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(galileo_handle_int)
-
-
- .align 5
- .set reorder
-ll_gt64120_irq:
- li a0,4
- move a1,sp
- jal do_IRQ
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_compare_irq:
- li a0,7
- move a1,sp
- jal do_IRQ
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_pci_intA:
- move a0,sp
- jal pci_intA
- nop
- j ret_from_irq
- nop
-
-#if 0
- .align 5
- .set reorder
-ll_pci_intB:
- move a0,sp
- jal pci_intB
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_pci_intC:
- move a0,sp
- jal pci_intC
- nop
- j ret_from_irq
- nop
-#endif
-
- .align 5
- .set reorder
-ll_pci_intD:
- move a0,sp
- jal pci_intD
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_serial_irq:
- li a0,6
- move a1,sp
- jal do_IRQ
- nop
- j ret_from_irq
- nop
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index 3b186159b21a..46c468b26b30 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -46,14 +46,22 @@
#include <asm/system.h>
#include <asm/gt64120.h>
-asmlinkage inline void pci_intA(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
- do_IRQ(GT_INTA, regs);
-}
-
-asmlinkage inline void pci_intD(struct pt_regs *regs)
-{
- do_IRQ(GT_INTD, regs);
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP4) /* int2 hardware line (timer) */
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP2) /* int0 hardware line */
+ do_IRQ(GT_INTA, regs);
+ else if (pending & STATUSF_IP5) /* int3 hardware line */
+ do_IRQ(GT_INTD, regs);
+ else if (pending & STATUSF_IP6) /* int4 hardware line */
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7) /* compare int */
+ do_IRQ(7, regs);
+ else
+ spurious_interrupt(regs);
}
static void disable_ev64120_irq(unsigned int irq_nr)
@@ -109,16 +117,11 @@ static struct hw_interrupt_type ev64120_irq_type = {
void gt64120_irq_setup(void)
{
- extern asmlinkage void galileo_handle_int(void);
-
/*
* Clear all of the interrupts while we change the able around a bit.
*/
clear_c0_status(ST0_IM);
- /* Sets the exception_handler array. */
- set_except_vector(0, galileo_handle_int);
-
local_irq_disable();
/*
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 7b59c6567c79..6f708df8373b 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,7 +2,7 @@
# Makefile for Momentum's Ocelot board.
#
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
deleted file mode 100644
index 808acef248cc..000000000000
--- a/arch/mips/gt64120/momenco_ocelot/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ocelot_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_pri_enet_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_sec_enet_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_uart1_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_cpci_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_galileo_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- /* now look at the extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line */
- bnez t1, ll_pmc1_irq
- andi t1, t0, STATUSF_IP9 /* int7 hardware line */
- bnez t1, ll_pmc2_irq
- andi t1, t0, STATUSF_IP10 /* int8 hardware line */
- bnez t1, ll_cpci_abcd_irq
- andi t1, t0, STATUSF_IP11 /* int9 hardware line */
- bnez t1, ll_uart2_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot_handle_int)
-
- .align 5
-ll_pri_enet_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_sec_enet_irq:
- li a0, 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart1_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_irq:
- li a0, 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_galileo_irq:
- li a0, 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pmc1_irq:
- li a0, 8
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pmc2_irq:
- li a0, 9
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_abcd_irq:
- li a0, 10
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart2_irq:
- li a0, 11
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index 4f108da71b23..885f67f32ea3 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -48,7 +48,38 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP2) /* int0 hardware line */
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3) /* int1 hardware line */
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4) /* int2 hardware line */
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5) /* int3 hardware line */
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6) /* int4 hardware line */
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+ if (pending & STATUSF_IP8) /* int6 hardware line */
+ do_IRQ(8, regs);
+ else if (pending & STATUSF_IP9) /* int7 hardware line */
+ do_IRQ(9, regs);
+ else if (pending & STATUSF_IP10) /* int8 hardware line */
+ do_IRQ(10, regs);
+ else if (pending & STATUSF_IP11) /* int9 hardware line */
+ do_IRQ(11, regs);
+ }
+}
void __init arch_init_irq(void)
{
@@ -59,9 +90,6 @@ void __init arch_init_irq(void)
clear_c0_status(ST0_IM);
local_irq_disable();
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot_handle_int);
-
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
}
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile
index 0e7853f43983..63431538d0ec 100644
--- a/arch/mips/ite-boards/generic/Makefile
+++ b/arch/mips/ite-boards/generic/Makefile
@@ -6,7 +6,7 @@
# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
#
-obj-y += it8172_setup.o irq.o int-handler.o pmon_prom.o \
+obj-y += it8172_setup.o irq.o pmon_prom.o \
time.o lpc.o puts.o reset.o
obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
deleted file mode 100644
index d190d8add9cb..000000000000
--- a/arch/mips/ite-boards/generic/int-handler.S
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .set macro
- .set noat
- .align 5
-
-NESTED(it8172_IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI # Important: mark KERNEL mode !
-
- /* We're working with 'reorder' set at this point. */
- /*
- * Get pending interrupts
- */
-
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
-
- andi t0,0xff00 # isolate pending bits
- beqz t0, 3f # spurious interrupt
-
- andi a0, t0, CAUSEF_IP7
- beq a0, zero, 1f
-
- li a0, 127 # MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
- move a1, sp
- jal ll_timer_interrupt
- j ret_from_irq
- nop
-
-1:
- andi a0, t0, CAUSEF_IP2 # the only int we expect at this time
- beq a0, zero, 3f
- move a0,sp
- jal it8172_hw0_irqdispatch
-
- mfc0 t0,CP0_STATUS # disable interrupts
- ori t0,1
- xori t0,1
- mtc0 t0,CP0_STATUS
- nop
- nop
- nop
-
- la a1, ret_from_irq
- jr a1
- nop
-
-3:
- move a0, sp
- jal mips_spurious_interrupt
- nop
- la a1, ret_from_irq
- jr a1
- nop
-
-END(it8172_IRQ)
-
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
index e67f96129491..77be7216bdd0 100644
--- a/arch/mips/ite-boards/generic/irq.c
+++ b/arch/mips/ite-boards/generic/irq.c
@@ -62,12 +62,8 @@
#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
-void disable_it8172_irq(unsigned int irq_nr);
-void enable_it8172_irq(unsigned int irq_nr);
-
extern void set_debug_traps(void);
extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
-extern asmlinkage void it8172_IRQ(void);
struct it8172_intc_regs volatile *it8172_hw0_icregs =
(struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
@@ -181,8 +177,6 @@ void __init arch_init_irq(void)
int i;
unsigned long flags;
- set_except_vector(0, it8172_IRQ);
-
/* mask all interrupts */
it8172_hw0_icregs->lb_mask = 0xffff;
it8172_hw0_icregs->lpc_mask = 0xffff;
@@ -282,6 +276,18 @@ void it8172_hw0_irqdispatch(struct pt_regs *regs)
do_IRQ(irq, regs);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (!pending)
+ mips_spurious_interrupt(regs);
+ else if (pending & CAUSEF_IP7)
+ ll_timer_interrupt(127, regs);
+ else if (pending & CAUSEF_IP2)
+ it8172_hw0_irqdispatch(regs);
+}
+
void show_pending_irqs(void)
{
fputs("intstatus: ");
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
index b79817bb6cce..dee497a91807 100644
--- a/arch/mips/ite-boards/generic/time.c
+++ b/arch/mips/ite-boards/generic/time.c
@@ -29,6 +29,7 @@
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
#include <asm/time.h>
#include <asm/mipsregs.h>
diff --git a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c
index b774db035b31..05cf9218c432 100644
--- a/arch/mips/ite-boards/ivr/init.c
+++ b/arch/mips/ite-boards/ivr/init.c
@@ -34,13 +34,13 @@
#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <asm/sections.h>
#include <asm/it8172/it8172.h>
#include <asm/it8172/it8172_dbg.h>
int prom_argc;
char **prom_argv, **prom_envp;
-extern char _end;
extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize);
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c
index e8ec8be66a80..ea2a754cafe5 100644
--- a/arch/mips/ite-boards/qed-4n-s01b/init.c
+++ b/arch/mips/ite-boards/qed-4n-s01b/init.c
@@ -34,13 +34,13 @@
#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <asm/sections.h>
#include <asm/it8172/it8172.h>
#include <asm/it8172/it8172_dbg.h>
int prom_argc;
char **prom_argv, **prom_envp;
-extern char _end;
extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize);
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index 85749246a671..02bd39add891 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,6 +2,6 @@
# Makefile for the Jazz family specific parts of the kernel
#
-obj-y := int-handler.o irq.o jazzdma.o reset.o setup.o
+obj-y := irq.o jazzdma.o reset.o setup.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
deleted file mode 100644
index dc752c67b528..000000000000
--- a/arch/mips/jazz/int-handler.S
+++ /dev/null
@@ -1,282 +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) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
- *
- * Jazz family specific interrupt stuff
- *
- * To do: On Jazz machines we remap some non-ISA interrupts to ISA
- * interrupts. These interrupts should use their own vectors.
- * Squeeze the last cycles out of the handlers. Only a dead
- * cycle is a good cycle.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
- */
- .set noreorder
-
- NESTED(jazz_handle_int, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI
- .set at
-
- /*
- * Get pending interrupts
- */
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
- andi t0,0xff00 # isolate pending bits
- beqz t0,3f
- sll t0,16 # delay slot
-
- /*
- * Find irq with highest priority
- * FIXME: This is slow - use binary search
- */
- la t1,ll_vectors
-1: bltz t0,2f # found pending irq
- sll t0,1
- b 1b
- subu t1,PTRSIZE # delay slot
-
- /*
- * Do the low-level stuff
- */
-2: lw t0,(t1)
- jr t0
- nop # delay slot
- END(jazz_handle_int)
-
-ll_sw0: li s1,~IE_SW0
- mfc0 t0,CP0_CAUSE
- and t0,s1
- mtc0 t0,CP0_CAUSE
- PANIC("Unimplemented sw0 handler")
-
-ll_sw1: li s1,~IE_SW1
- mfc0 t0,CP0_CAUSE
- and t0,s1
- mtc0 t0,CP0_CAUSE
- PANIC("Unimplemented sw1 handler")
-
-ll_local_dma: li s1,~IE_IRQ0
- PANIC("Unimplemented local_dma handler")
-
-ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
-#if PTRSIZE == 8 /* True 64 bit kernel */
- dsll t0,1
-#endif
- .set reorder
- LONG_L t0,local_vector(t0)
- jr t0
- .set noreorder
-
-/*
- * The braindead PICA hardware gives us no way to distinguish if we really
- * received interrupt 7 from the (E)ISA bus or if we just received an
- * interrupt with no findable cause. This sometimes happens with braindead
- * cards. Oh well - for all the Jazz boxes slots are more or less just
- * whistles and bells and we're aware of the problem.
- */
-ll_isa_irq: lw a0, JAZZ_EISA_IRQ_ACK
-
- jal do_IRQ
- move a1,sp
-
- j ret_from_irq
- nop
-
-/*
- * Hmm... This is not just a plain PC clone so the question is
- * which devices on Jazz machines can generate an (E)ISA NMI?
- * (Writing to nonexistent memory?)
- */
-ll_isa_nmi: li s1,~IE_IRQ3
- PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ - remapped to be more similar to an IBM compatible.
- *
- * The timer interrupt is handled specially to ensure that the jiffies
- * variable is updated at all times. Specifically, the timer interrupt is
- * just like the complete handlers except that it is invoked with interrupts
- * disabled and should never re-enable them. If other interrupts were
- * allowed to be processed while the timer interrupt is active, then the
- * other interrupts would have to avoid using the jiffies variable for delay
- * and interval timing operations to avoid hanging the system.
- */
-ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
- li s1,~IE_IRQ4
-
- li a0, JAZZ_TIMER_IRQ
- jal do_IRQ
- move a1,sp
-
- mfc0 t0,CP0_STATUS # disable interrupts again
- ori t0,1
- xori t0,1
- mtc0 t0,CP0_STATUS
-
- j ret_from_irq
- nop
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count: j ret_from_irq
- mtc0 zero,CP0_COMPARE
-
-#if 0
-/*
- * Call the handler for the interrupt
- * (Currently unused)
- */
-call_real: /*
- * temporarily disable interrupt
- */
- mfc0 t2,CP0_STATUS
- and t2,s1
- mtc0 t2,CP0_STATUS
- nor s1,zero,s1
- jal do_IRQ
-
- /*
- * reenable interrupt
- */
- mfc0 t2,CP0_STATUS
- or t2,s1
- mtc0 t2,CP0_STATUS
- j ret_from_irq
-#endif
-
- .data
- PTR ll_sw0 # SW0
- PTR ll_sw1 # SW1
- PTR ll_local_dma # Local DMA
- PTR ll_local_dev # Local devices
- PTR ll_isa_irq # ISA IRQ
- PTR ll_isa_nmi # ISA NMI
- PTR ll_timer # Timer
-ll_vectors: PTR ll_count # Count/Compare IRQ
-
- /*
- * Interrupt handlers for local devices.
- */
- .text
- .set reorder
-loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ
- */
-loc_parallel: li s1,~JAZZ_IE_PARALLEL
- li a0,JAZZ_PARALLEL_IRQ
- b loc_call
-
-/*
- * Floppy IRQ
- */
-loc_floppy: li s1,~JAZZ_IE_FLOPPY
- li a0,JAZZ_FLOPPY_IRQ
- b loc_call
-
-/*
- * Sound IRQ
- */
-loc_sound: PANIC("Unimplemented loc_sound handler")
-loc_video: PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler
- */
-loc_ethernet: li s1,~JAZZ_IE_ETHERNET
- li a0,JAZZ_ETHERNET_IRQ
- b loc_call
-
-/*
- * SCSI interrupt handler
- */
-loc_scsi: li s1,~JAZZ_IE_SCSI
- li a0,JAZZ_SCSI_IRQ
- b loc_call
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
- li a0,JAZZ_KEYBOARD_IRQ
- b loc_call
-
-/*
- * Mouse interrupt handler
- */
-loc_mouse: li s1,~JAZZ_IE_MOUSE
- li a0,JAZZ_MOUSE_IRQ
- b loc_call
-
-/*
- * Serial port 1 IRQ
- */
-loc_serial1: li s1,~JAZZ_IE_SERIAL1
- li a0,JAZZ_SERIAL1_IRQ
- b loc_call
-
-/*
- * Serial port 2 IRQ
- */
-loc_serial2: li s1,~JAZZ_IE_SERIAL2
- li a0,JAZZ_SERIAL2_IRQ
- b loc_call
-
-/*
- * Call the interrupt handler for an interrupt generated by a
- * local device.
- */
-loc_call: /*
- * Temporarily disable interrupt source
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- and t2,s1
- sh t2,JAZZ_IO_IRQ_ENABLE
-
- nor s1,zero,s1
- jal do_IRQ
-
- /*
- * Reenable interrupt
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- or t2,s1
- sh t2,JAZZ_IO_IRQ_ENABLE
-
- j ret_from_irq
-
-/*
- * "Jump extender" to reach spurious_interrupt
- */
-3: j spurious_interrupt
-
-/*
- * Vectors for interrupts generated by local devices
- */
- .data
-local_vector: PTR loc_no_irq
- PTR loc_parallel
- PTR loc_floppy
- PTR loc_sound
- PTR loc_video
- PTR loc_ethernet
- PTR loc_scsi
- PTR loc_keyboard
- PTR loc_mouse
- PTR loc_serial1
- PTR loc_serial2
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index b309b1bcf2e8..becc9accd495 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -15,8 +15,6 @@
#include <asm/io.h>
#include <asm/jazz.h>
-extern asmlinkage void jazz_handle_int(void);
-
static DEFINE_SPINLOCK(r4030_lock);
static void enable_r4030_irq(unsigned int irq)
@@ -90,10 +88,82 @@ void __init init_r4030_ints(void)
*/
void __init arch_init_irq(void)
{
- set_except_vector(0, jazz_handle_int);
-
init_i8259_irqs(); /* Integrated i8259 */
init_r4030_ints();
change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
}
+
+static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
+{
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+ r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
+ do_IRQ(irq, regs);
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+ r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
+}
+
+static void ll_local_dev(struct pt_regs *regs)
+{
+ switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
+ case 0:
+ panic("Unimplemented loc_no_irq handler");
+ break;
+ case 4:
+ loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
+ break;
+ case 8:
+ loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
+ break;
+ case 12:
+ panic("Unimplemented loc_sound handler");
+ break;
+ case 16:
+ panic("Unimplemented loc_video handler");
+ break;
+ case 20:
+ loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
+ break;
+ case 24:
+ loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
+ break;
+ case 28:
+ loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
+ break;
+ case 32:
+ loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
+ break;
+ case 36:
+ loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
+ break;
+ case 40:
+ loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
+ break;
+ }
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & IE_IRQ5)
+ write_c0_compare(0);
+ else if (pending & IE_IRQ4) {
+ r4030_read_reg32(JAZZ_TIMER_REGISTER);
+ do_IRQ(JAZZ_TIMER_IRQ, regs);
+ } else if (pending & IE_IRQ3)
+ panic("Unimplemented ISA NMI handler");
+ else if (pending & IE_IRQ2)
+ do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
+ else if (pending & IE_IRQ1) {
+ ll_local_dev(regs);
+ } else if (unlikely(pending & IE_IRQ0))
+ panic("Unimplemented local_dma handler");
+ else if (pending & IE_SW1) {
+ clear_c0_cause(IE_SW1);
+ panic("Unimplemented sw1 handler");
+ } else if (pending & IE_SW0) {
+ clear_c0_cause(IE_SW0);
+ panic("Unimplemented sw0 handler");
+ }
+}
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
index a6bd3f4d3049..e6561345d12a 100644
--- a/arch/mips/jmr3927/common/rtc_ds1742.c
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -60,15 +60,15 @@ rtc_ds1742_get_time(void)
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
- CMOS_WRITE(RTC_READ, RTC_CONTROL);
- second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
- minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
- hour = BCD2BIN(CMOS_READ(RTC_HOURS));
- day = BCD2BIN(CMOS_READ(RTC_DATE));
- month = BCD2BIN(CMOS_READ(RTC_MONTH));
- year = BCD2BIN(CMOS_READ(RTC_YEAR));
- century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
- CMOS_WRITE(0, RTC_CONTROL);
+ rtc_write(RTC_READ, RTC_CONTROL);
+ second = BCD2BIN(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+ minute = BCD2BIN(rtc_read(RTC_MINUTES));
+ hour = BCD2BIN(rtc_read(RTC_HOURS));
+ day = BCD2BIN(rtc_read(RTC_DATE));
+ month = BCD2BIN(rtc_read(RTC_MONTH));
+ year = BCD2BIN(rtc_read(RTC_YEAR));
+ century = BCD2BIN(rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK);
+ rtc_write(0, RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags);
year += century * 100;
@@ -87,16 +87,16 @@ rtc_ds1742_set_time(unsigned long t)
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
- CMOS_WRITE(RTC_READ, RTC_CONTROL);
- cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
- cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
- cmos_hour = (u8)CMOS_READ(RTC_HOURS);
- cmos_day = (u8)CMOS_READ(RTC_DATE);
- cmos_month = (u8)CMOS_READ(RTC_MONTH);
- cmos_year = (u8)CMOS_READ(RTC_YEAR);
- cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK;
+ rtc_write(RTC_READ, RTC_CONTROL);
+ cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+ cmos_minute = (u8)rtc_read(RTC_MINUTES);
+ cmos_hour = (u8)rtc_read(RTC_HOURS);
+ cmos_day = (u8)rtc_read(RTC_DATE);
+ cmos_month = (u8)rtc_read(RTC_MONTH);
+ cmos_year = (u8)rtc_read(RTC_YEAR);
+ cmos_century = rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK;
- CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+ rtc_write(RTC_WRITE, RTC_CONTROL);
/* convert */
to_tm(t, &tm);
@@ -104,18 +104,18 @@ rtc_ds1742_set_time(unsigned long t)
/* check each field one by one */
year = BIN2BCD(tm.tm_year - EPOCH);
if (year != cmos_year) {
- CMOS_WRITE(year,RTC_YEAR);
+ rtc_write(year,RTC_YEAR);
}
month = BIN2BCD(tm.tm_mon);
if (month != (cmos_month & 0x1f)) {
- CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
+ rtc_write((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
}
day = BIN2BCD(tm.tm_mday);
if (day != cmos_day) {
- CMOS_WRITE(day, RTC_DATE);
+ rtc_write(day, RTC_DATE);
}
if (cmos_hour & 0x40) {
@@ -130,20 +130,20 @@ rtc_ds1742_set_time(unsigned long t)
/* 24 hour format */
hour = BIN2BCD(tm.tm_hour) & 0x3f;
}
- if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS);
+ if (hour != cmos_hour) rtc_write(hour, RTC_HOURS);
minute = BIN2BCD(tm.tm_min);
if (minute != cmos_minute) {
- CMOS_WRITE(minute, RTC_MINUTES);
+ rtc_write(minute, RTC_MINUTES);
}
second = BIN2BCD(tm.tm_sec);
if (second != cmos_second) {
- CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS);
+ rtc_write(second & RTC_SECONDS_MASK,RTC_SECONDS);
}
/* RTC_CENTURY and RTC_CONTROL share same address... */
- CMOS_WRITE(cmos_century, RTC_CONTROL);
+ rtc_write(cmos_century, RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -163,9 +163,9 @@ rtc_ds1742_init(unsigned long base)
rtc_mips_set_time = rtc_ds1742_set_time;
/* clear oscillator stop bit */
- CMOS_WRITE(RTC_READ, RTC_CONTROL);
- cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
- CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
- CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */
- CMOS_WRITE(0, RTC_CONTROL);
+ rtc_write(RTC_READ, RTC_CONTROL);
+ cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+ rtc_write(RTC_WRITE, RTC_CONTROL);
+ rtc_write(cmos_second, RTC_SECONDS); /* clear msb */
+ rtc_write(0, RTC_CONTROL);
}
diff --git a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile
index 75bf418b94c0..baf5077813c1 100644
--- a/arch/mips/jmr3927/rbhma3100/Makefile
+++ b/arch/mips/jmr3927/rbhma3100/Makefile
@@ -2,7 +2,7 @@
# Makefile for TOSHIBA JMR-TX3927 board
#
-obj-y += init.o int-handler.o irq.o setup.o
+obj-y += init.o irq.o setup.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o
diff --git a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S
deleted file mode 100644
index f85bbf407542..000000000000
--- a/arch/mips/jmr3927/rbhma3100/int-handler.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ahennessy@mvista.com
- *
- * Based on arch/mips/tsdb/kernel/int-handler.S
- *
- * Copyright (C) 2000-2001 Toshiba 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 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/jmr3927/jmr3927.h>
-
- /* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop
- * and moving across all the pending IRQ bits in the cause
- * register is _NOT_ the answer, the common case is one
- * pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register
- * IRQ mask, that would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs
- * off, nothing in between like BSD spl() brain-damage.
- *
- */
-
-/* Flush write buffer (needed?)
- * NOTE: TX39xx performs "non-blocking load", so explicitly use the target
- * register of LBU to flush immediately.
- */
-#define FLUSH_WB(tmp) \
- la tmp, JMR3927_IOC_REV_ADDR; \
- lbu tmp, (tmp); \
- move tmp, zero;
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(jmr3927_IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- jal jmr3927_irc_irqdispatch
- move a0, sp
- FLUSH_WB(t0)
- j ret_from_irq
- nop
- END(jmr3927_IRQ)
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 2810727f1d4e..11304d1354f4 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -77,8 +77,6 @@ static int jmr3927_gen_iack(void)
}
#endif
-extern asmlinkage void jmr3927_IRQ(void);
-
#define irc_dlevel 0
#define irc_elevel 1
@@ -262,7 +260,7 @@ void jmr3927_spurious(struct pt_regs *regs)
regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
}
-void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
int irq;
@@ -398,8 +396,6 @@ void __init arch_init_irq(void)
jmr3927_irq_init(NR_ISA_IRQS);
- set_except_vector(0, jmr3927_IRQ);
-
/* setup irq space */
add_tb_irq_space(&jmr3927_isac_irqspace);
add_tb_irq_space(&jmr3927_ioc_irqspace);
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 309d54cceda3..34e8a256765c 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -34,8 +34,11 @@ obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_MIPS_MT_SMP) += smp_mt.o
+obj-$(CONFIG_MIPS_MT) += mips-mt.o
+obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
+obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
+obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ca6b03c773be..92b28b674d6f 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -69,6 +69,9 @@ void output_ptreg_defines(void)
offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
offset("#define PT_STATUS ", struct pt_regs, cp0_status);
offset("#define PT_CAUSE ", struct pt_regs, cp0_cause);
+#ifdef CONFIG_MIPS_MT_SMTC
+ offset("#define PT_TCSTATUS ", struct pt_regs, cp0_tcstatus);
+#endif /* CONFIG_MIPS_MT_SMTC */
size("#define PT_SIZE ", struct pt_regs);
linefeed;
}
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 374de839558d..b6232d9033cb 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -184,7 +184,7 @@ int __compute_return_epc(struct pt_regs *regs)
bit = (insn.i_format.rt >> 2);
bit += (bit != 0);
bit += 23;
- switch (insn.i_format.rt) {
+ switch (insn.i_format.rt & 3) {
case 0: /* bc1f */
case 2: /* bc1fl */
if (~fcr31 & (1 << bit))
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 83c87fe4ee4f..d101d2fb24ca 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -17,6 +17,9 @@
#include <asm/isadep.h>
#include <asm/thread_info.h>
#include <asm/war.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
#ifdef CONFIG_PREEMPT
.macro preempt_stop
@@ -75,6 +78,37 @@ FEXPORT(syscall_exit)
bnez t0, syscall_exit_work
FEXPORT(restore_all) # restore full frame
+#ifdef CONFIG_MIPS_MT_SMTC
+/* Detect and execute deferred IPI "interrupts" */
+ move a0,sp
+ jal deferred_smtc_ipi
+/* Re-arm any temporarily masked interrupts not explicitly "acked" */
+ mfc0 v0, CP0_TCSTATUS
+ ori v1, v0, TCSTATUS_IXMT
+ mtc0 v1, CP0_TCSTATUS
+ andi v0, TCSTATUS_IXMT
+ ehb
+ mfc0 t0, CP0_TCCONTEXT
+ DMT 9 # dmt t1
+ jal mips_ihb
+ mfc0 t2, CP0_STATUS
+ andi t3, t0, 0xff00
+ or t2, t2, t3
+ mtc0 t2, CP0_STATUS
+ ehb
+ andi t1, t1, VPECONTROL_TE
+ beqz t1, 1f
+ EMT
+1:
+ mfc0 v1, CP0_TCSTATUS
+ /* We set IXMT above, XOR should cler it here */
+ xori v1, v1, TCSTATUS_IXMT
+ or v1, v0, v1
+ mtc0 v1, CP0_TCSTATUS
+ ehb
+ xor t0, t0, t3
+ mtc0 t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC */
.set noat
RESTORE_TEMP
RESTORE_AT
@@ -120,28 +154,17 @@ syscall_exit_work:
jal do_syscall_trace
b resume_userspace
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
+
/*
- * Common spurious interrupt handler.
+ * MIPS32R2 Instruction Hazard Barrier - must be called
+ *
+ * For C code use the inline version named instruction_hazard().
*/
-LEAF(spurious_interrupt)
- /*
- * Someone tried to fool us by sending an interrupt but we
- * couldn't find a cause for it.
- */
- PTR_LA t1, irq_err_count
-#ifdef CONFIG_SMP
-1: ll t0, (t1)
- addiu t0, 1
- sc t0, (t1)
-#if R10000_LLSC_WAR
- beqzl t0, 1b
-#else
- beqz t0, 1b
-#endif
-#else
- lw t0, (t1)
- addiu t0, 1
- sw t0, (t1)
-#endif
- j ret_from_irq
- END(spurious_interrupt)
+LEAF(mips_ihb)
+ .set mips32r2
+ jr.hb ra
+ nop
+ END(mips_ihb)
+
+#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 235ad9f6bd35..10f28fb9f008 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -283,11 +283,33 @@
*/
3:
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify write of Status must be atomic */
+ mfc0 t2, CP0_TCSTATUS
+ ori t1, t2, TCSTATUS_IXMT
+ mtc0 t1, CP0_TCSTATUS
+ andi t2, t2, TCSTATUS_IXMT
+ ehb
+ DMT 9 # dmt t1
+ jal mips_ihb
+ nop
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
ori t0, 0x1f
xori t0, 0x1f
mtc0 t0, CP0_STATUS
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ andi t1, t1, VPECONTROL_TE
+ beqz t1, 9f
+ nop
+ EMT # emt
+9:
+ mfc0 t1, CP0_TCSTATUS
+ xori t1, t1, TCSTATUS_IXMT
+ or t1, t1, t2
+ mtc0 t1, CP0_TCSTATUS
+ ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v0, GDB_FR_STATUS(sp)
LONG_L v1, GDB_FR_EPC(sp)
mtc0 v0, CP0_STATUS
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index d4f88e0af24c..6ecbdc1fefd1 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -140,6 +140,7 @@
#include <asm/system.h>
#include <asm/gdb-stub.h>
#include <asm/inst.h>
+#include <asm/smp.h>
/*
* external low-level support routines
@@ -669,6 +670,64 @@ static void kgdb_wait(void *arg)
local_irq_restore(flags);
}
+/*
+ * GDB stub needs to call kgdb_wait on all processor with interrupts
+ * disabled, so it uses it's own special variant.
+ */
+static int kgdb_smp_call_kgdb_wait(void)
+{
+#ifdef CONFIG_SMP
+ struct call_data_struct data;
+ int i, cpus = num_online_cpus() - 1;
+ int cpu = smp_processor_id();
+
+ /*
+ * Can die spectacularly if this CPU isn't yet marked online
+ */
+ BUG_ON(!cpu_online(cpu));
+
+ if (!cpus)
+ return 0;
+
+ if (spin_is_locked(&smp_call_lock)) {
+ /*
+ * Some other processor is trying to make us do something
+ * but we're not going to respond... give up
+ */
+ return -1;
+ }
+
+ /*
+ * We will continue here, accepting the fact that
+ * the kernel may deadlock if another CPU attempts
+ * to call smp_call_function now...
+ */
+
+ data.func = kgdb_wait;
+ data.info = NULL;
+ atomic_set(&data.started, 0);
+ data.wait = 0;
+
+ spin_lock(&smp_call_lock);
+ call_data = &data;
+ mb();
+
+ /* Send a message to all other CPUs and wait for them to respond */
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i) && i != cpu)
+ core_send_ipi(i, SMP_CALL_FUNCTION);
+
+ /* Wait for response */
+ /* FIXME: lock-up detection, backtrace on lock-up */
+ while (atomic_read(&data.started) != cpus)
+ barrier();
+
+ call_data = NULL;
+ spin_unlock(&smp_call_lock);
+#endif
+
+ return 0;
+}
/*
* This function does all command processing for interfacing to gdb. It
@@ -718,7 +777,7 @@ void handle_exception (struct gdb_regs *regs)
/*
* force other cpus to enter kgdb
*/
- smp_call_function(kgdb_wait, NULL, 0, 0);
+ kgdb_smp_call_kgdb_wait();
/*
* If we're in breakpoint() increment the PC
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 13f22d1d0e8b..ff7af369f286 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/cacheops.h>
#include <asm/regdef.h>
#include <asm/fpregdef.h>
@@ -122,6 +123,20 @@ handle_vcei:
.set pop
END(except_vec3_r4000)
+ __FINIT
+
+ .align 5
+NESTED(handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+
+ PTR_LA ra, ret_from_irq
+ move a0, sp
+ j plat_irq_dispatch
+ END(handle_int)
+
+ __INIT
+
/*
* Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
* This is a dedicated interrupt exception vector which reduces the
@@ -157,6 +172,15 @@ NESTED(except_vec_vi, 0, sp)
SAVE_AT
.set push
.set noreorder
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * To keep from blindly blocking *all* interrupts
+ * during service by SMTC kernel, we also want to
+ * pass the IM value to be cleared.
+ */
+EXPORT(except_vec_vi_mori)
+ ori a0, $0, 0
+#endif /* CONFIG_MIPS_MT_SMTC */
EXPORT(except_vec_vi_lui)
lui v0, 0 /* Patched */
j except_vec_vi_handler
@@ -173,6 +197,25 @@ EXPORT(except_vec_vi_end)
NESTED(except_vec_vi_handler, 0, sp)
SAVE_TEMP
SAVE_STATIC
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC has an interesting problem that interrupts are level-triggered,
+ * and the CLI macro will clear EXL, potentially causing a duplicate
+ * interrupt service invocation. So we need to clear the associated
+ * IM bit of Status prior to doing CLI, and restore it after the
+ * service routine has been invoked - we must assume that the
+ * service routine will have cleared the state, and any active
+ * level represents a new or otherwised unserviced event...
+ */
+ mfc0 t1, CP0_STATUS
+ and t0, a0, t1
+ mfc0 t2, CP0_TCCONTEXT
+ or t0, t0, t2
+ mtc0 t0, CP0_TCCONTEXT
+ xor t1, t1, t0
+ mtc0 t1, CP0_STATUS
+ ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
CLI
move a0, sp
jalr v0
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 2e9122a4213a..bdf6f6eff721 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -18,6 +18,7 @@
#include <linux/threads.h>
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/regdef.h>
#include <asm/page.h>
#include <asm/mipsregs.h>
@@ -82,12 +83,33 @@
*/
.macro setup_c0_status set clr
.set push
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * For SMTC, we need to set privilege and disable interrupts only for
+ * the current TC, using the TCStatus register.
+ */
+ mfc0 t0, CP0_TCSTATUS
+ /* Fortunately CU 0 is in the same place in both registers */
+ /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+ li t1, ST0_CU0 | 0x08001c00
+ or t0, t1
+ /* Clear TKSU, leave IXMT */
+ xori t0, 0x00001800
+ mtc0 t0, CP0_TCSTATUS
+ ehb
+ /* We need to leave the global IE bit set, but clear EXL...*/
+ mfc0 t0, CP0_STATUS
+ or t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr
+ xor t0, ST0_EXL | ST0_ERL | \clr
+ mtc0 t0, CP0_STATUS
+#else
mfc0 t0, CP0_STATUS
or t0, ST0_CU0|\set|0x1f|\clr
xor t0, 0x1f|\clr
mtc0 t0, CP0_STATUS
.set noreorder
sll zero,3 # ehb
+#endif
.set pop
.endm
@@ -134,6 +156,24 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
ARC64_TWIDDLE_PC
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * In SMTC kernel, "CLI" is thread-specific, in TCStatus.
+ * We still need to enable interrupts globally in Status,
+ * and clear EXL/ERL.
+ *
+ * TCContext is used to track interrupt levels under
+ * service in SMTC kernel. Clear for boot TC before
+ * allowing any interrupts.
+ */
+ mtc0 zero, CP0_TCCONTEXT
+
+ mfc0 t0, CP0_STATUS
+ ori t0, t0, 0xff1f
+ xori t0, t0, 0x001e
+ mtc0 t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
+
PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE
@@ -166,8 +206,25 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
* function after setting up the stack and gp registers.
*/
NESTED(smp_bootstrap, 16, sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * Read-modify-writes of Status must be atomic, and this
+ * is one case where CLI is invoked without EXL being
+ * necessarily set. The CLI and setup_c0_status will
+ * in fact be redundant for all but the first TC of
+ * each VPE being booted.
+ */
+ DMT 10 # dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
+ jal mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
setup_c0_status_sec
smp_slave_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+ andi t2, t2, VPECONTROL_TE
+ beqz t2, 2f
+ EMT # emt
+2:
+#endif /* CONFIG_MIPS_MT_SMTC */
j start_secondary
END(smp_bootstrap)
#endif /* CONFIG_SMP */
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index b974ac9057f6..2125ba5f1d9b 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -187,6 +187,10 @@ handle_real_irq:
outb(cached_21,0x21);
outb(0x60+irq,0x20); /* 'Specific EOI' to master */
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (irq_hwmask[irq] & ST0_IM)
+ set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
spin_unlock_irqrestore(&i8259A_lock, flags);
return;
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 3f653c7cfbf3..97ebdc754b9e 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -76,6 +76,11 @@ static void level_mask_and_ack_msc_irq(unsigned int irq)
mask_msc_irq(irq);
if (!cpu_has_veic)
MSCIC_WRITE(MSC01_IC_EOI, 0);
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* This actually needs to be a call into platform code */
+ if (irq_hwmask[irq] & ST0_IM)
+ set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
}
/*
@@ -92,6 +97,10 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq)
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (irq_hwmask[irq] & ST0_IM)
+ set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
}
/*
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 3dd76b3d2967..3dce742e716f 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -38,6 +38,15 @@ void ack_bad_irq(unsigned int irq)
atomic_t irq_err_count;
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+unsigned long irq_hwmask[NR_IRQS];
+#endif /* CONFIG_MIPS_MT_SMTC */
+
#undef do_IRQ
/*
@@ -49,6 +58,7 @@ asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs)
{
irq_enter();
+ __DO_IRQ_SMTC_HOOK();
__do_IRQ(irq, regs);
irq_exit();
@@ -101,6 +111,11 @@ skip:
return 0;
}
+asmlinkage void spurious_interrupt(struct pt_regs *regs)
+{
+ atomic_inc(&irq_err_count);
+}
+
#ifdef CONFIG_KGDB
extern void breakpoint(void);
extern void set_debug_traps(void);
@@ -124,6 +139,9 @@ void __init init_IRQ(void)
irq_desc[i].depth = 1;
irq_desc[i].handler = &no_irq_type;
spin_lock_init(&irq_desc[i].lock);
+#ifdef CONFIG_MIPS_MT_SMTC
+ irq_hwmask[i] = 0;
+#endif /* CONFIG_MIPS_MT_SMTC */
}
arch_init_irq();
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
new file mode 100644
index 000000000000..f06a144c7881
--- /dev/null
+++ b/arch/mips/kernel/kspd.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 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/kernel.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+
+#include <asm/vpe.h>
+#include <asm/rtlx.h>
+#include <asm/kspd.h>
+
+static struct workqueue_struct *workqueue = NULL;
+static struct work_struct work;
+
+extern unsigned long cpu_khz;
+
+struct mtsp_syscall {
+ int cmd;
+ unsigned char abi;
+ unsigned char size;
+};
+
+struct mtsp_syscall_ret {
+ int retval;
+ int errno;
+};
+
+struct mtsp_syscall_generic {
+ int arg0;
+ int arg1;
+ int arg2;
+ int arg3;
+ int arg4;
+ int arg5;
+ int arg6;
+};
+
+static struct list_head kspd_notifylist;
+static int sp_stopping = 0;
+
+/* these should match with those in the SDE kit */
+#define MTSP_SYSCALL_BASE 0
+#define MTSP_SYSCALL_EXIT (MTSP_SYSCALL_BASE + 0)
+#define MTSP_SYSCALL_OPEN (MTSP_SYSCALL_BASE + 1)
+#define MTSP_SYSCALL_READ (MTSP_SYSCALL_BASE + 2)
+#define MTSP_SYSCALL_WRITE (MTSP_SYSCALL_BASE + 3)
+#define MTSP_SYSCALL_CLOSE (MTSP_SYSCALL_BASE + 4)
+#define MTSP_SYSCALL_LSEEK32 (MTSP_SYSCALL_BASE + 5)
+#define MTSP_SYSCALL_ISATTY (MTSP_SYSCALL_BASE + 6)
+#define MTSP_SYSCALL_GETTIME (MTSP_SYSCALL_BASE + 7)
+#define MTSP_SYSCALL_PIPEFREQ (MTSP_SYSCALL_BASE + 8)
+#define MTSP_SYSCALL_GETTOD (MTSP_SYSCALL_BASE + 9)
+
+#define MTSP_O_RDONLY 0x0000
+#define MTSP_O_WRONLY 0x0001
+#define MTSP_O_RDWR 0x0002
+#define MTSP_O_NONBLOCK 0x0004
+#define MTSP_O_APPEND 0x0008
+#define MTSP_O_SHLOCK 0x0010
+#define MTSP_O_EXLOCK 0x0020
+#define MTSP_O_ASYNC 0x0040
+#define MTSP_O_FSYNC O_SYNC
+#define MTSP_O_NOFOLLOW 0x0100
+#define MTSP_O_SYNC 0x0080
+#define MTSP_O_CREAT 0x0200
+#define MTSP_O_TRUNC 0x0400
+#define MTSP_O_EXCL 0x0800
+#define MTSP_O_BINARY 0x8000
+
+#define SP_VPE 1
+
+struct apsp_table {
+ int sp;
+ int ap;
+};
+
+/* we might want to do the mode flags too */
+struct apsp_table open_flags_table[] = {
+ { MTSP_O_RDWR, O_RDWR },
+ { MTSP_O_WRONLY, O_WRONLY },
+ { MTSP_O_CREAT, O_CREAT },
+ { MTSP_O_TRUNC, O_TRUNC },
+ { MTSP_O_NONBLOCK, O_NONBLOCK },
+ { MTSP_O_APPEND, O_APPEND },
+ { MTSP_O_NOFOLLOW, O_NOFOLLOW }
+};
+
+struct apsp_table syscall_command_table[] = {
+ { MTSP_SYSCALL_OPEN, __NR_open },
+ { MTSP_SYSCALL_CLOSE, __NR_close },
+ { MTSP_SYSCALL_READ, __NR_read },
+ { MTSP_SYSCALL_WRITE, __NR_write },
+ { MTSP_SYSCALL_LSEEK32, __NR_lseek }
+};
+
+static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3)
+{
+ register long int _num __asm__ ("$2") = num;
+ register long int _arg0 __asm__ ("$4") = arg0;
+ register long int _arg1 __asm__ ("$5") = arg1;
+ register long int _arg2 __asm__ ("$6") = arg2;
+ register long int _arg3 __asm__ ("$7") = arg3;
+
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ __asm__ __volatile__ (
+ " syscall \n"
+ : "=r" (_num), "=r" (_arg3)
+ : "r" (_num), "r" (_arg0), "r" (_arg1), "r" (_arg2), "r" (_arg3));
+
+ set_fs(old_fs);
+
+ /* $a3 is error flag */
+ if (_arg3)
+ return -_num;
+
+ return _num;
+}
+
+static int translate_syscall_command(int cmd)
+{
+ int i;
+ int ret = -1;
+
+ for (i = 0; i < ARRAY_SIZE(syscall_command_table); i++) {
+ if ((cmd == syscall_command_table[i].sp))
+ return syscall_command_table[i].ap;
+ }
+
+ return ret;
+}
+
+static unsigned int translate_open_flags(int flags)
+{
+ int i;
+ unsigned int ret = 0;
+
+ for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table));
+ i++) {
+ if( (flags & open_flags_table[i].sp) ) {
+ ret |= open_flags_table[i].ap;
+ }
+ }
+
+ return ret;
+}
+
+
+static void sp_setfsuidgid( uid_t uid, gid_t gid)
+{
+ current->fsuid = uid;
+ current->fsgid = gid;
+
+ key_fsuid_changed(current);
+ key_fsgid_changed(current);
+}
+
+/*
+ * Expects a request to be on the sysio channel. Reads it. Decides whether
+ * its a linux syscall and runs it, or whatever. Puts the return code back
+ * into the request and sends the whole thing back.
+ */
+void sp_work_handle_request(void)
+{
+ struct mtsp_syscall sc;
+ struct mtsp_syscall_generic generic;
+ struct mtsp_syscall_ret ret;
+ struct kspd_notifications *n;
+ struct timeval tv;
+ struct timezone tz;
+ int cmd;
+
+ char *vcwd;
+ mm_segment_t old_fs;
+ int size;
+
+ ret.retval = -1;
+
+ if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
+ printk(KERN_ERR "Expected request but nothing to read\n");
+ return;
+ }
+
+ size = sc.size;
+
+ if (size) {
+ if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
+ printk(KERN_ERR "Expected request but nothing to read\n");
+ return;
+ }
+ }
+
+ /* Run the syscall at the priviledge of the user who loaded the
+ SP program */
+
+ if (vpe_getuid(SP_VPE))
+ sp_setfsuidgid( vpe_getuid(SP_VPE), vpe_getgid(SP_VPE));
+
+ switch (sc.cmd) {
+ /* needs the flags argument translating from SDE kit to
+ linux */
+ case MTSP_SYSCALL_PIPEFREQ:
+ ret.retval = cpu_khz * 1000;
+ ret.errno = 0;
+ break;
+
+ case MTSP_SYSCALL_GETTOD:
+ memset(&tz, 0, sizeof(tz));
+ if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
+ (int)&tz, 0,0)) == 0)
+ ret.retval = tv.tv_sec;
+
+ ret.errno = errno;
+ break;
+
+ case MTSP_SYSCALL_EXIT:
+ list_for_each_entry(n, &kspd_notifylist, list)
+ n->kspd_sp_exit(SP_VPE);
+ sp_stopping = 1;
+
+ printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n",
+ generic.arg0);
+ break;
+
+ case MTSP_SYSCALL_OPEN:
+ generic.arg1 = translate_open_flags(generic.arg1);
+
+ vcwd = vpe_getcwd(SP_VPE);
+
+ /* change to the cwd of the process that loaded the SP program */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ sys_chdir(vcwd);
+ set_fs(old_fs);
+
+ sc.cmd = __NR_open;
+
+ /* fall through */
+
+ default:
+ if ((sc.cmd >= __NR_Linux) &&
+ (sc.cmd <= (__NR_Linux + __NR_Linux_syscalls)) )
+ cmd = sc.cmd;
+ else
+ cmd = translate_syscall_command(sc.cmd);
+
+ if (cmd >= 0) {
+ ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1,
+ generic.arg2, generic.arg3);
+ ret.errno = errno;
+ } else
+ printk(KERN_WARNING
+ "KSPD: Unknown SP syscall number %d\n", sc.cmd);
+ break;
+ } /* switch */
+
+ if (vpe_getuid(SP_VPE))
+ sp_setfsuidgid( 0, 0);
+
+ if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
+ < sizeof(struct mtsp_syscall_ret))
+ printk("KSPD: sp_work_handle_request failed to send to SP\n");
+}
+
+static void sp_cleanup(void)
+{
+ struct files_struct *files = current->files;
+ int i, j;
+ struct fdtable *fdt;
+
+ j = 0;
+
+ /*
+ * It is safe to dereference the fd table without RCU or
+ * ->file_lock
+ */
+ fdt = files_fdtable(files);
+ for (;;) {
+ unsigned long set;
+ i = j * __NFDBITS;
+ if (i >= fdt->max_fdset || i >= fdt->max_fds)
+ break;
+ set = fdt->open_fds->fds_bits[j++];
+ while (set) {
+ if (set & 1) {
+ struct file * file = xchg(&fdt->fd[i], NULL);
+ if (file)
+ filp_close(file, files);
+ }
+ i++;
+ set >>= 1;
+ }
+ }
+}
+
+static int channel_open = 0;
+
+/* the work handler */
+static void sp_work(void *data)
+{
+ if (!channel_open) {
+ if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
+ printk("KSPD: unable to open sp channel\n");
+ sp_stopping = 1;
+ } else {
+ channel_open++;
+ printk(KERN_DEBUG "KSPD: SP channel opened\n");
+ }
+ } else {
+ /* wait for some data, allow it to sleep */
+ rtlx_read_poll(RTLX_CHANNEL_SYSIO, 1);
+
+ /* Check we haven't been woken because we are stopping */
+ if (!sp_stopping)
+ sp_work_handle_request();
+ }
+
+ if (!sp_stopping)
+ queue_work(workqueue, &work);
+ else
+ sp_cleanup();
+}
+
+static void startwork(int vpe)
+{
+ sp_stopping = channel_open = 0;
+
+ if (workqueue == NULL) {
+ if ((workqueue = create_singlethread_workqueue("kspd")) == NULL) {
+ printk(KERN_ERR "unable to start kspd\n");
+ return;
+ }
+
+ INIT_WORK(&work, sp_work, NULL);
+ queue_work(workqueue, &work);
+ } else
+ queue_work(workqueue, &work);
+
+}
+
+static void stopwork(int vpe)
+{
+ sp_stopping = 1;
+
+ printk(KERN_DEBUG "KSPD: SP stopping\n");
+}
+
+void kspd_notify(struct kspd_notifications *notify)
+{
+ list_add(&notify->list, &kspd_notifylist);
+}
+
+static struct vpe_notifications notify;
+static int kspd_module_init(void)
+{
+ INIT_LIST_HEAD(&kspd_notifylist);
+
+ notify.start = startwork;
+ notify.stop = stopwork;
+ vpe_notify(SP_VPE, &notify);
+
+ return 0;
+}
+
+static void kspd_module_exit(void)
+{
+
+}
+
+module_init(kspd_module_init);
+module_exit(kspd_module_exit);
+
+MODULE_DESCRIPTION("MIPS KSPD");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 3f40c37a9ee6..a7d2bb3cf835 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -356,73 +356,13 @@ asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
size_t count, u32 unused, u64 a4, u64 a5)
{
- ssize_t ret;
- struct file * file;
- ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
- loff_t pos;
-
- ret = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad_file;
- if (!(file->f_mode & FMODE_READ))
- goto out;
- pos = merge_64(a4, a5);
- ret = rw_verify_area(READ, file, &pos, count);
- if (ret < 0)
- goto out;
- ret = -EINVAL;
- if (!file->f_op || !(read = file->f_op->read))
- goto out;
- if (pos < 0)
- goto out;
- ret = -ESPIPE;
- if (!(file->f_mode & FMODE_PREAD))
- goto out;
- ret = read(file, buf, count, &pos);
- if (ret > 0)
- dnotify_parent(file->f_dentry, DN_ACCESS);
-out:
- fput(file);
-bad_file:
- return ret;
+ return sys_pread64(fd, buf, count, merge_64(a4, a5));
}
asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
size_t count, u32 unused, u64 a4, u64 a5)
{
- ssize_t ret;
- struct file * file;
- ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
- loff_t pos;
-
- ret = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad_file;
- if (!(file->f_mode & FMODE_WRITE))
- goto out;
- pos = merge_64(a4, a5);
- ret = rw_verify_area(WRITE, file, &pos, count);
- if (ret < 0)
- goto out;
- ret = -EINVAL;
- if (!file->f_op || !(write = file->f_op->write))
- goto out;
- if (pos < 0)
- goto out;
-
- ret = -ESPIPE;
- if (!(file->f_mode & FMODE_PWRITE))
- goto out;
-
- ret = write(file, buf, count, &pos);
- if (ret > 0)
- dnotify_parent(file->f_dentry, DN_MODIFY);
-out:
- fput(file);
-bad_file:
- return ret;
+ return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
}
asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
@@ -1182,6 +1122,16 @@ asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
return sys_readahead(fd, merge_64(a2, a3), count);
}
+asmlinkage long sys32_sync_file_range(int fd, int __pad,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ int flags)
+{
+ return sys_sync_file_range(fd,
+ merge_64(a2, a3), merge_64(a4, a5),
+ flags);
+}
+
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned int))
static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
new file mode 100644
index 000000000000..02237a685ec7
--- /dev/null
+++ b/arch/mips/kernel/mips-mt.c
@@ -0,0 +1,449 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsmtregs.h>
+#include <asm/r4kcache.h>
+#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 task_t *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;
+ task_t *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;
+ }
+
+ /* 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;
+ task_t *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 = 0;
+
+ 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.
+ */
+
+void mips_mt_regdump(unsigned long mvpctl)
+{
+ unsigned long flags;
+ unsigned long vpflags;
+ unsigned long mvpconf0;
+ int nvpe;
+ int ntc;
+ int i;
+ int tc;
+ unsigned long haltval;
+ unsigned long tcstatval;
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_soft_dump(void);
+#endif /* CONFIG_MIPT_MT_SMTC */
+
+ local_irq_save(flags);
+ vpflags = dvpe();
+ printk("=== MIPS MT State Dump ===\n");
+ printk("-- Global State --\n");
+ printk(" MVPControl Passed: %08lx\n", mvpctl);
+ printk(" MVPControl Read: %08lx\n", vpflags);
+ printk(" MVPConf0 : %08lx\n", (mvpconf0 = read_c0_mvpconf0()));
+ 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++) {
+ 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 */
+ }
+ }
+ }
+ printk("-- per-TC State --\n");
+ for(tc = 0; tc < ntc; tc++) {
+ settc(tc);
+ 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 */
+ printk(" TC %d (current TC with VPE EPC above)\n", tc);
+ } else {
+ haltval = read_tc_c0_tchalt();
+ write_tc_c0_tchalt(1);
+ tcstatval = read_tc_c0_tcstatus();
+ printk(" TC %d\n", tc);
+ }
+ printk(" TCStatus : %08lx\n", tcstatval);
+ printk(" TCBind : %08lx\n", read_tc_c0_tcbind());
+ printk(" TCRestart : %08lx\n", read_tc_c0_tcrestart());
+ printk(" TCHalt : %08lx\n", haltval);
+ printk(" TCContext : %08lx\n", read_tc_c0_tccontext());
+ if (!haltval)
+ write_tc_c0_tchalt(0);
+ }
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_soft_dump();
+#endif /* CONFIG_MIPT_MT_SMTC */
+ printk("===========================\n");
+ evpe(vpflags);
+ local_irq_restore(flags);
+}
+
+static int mt_opt_norps = 0;
+static int mt_opt_rpsctl = -1;
+static int mt_opt_nblsu = -1;
+static int mt_opt_forceconfig7 = 0;
+static int mt_opt_config7 = -1;
+
+static int __init rps_disable(char *s)
+{
+ mt_opt_norps = 1;
+ return 1;
+}
+__setup("norps", rps_disable);
+
+static int __init rpsctl_set(char *str)
+{
+ get_option(&str, &mt_opt_rpsctl);
+ return 1;
+}
+__setup("rpsctl=", rpsctl_set);
+
+static int __init nblsu_set(char *str)
+{
+ get_option(&str, &mt_opt_nblsu);
+ return 1;
+}
+__setup("nblsu=", nblsu_set);
+
+static int __init config7_set(char *str)
+{
+ get_option(&str, &mt_opt_config7);
+ mt_opt_forceconfig7 = 1;
+ return 1;
+}
+__setup("config7=", config7_set);
+
+/* Experimental cache flush control parameters that should go away some day */
+int mt_protiflush = 0;
+int mt_protdflush = 0;
+int mt_n_iflushes = 1;
+int mt_n_dflushes = 1;
+
+static int __init set_protiflush(char *s)
+{
+ mt_protiflush = 1;
+ return 1;
+}
+__setup("protiflush", set_protiflush);
+
+static int __init set_protdflush(char *s)
+{
+ mt_protdflush = 1;
+ return 1;
+}
+__setup("protdflush", set_protdflush);
+
+static int __init niflush(char *s)
+{
+ get_option(&s, &mt_n_iflushes);
+ return 1;
+}
+__setup("niflush=", niflush);
+
+static int __init ndflush(char *s)
+{
+ get_option(&s, &mt_n_dflushes);
+ 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;
+
+static int __init set_itc_base(char *str)
+{
+ get_option(&str, &itc_base);
+ return 1;
+}
+
+__setup("itcbase=", set_itc_base);
+
+void mips_mt_set_cpuoptions(void)
+{
+ unsigned int oconfig7 = read_c0_config7();
+ unsigned int nconfig7 = oconfig7;
+
+ if (mt_opt_norps) {
+ printk("\"norps\" option deprectated: use \"rpsctl=\"\n");
+ }
+ if (mt_opt_rpsctl >= 0) {
+ printk("34K return prediction stack override set to %d.\n",
+ mt_opt_rpsctl);
+ if (mt_opt_rpsctl)
+ nconfig7 |= (1 << 2);
+ else
+ nconfig7 &= ~(1 << 2);
+ }
+ if (mt_opt_nblsu >= 0) {
+ printk("34K ALU/LSU sync override set to %d.\n", mt_opt_nblsu);
+ if (mt_opt_nblsu)
+ nconfig7 |= (1 << 5);
+ else
+ nconfig7 &= ~(1 << 5);
+ }
+ if (mt_opt_forceconfig7) {
+ printk("CP0.Config7 forced to 0x%08x.\n", mt_opt_config7);
+ nconfig7 = mt_opt_config7;
+ }
+ if (oconfig7 != nconfig7) {
+ __asm__ __volatile("sync");
+ write_c0_config7(nconfig7);
+ ehb ();
+ printk("Config7: 0x%08x\n", read_c0_config7());
+ }
+
+ /* Report Cache management debug options */
+ if (mt_protiflush)
+ printk("I-cache flushes single-threaded\n");
+ if (mt_protdflush)
+ printk("D-cache flushes single-threaded\n");
+ if (mt_n_iflushes != 1)
+ printk("I-Cache Flushes Repeated %d times\n", mt_n_iflushes);
+ 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
+ * specific to the 34K core family, which uses
+ * a special mode bit ("ITC") in the ErrCtl
+ * register to enable access to ITC control
+ * registers via cache "tag" operations.
+ */
+ unsigned long ectlval;
+ unsigned long itcblkgrn;
+
+ /* ErrCtl register is known as "ecc" to Linux */
+ ectlval = read_c0_ecc();
+ write_c0_ecc(ectlval | (0x1 << 26));
+ ehb();
+#define INDEX_0 (0x80000000)
+#define INDEX_8 (0x80000008)
+ /* Read "cache tag" for Dcache pseudo-index 8 */
+ cache_op(Index_Load_Tag_D, INDEX_8);
+ ehb();
+ itcblkgrn = read_c0_dtaglo();
+ itcblkgrn &= 0xfffe0000;
+ /* Set for 128 byte pitch of ITC cells */
+ itcblkgrn |= 0x00000c00;
+ /* Stage in Tag register */
+ write_c0_dtaglo(itcblkgrn);
+ ehb();
+ /* Write out to ITU with CACHE op */
+ cache_op(Index_Store_Tag_D, INDEX_8);
+ /* Now set base address, and turn ITC on with 0x1 bit */
+ write_c0_dtaglo((itc_base & 0xfffffc00) | 0x1 );
+ ehb();
+ /* Write out to ITU with CACHE op */
+ cache_op(Index_Store_Tag_D, INDEX_0);
+ write_c0_ecc(ectlval);
+ ehb();
+ printk("Mapped %ld ITC cells starting at 0x%08x\n",
+ ((itcblkgrn & 0x7fe00000) >> 20), itc_base);
+ }
+}
+
+/*
+ * Function to protect cache flushes from concurrent execution
+ * depends on MP software model chosen.
+ */
+
+void mt_cflush_lockdown(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_cflush_lockdown(void);
+
+ smtc_cflush_lockdown();
+#endif /* CONFIG_MIPS_MT_SMTC */
+ /* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
+
+void mt_cflush_release(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_cflush_release(void);
+
+ smtc_cflush_release();
+#endif /* CONFIG_MIPS_MT_SMTC */
+ /* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 86e42c633f73..0a71a4c33716 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -28,22 +28,9 @@ extern long __strnlen_user_asm(const char *s);
/*
* String functions
*/
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-#ifdef CONFIG_64BIT
-EXPORT_SYMBOL(strncmp);
-#endif
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(kernel_thread);
@@ -62,6 +49,3 @@ EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(invalid_pte_table);
-#ifdef CONFIG_GENERIC_IRQ_PROBE
-EXPORT_SYMBOL(probe_irq_mask);
-#endif
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index c66db5e5ab62..199a06e873c6 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -41,6 +41,10 @@
#include <asm/elf.h>
#include <asm/isadep.h>
#include <asm/inst.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+extern void smtc_idle_loop_hook(void);
+#endif /* CONFIG_MIPS_MT_SMTC */
/*
* The idle thread. There's no useful work to be done, so just try to conserve
@@ -51,9 +55,13 @@ ATTRIB_NORET void cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
- while (!need_resched())
+ while (!need_resched()) {
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_idle_loop_hook();
+#endif /* CONFIG_MIPS_MT_SMTC */
if (cpu_wait)
(*cpu_wait)();
+ }
preempt_enable_no_resched();
schedule();
preempt_disable();
@@ -177,6 +185,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
clear_tsk_thread_flag(p, TIF_USEDFPU);
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /*
+ * FPU affinity support is cleaner if we track the
+ * user-visible CPU affinity from the very beginning.
+ * The generic cpus_allowed mask will already have
+ * been copied from the parent before copy_thread
+ * is invoked.
+ */
+ p->thread.user_cpus_allowed = p->cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
if (clone_flags & CLONE_SETTLS)
ti->tp_value = regs->regs[7];
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f838b36cc765..f3106d0771b0 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -248,10 +248,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case FPC_EIR: { /* implementation / version register */
unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned int irqflags;
+ unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
if (!cpu_has_fpu)
break;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify-write of Status must be atomic */
+ local_irq_save(irqflags);
+ mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
@@ -266,6 +276,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
write_c0_status(flags);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ emt(mtflags);
+ local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
preempt_enable();
break;
}
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 0d5cf97af727..8704dc0496ea 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -173,12 +173,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
break;
case FPC_EIR: { /* implementation / version register */
unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned int irqflags;
+ unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
if (!cpu_has_fpu) {
tmp = 0;
break;
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify-write of Status must be atomic */
+ local_irq_save(irqflags);
+ mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
@@ -193,6 +203,10 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
write_c0_status(flags);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ emt(mtflags);
+ local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
preempt_enable();
break;
}
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index d2afbd19a9c8..0b1b54acee9f 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -88,7 +88,18 @@
PTR_ADDIU 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 */
+ mfc0 t2, CP0_TCSTATUS
+ ori t1, t2, TCSTATUS_IXMT
+ mtc0 t1, CP0_TCSTATUS
+ andi t2, t2, TCSTATUS_IXMT
+ ehb
+ DMT 8 # dmt t0
+ move t1,ra
+ jal mips_ihb
+ move ra,t1
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t1, CP0_STATUS /* Do we really need this? */
li a3, 0xff01
and t1, a3
@@ -97,6 +108,18 @@
and a2, a3
or a2, t1
mtc0 a2, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+ ehb
+ andi t0, t0, VPECONTROL_TE
+ beqz t0, 1f
+ emt
+1:
+ mfc0 t1, CP0_TCSTATUS
+ xori t1, t1, TCSTATUS_IXMT
+ or t1, t1, t2
+ mtc0 t1, CP0_TCSTATUS
+ ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
move v0, a0
jr ra
END(resume)
@@ -131,10 +154,19 @@ LEAF(_restore_fp)
#define FPU_DEFAULT 0x00000000
LEAF(_init_fpu)
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */
+ mfc0 t0, CP0_TCSTATUS
+ /* Bit position is the same for Status, TCStatus */
+ li t1, ST0_CU1
+ or t0, t1
+ mtc0 t0, CP0_TCSTATUS
+#else /* Normal MIPS CU1 enable */
mfc0 t0, CP0_STATUS
li t1, ST0_CU1
or t0, t1
mtc0 t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
fpu_enable_hazard
li t1, FPU_DEFAULT
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 986a9cf23067..caf777f83289 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -21,45 +21,44 @@
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/seq_file.h>
+#include <linux/syscalls.h>
+#include <linux/moduleloader.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/wait.h>
-
#include <asm/mipsmtregs.h>
-#include <asm/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/vpe.h>
#include <asm/rtlx.h>
-#include <asm/uaccess.h>
#define RTLX_TARG_VPE 1
static struct rtlx_info *rtlx;
static int major;
static char module_name[] = "rtlx";
-static struct irqaction irq;
-static int irq_num;
-
-static inline int spacefree(int read, int write, int size)
-{
- if (read == write) {
- /*
- * never fill the buffer completely, so indexes are always
- * equal if empty and only empty, or !equal if data available
- */
- return size - 1;
- }
-
- return ((read + size - write) % size) - 1;
-}
static struct chan_waitqueues {
wait_queue_head_t rt_queue;
wait_queue_head_t lx_queue;
+ int in_open;
} channel_wqs[RTLX_CHANNELS];
+static struct irqaction irq;
+static int irq_num;
+static struct vpe_notifications notify;
+static int sp_stopping = 0;
+
extern void *vpe_get_shared(int index);
static void rtlx_dispatch(struct pt_regs *regs)
@@ -67,174 +66,298 @@ static void rtlx_dispatch(struct pt_regs *regs)
do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
}
+
+/* Interrupt handler may be called before rtlx_init has otherwise had
+ a chance to run.
+*/
static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
for (i = 0; i < RTLX_CHANNELS; i++) {
- struct rtlx_channel *chan = &rtlx->channel[i];
-
- if (chan->lx_read != chan->lx_write)
- wake_up_interruptible(&channel_wqs[i].lx_queue);
+ wake_up(&channel_wqs[i].lx_queue);
+ wake_up(&channel_wqs[i].rt_queue);
}
return IRQ_HANDLED;
}
-/* call when we have the address of the shared structure from the SP side. */
-static int rtlx_init(struct rtlx_info *rtlxi)
+static __attribute_used__ void dump_rtlx(void)
{
int i;
- if (rtlxi->id != RTLX_ID) {
- printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi);
- return -ENOEXEC;
- }
+ printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
- /* initialise the wait queues */
for (i = 0; i < RTLX_CHANNELS; i++) {
- init_waitqueue_head(&channel_wqs[i].rt_queue);
- init_waitqueue_head(&channel_wqs[i].lx_queue);
- }
+ struct rtlx_channel *chan = &rtlx->channel[i];
- /* set up for interrupt handling */
- memset(&irq, 0, sizeof(struct irqaction));
+ printk(" rt_state %d lx_state %d buffer_size %d\n",
+ chan->rt_state, chan->lx_state, chan->buffer_size);
- if (cpu_has_vint)
- set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+ printk(" rt_read %d rt_write %d\n",
+ chan->rt_read, chan->rt_write);
+
+ printk(" lx_read %d lx_write %d\n",
+ chan->lx_read, chan->lx_write);
- irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
- irq.handler = rtlx_interrupt;
- irq.flags = SA_INTERRUPT;
- irq.name = "RTLX";
- irq.dev_id = rtlx;
- setup_irq(irq_num, &irq);
+ printk(" rt_buffer <%s>\n", chan->rt_buffer);
+ printk(" lx_buffer <%s>\n", chan->lx_buffer);
+ }
+}
+
+/* call when we have the address of the shared structure from the SP side. */
+static int rtlx_init(struct rtlx_info *rtlxi)
+{
+ if (rtlxi->id != RTLX_ID) {
+ printk(KERN_ERR "no valid RTLX id at 0x%p 0x%x\n", rtlxi, rtlxi->id);
+ return -ENOEXEC;
+ }
rtlx = rtlxi;
return 0;
}
-/* only allow one open process at a time to open each channel */
-static int rtlx_open(struct inode *inode, struct file *filp)
+/* notifications */
+static void starting(int vpe)
+{
+ int i;
+ sp_stopping = 0;
+
+ /* force a reload of rtlx */
+ rtlx=NULL;
+
+ /* wake up any sleeping rtlx_open's */
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+static void stopping(int vpe)
{
- int minor, ret;
+ int i;
+
+ sp_stopping = 1;
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+
+int rtlx_open(int index, int can_sleep)
+{
+ int ret;
struct rtlx_channel *chan;
+ volatile struct rtlx_info **p;
- /* assume only 1 device at the mo. */
- minor = MINOR(inode->i_rdev);
+ if (index >= RTLX_CHANNELS) {
+ printk(KERN_DEBUG "rtlx_open index out of range\n");
+ return -ENOSYS;
+ }
+
+ if (channel_wqs[index].in_open) {
+ printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
+ return -EBUSY;
+ }
+
+ channel_wqs[index].in_open++;
if (rtlx == NULL) {
- struct rtlx_info **p;
if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
- printk(KERN_ERR "vpe_get_shared is NULL. "
- "Has an SP program been loaded?\n");
- return -EFAULT;
+ if (can_sleep) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* go to sleep */
+ add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ /* back running */
+ } else {
+ printk( KERN_DEBUG "No SP program loaded, and device "
+ "opened with O_NONBLOCK\n");
+ channel_wqs[index].in_open = 0;
+ return -ENOSYS;
+ }
}
if (*p == NULL) {
- printk(KERN_ERR "vpe_shared %p %p\n", p, *p);
- return -EFAULT;
+ if (can_sleep) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* go to sleep */
+ add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (*p == NULL) {
+ schedule();
+
+ /* reset task state to interruptable otherwise
+ we'll whizz round here like a very fast loopy
+ thing. schedule() appears to return with state
+ set to TASK_RUNNING.
+
+ If the loaded SP program, for whatever reason,
+ doesn't set up the shared structure *p will never
+ become true. So whoever connected to either /dev/rt?
+ or if it was kspd, will then take up rather a lot of
+ processor cycles.
+ */
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ /* back running */
+ }
+ else {
+ printk(" *vpe_get_shared is NULL. "
+ "Has an SP program been loaded?\n");
+ channel_wqs[index].in_open = 0;
+ return -ENOSYS;
+ }
}
- if ((ret = rtlx_init(*p)) < 0)
- return ret;
+ if ((unsigned int)*p < KSEG0) {
+ printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
+ "maybe an error code %d\n", (int)*p);
+ channel_wqs[index].in_open = 0;
+ return -ENOSYS;
+ }
+
+ if ((ret = rtlx_init(*p)) < 0) {
+ channel_wqs[index].in_open = 0;
+ return ret;
+ }
}
- chan = &rtlx->channel[minor];
+ chan = &rtlx->channel[index];
- if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state))
- return -EBUSY;
+ if (chan->lx_state == RTLX_STATE_OPENED) {
+ channel_wqs[index].in_open = 0;
+ return -EBUSY;
+ }
+ chan->lx_state = RTLX_STATE_OPENED;
+ channel_wqs[index].in_open = 0;
return 0;
}
-static int rtlx_release(struct inode *inode, struct file *filp)
+int rtlx_release(int index)
{
- int minor = MINOR(inode->i_rdev);
-
- clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state);
- smp_mb__after_clear_bit();
-
+ rtlx->channel[index].lx_state = RTLX_STATE_UNUSED;
return 0;
}
-static unsigned int rtlx_poll(struct file *file, poll_table * wait)
+unsigned int rtlx_read_poll(int index, int can_sleep)
{
- int minor;
- unsigned int mask = 0;
- struct rtlx_channel *chan;
+ struct rtlx_channel *chan;
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
- chan = &rtlx->channel[minor];
+ if (rtlx == NULL)
+ return 0;
- poll_wait(file, &channel_wqs[minor].rt_queue, wait);
- poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+ chan = &rtlx->channel[index];
/* data available to read? */
- if (chan->lx_read != chan->lx_write)
- mask |= POLLIN | POLLRDNORM;
+ if (chan->lx_read == chan->lx_write) {
+ if (can_sleep) {
+ DECLARE_WAITQUEUE(wait, current);
- /* space to write */
- if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size))
- mask |= POLLOUT | POLLWRNORM;
+ /* go to sleep */
+ add_wait_queue(&channel_wqs[index].lx_queue, &wait);
- return mask;
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (chan->lx_read == chan->lx_write) {
+ schedule();
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (sp_stopping) {
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+ return 0;
+ }
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ /* back running */
+ }
+ else
+ return 0;
+ }
+
+ return (chan->lx_write + chan->buffer_size - chan->lx_read)
+ % chan->buffer_size;
}
-static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
- loff_t * ppos)
+static inline int write_spacefree(int read, int write, int size)
{
- unsigned long failed;
- size_t fl = 0L;
- int minor;
- struct rtlx_channel *lx;
- DECLARE_WAITQUEUE(wait, current);
+ if (read == write) {
+ /*
+ * Never fill the buffer completely, so indexes are always
+ * equal if empty and only empty, or !equal if data available
+ */
+ return size - 1;
+ }
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
- lx = &rtlx->channel[minor];
+ return ((read + size - write) % size) - 1;
+}
- /* data available? */
- if (lx->lx_write == lx->lx_read) {
- if (file->f_flags & O_NONBLOCK)
- return 0; /* -EAGAIN makes cat whinge */
+unsigned int rtlx_write_poll(int index)
+{
+ struct rtlx_channel *chan = &rtlx->channel[index];
+ return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
+}
- /* go to sleep */
- add_wait_queue(&channel_wqs[minor].lx_queue, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
+static inline void copy_to(void *dst, void *src, size_t count, int user)
+{
+ if (user)
+ copy_to_user(dst, src, count);
+ else
+ memcpy(dst, src, count);
+}
- while (lx->lx_write == lx->lx_read)
- schedule();
+static inline void copy_from(void *dst, void *src, size_t count, int user)
+{
+ if (user)
+ copy_from_user(dst, src, count);
+ else
+ memcpy(dst, src, count);
+}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&channel_wqs[minor].lx_queue, &wait);
+ssize_t rtlx_read(int index, void *buff, size_t count, int user)
+{
+ size_t fl = 0L;
+ struct rtlx_channel *lx;
- /* back running */
- }
+ if (rtlx == NULL)
+ return -ENOSYS;
+
+ lx = &rtlx->channel[index];
/* find out how much in total */
count = min(count,
- (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
+ (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read)
+ % lx->buffer_size);
/* then how much from the read pointer onwards */
- fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
+ fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
- failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
- if (failed) {
- count = fl - failed;
- goto out;
- }
+ copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user);
/* and if there is anything left at the beginning of the buffer */
- if (count - fl) {
- failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
- if (failed) {
- count -= failed;
- goto out;
- }
- }
+ if ( count - fl )
+ copy_to (buff + fl, lx->lx_buffer, count - fl, user);
-out:
/* update the index */
lx->lx_read += count;
lx->lx_read %= lx->buffer_size;
@@ -242,20 +365,100 @@ out:
return count;
}
-static ssize_t rtlx_write(struct file *file, const char __user * buffer,
+ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
+{
+ struct rtlx_channel *rt;
+ size_t fl;
+
+ if (rtlx == NULL)
+ return(-ENOSYS);
+
+ rt = &rtlx->channel[index];
+
+ /* total number of bytes to copy */
+ count = min(count,
+ (size_t)write_spacefree(rt->rt_read, rt->rt_write,
+ rt->buffer_size));
+
+ /* first bit from write pointer to the end of the buffer, or count */
+ fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
+
+ copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user);
+
+ /* if there's any left copy to the beginning of the buffer */
+ if( count - fl )
+ copy_from (rt->rt_buffer, buffer + fl, count - fl, user);
+
+ rt->rt_write += count;
+ rt->rt_write %= rt->buffer_size;
+
+ return(count);
+}
+
+
+static int file_open(struct inode *inode, struct file *filp)
+{
+ int minor = iminor(inode);
+
+ return rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
+}
+
+static int file_release(struct inode *inode, struct file *filp)
+{
+ int minor = iminor(inode);
+
+ return rtlx_release(minor);
+}
+
+static unsigned int file_poll(struct file *file, poll_table * wait)
+{
+ int minor;
+ unsigned int mask = 0;
+
+ minor = iminor(file->f_dentry->d_inode);
+
+ poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+ poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+
+ if (rtlx == NULL)
+ return 0;
+
+ /* data available to read? */
+ if (rtlx_read_poll(minor, 0))
+ mask |= POLLIN | POLLRDNORM;
+
+ /* space to write */
+ if (rtlx_write_poll(minor))
+ mask |= POLLOUT | POLLWRNORM;
+
+ return mask;
+}
+
+static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
+ loff_t * ppos)
+{
+ int minor = iminor(file->f_dentry->d_inode);
+
+ /* data available? */
+ if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
+ return 0; // -EAGAIN makes cat whinge
+ }
+
+ return rtlx_read(minor, buffer, count, 1);
+}
+
+static ssize_t file_write(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
- unsigned long failed;
int minor;
struct rtlx_channel *rt;
- size_t fl;
DECLARE_WAITQUEUE(wait, current);
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ minor = iminor(file->f_dentry->d_inode);
rt = &rtlx->channel[minor];
/* any space left... */
- if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) {
+ if (!rtlx_write_poll(minor)) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -263,61 +466,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer,
add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
set_current_state(TASK_INTERRUPTIBLE);
- while (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size))
+ while (!rtlx_write_poll(minor))
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
}
- /* total number of bytes to copy */
- count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
-
- /* first bit from write pointer to the end of the buffer, or count */
- fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
-
- failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
- if (failed) {
- count = fl - failed;
- goto out;
- }
-
- /* if there's any left copy to the beginning of the buffer */
- if (count - fl) {
- failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
- if (failed) {
- count -= failed;
- goto out;
- }
- }
-
-out:
- rt->rt_write += count;
- rt->rt_write %= rt->buffer_size;
-
- return count;
+ return rtlx_write(minor, (void *)buffer, count, 1);
}
static struct file_operations rtlx_fops = {
- .owner = THIS_MODULE,
- .open = rtlx_open,
- .release = rtlx_release,
- .write = rtlx_write,
- .read = rtlx_read,
- .poll = rtlx_poll
+ .owner = THIS_MODULE,
+ .open = file_open,
+ .release = file_release,
+ .write = file_write,
+ .read = file_read,
+ .poll = file_poll
+};
+
+static struct irqaction rtlx_irq = {
+ .handler = rtlx_interrupt,
+ .flags = SA_INTERRUPT,
+ .name = "RTLX",
};
+static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+
static char register_chrdev_failed[] __initdata =
KERN_ERR "rtlx_module_init: unable to register device\n";
-static int __init rtlx_module_init(void)
+static int rtlx_module_init(void)
{
+ int i;
+
major = register_chrdev(0, module_name, &rtlx_fops);
if (major < 0) {
printk(register_chrdev_failed);
return major;
}
+ /* initialise the wait queues */
+ for (i = 0; i < RTLX_CHANNELS; i++) {
+ init_waitqueue_head(&channel_wqs[i].rt_queue);
+ init_waitqueue_head(&channel_wqs[i].lx_queue);
+ channel_wqs[i].in_open = 0;
+ }
+
+ /* set up notifiers */
+ notify.start = starting;
+ notify.stop = stopping;
+ vpe_notify(RTLX_TARG_VPE, &notify);
+
+ if (cpu_has_vint)
+ set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+
+ rtlx_irq.dev_id = rtlx;
+ setup_irq(rtlx_irq_num, &rtlx_irq);
+
return 0;
}
@@ -330,5 +536,5 @@ module_init(rtlx_module_init);
module_exit(rtlx_module_exit);
MODULE_DESCRIPTION("MIPS RTLX");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc.");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 2f2dc54b2e26..a0ac0e5f61ad 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -569,8 +569,19 @@ einval: li v0, -EINVAL
sys sys_tkill 2
sys sys_sendfile64 5
sys sys_futex 6
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /*
+ * For FPU affinity scheduling on MIPS MT processors, we need to
+ * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+ * in kernel/sched.c. Considered only temporary we only support these
+ * hooks for the 32-bit kernel - there is no MIPS64 MT processor atm.
+ */
+ sys mipsmt_sys_sched_setaffinity 3
+ sys mipsmt_sys_sched_getaffinity 3
+#else
sys sys_sched_setaffinity 3
sys sys_sched_getaffinity 3 /* 4240 */
+#endif /* CONFIG_MIPS_MT_FPAFF */
sys sys_io_setup 2
sys sys_io_destroy 1
sys sys_io_getevents 5
@@ -634,6 +645,8 @@ einval: li v0, -EINVAL
sys sys_pselect6 6
sys sys_ppoll 5
sys sys_unshare 1
+ sys sys_splice 4
+ sys sys_sync_file_range 7 /* 4305 */
.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 98bf25df56f3..9ba750887377 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -460,3 +460,5 @@ sys_call_table:
PTR sys_pselect6 /* 5260 */
PTR sys_ppoll
PTR sys_unshare
+ PTR sys_splice
+ PTR sys_sync_file_range
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 05a2c0567dae..942aca26f9c4 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -386,3 +386,5 @@ EXPORT(sysn32_call_table)
PTR sys_pselect6
PTR sys_ppoll /* 6265 */
PTR sys_unshare
+ PTR sys_splice
+ PTR sys_sync_file_range
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 19c4ca481b02..b53a9207f530 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -508,4 +508,6 @@ sys_call_table:
PTR sys_pselect6
PTR sys_ppoll
PTR sys_unshare
+ PTR sys_splice
+ PTR sys32_sync_file_range /* 4305 */
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index dcbfd27071f0..bcf1b10e518f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -529,7 +529,10 @@ void __init setup_arch(char **cmdline_p)
int __init fpu_disable(char *s)
{
- cpu_data[0].options &= ~MIPS_CPU_FPU;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++)
+ cpu_data[i].options &= ~MIPS_CPU_FPU;
return 1;
}
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp-mt.c
index 993b8bf56aaf..57770902b9ae 100644
--- a/arch/mips/kernel/smp_mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -1,8 +1,4 @@
/*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
- *
- * Elizabeth Clarke (beth@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.
@@ -16,6 +12,10 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
+ * Copyright (C) 2004, 05, 06 MIPS Technologies, Inc.
+ * Elizabeth Clarke (beth@mips.com)
+ * Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
*/
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -24,6 +24,7 @@
#include <linux/compiler.h>
#include <asm/atomic.h>
+#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -33,8 +34,8 @@
#include <asm/time.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
-#include <asm/cacheflush.h>
-#include <asm/mips-boards/maltaint.h>
+#include <asm/mips_mt.h>
+#include <asm/mips-boards/maltaint.h> /* This is f*cking wrong */
#define MIPS_CPU_IPI_RESCHED_IRQ 0
#define MIPS_CPU_IPI_CALL_IRQ 1
@@ -66,6 +67,7 @@ void __init sanitize_tlb_entries(void)
if (!cpu_has_mipsmt)
return;
+ /* Enable VPC */
set_c0_mvpcontrol(MVPCONTROL_VPC);
back_to_back_c0_hazard();
@@ -106,12 +108,12 @@ void __init sanitize_tlb_entries(void)
static void ipi_resched_dispatch (struct pt_regs *regs)
{
- do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs);
+ do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ, regs);
}
static void ipi_call_dispatch (struct pt_regs *regs)
{
- do_IRQ(MIPS_CPU_IPI_CALL_IRQ, regs);
+ do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ, regs);
}
irqreturn_t ipi_resched_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -148,6 +150,11 @@ void plat_smp_setup(void)
unsigned long val;
int i, num;
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* If we have an FPU, enroll ourselves in the FPU-full mask */
+ if (cpu_has_fpu)
+ cpu_set(0, mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
if (!cpu_has_mipsmt)
return;
@@ -155,6 +162,8 @@ void plat_smp_setup(void)
dvpe();
dmt();
+ mips_mt_set_cpuoptions();
+
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -189,11 +198,13 @@ void plat_smp_setup(void)
if (i != 0) {
write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
- write_vpe_c0_cause(read_vpe_c0_cause() & ~CAUSEF_IP);
/* set config to be the same as vpe0, particularly kseg0 coherency alg */
write_vpe_c0_config( read_c0_config());
+ /* make sure there are no software interrupts pending */
+ write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+
/* Propagate Config7 */
write_vpe_c0_config7(read_c0_config7());
}
@@ -233,16 +244,16 @@ void plat_smp_setup(void)
/* We'll wait until starting the secondaries before starting MVPE */
printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+}
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
/* set up ipi interrupts */
if (cpu_has_vint) {
set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
}
-}
-void __init plat_prepare_cpus(unsigned int max_cpus)
-{
cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
@@ -287,7 +298,8 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
/* global pointer */
write_tc_gpr_gp((unsigned long)gp);
- flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1));
+ flush_icache_range((unsigned long)gp,
+ (unsigned long)(gp + sizeof(struct thread_info)));
/* finally out of configuration and into chaos */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -305,6 +317,12 @@ void prom_smp_finish(void)
{
write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* If we have an FPU, enroll ourselves in the FPU-full mask */
+ if (cpu_has_fpu)
+ cpu_set(smp_processor_id(), mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
local_irq_enable();
}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 78d171bfa331..d42f358754ad 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -38,6 +38,10 @@
#include <asm/mmu_context.h>
#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
cpumask_t phys_cpu_present_map; /* Bitmask of available CPUs */
volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */
@@ -85,6 +89,10 @@ asmlinkage void start_secondary(void)
{
unsigned int cpu;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Only do cpu_probe for first TC of CPU */
+ if ((read_c0_tcbind() & TCBIND_CURTC) == 0)
+#endif /* CONFIG_MIPS_MT_SMTC */
cpu_probe();
cpu_report();
per_cpu_trap_init();
@@ -179,11 +187,13 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,
if (wait)
while (atomic_read(&data.finished) != cpus)
barrier();
+ call_data = NULL;
spin_unlock(&smp_call_lock);
return 0;
}
+
void smp_call_function_interrupt(void)
{
void (*func) (void *info) = call_data->func;
@@ -446,5 +456,3 @@ subsys_initcall(topology_init);
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL(flush_tlb_one);
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(synchronize_irq);
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
new file mode 100644
index 000000000000..c9d65196d917
--- /dev/null
+++ b/arch/mips/kernel/smtc-asm.S
@@ -0,0 +1,130 @@
+/*
+ * Assembly Language Functions for MIPS MT SMTC support
+ */
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
+
+#include <asm/regdef.h>
+#include <asm/asmmacro.h>
+#include <asm/stackframe.h>
+#include <asm/stackframe.h>
+
+/*
+ * "Software Interrupt" linkage.
+ *
+ * This is invoked when an "Interrupt" is sent from one TC to another,
+ * where the TC to be interrupted is halted, has it's Restart address
+ * and Status values saved by the "remote control" thread, then modified
+ * to cause execution to begin here, in kenel mode. This code then
+ * disguises the TC state as that of an exception and transfers
+ * control to the general exception or vectored interrupt handler.
+ */
+ .set noreorder
+
+/*
+The __smtc_ipi_vector would use k0 and k1 as temporaries and
+1) Set EXL (this is per-VPE, so this can't be done by proxy!)
+2) Restore the K/CU and IXMT bits to the pre "exception" state
+ (EXL means no interrupts and access to the kernel map).
+3) Set EPC to be the saved value of TCRestart.
+4) Jump to the exception handler entry point passed by the sender.
+
+CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
+*/
+
+/*
+ * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
+ * state of pre-halt thread, then save everything and call
+ * thought some function pointer to imaginary_exception, which
+ * will parse a register value or memory message queue to
+ * deliver things like interprocessor interrupts. On return
+ * from that function, jump to the global ret_from_irq code
+ * to invoke the scheduler and return as appropriate.
+ */
+
+#define PT_PADSLOT4 (PT_R0-8)
+#define PT_PADSLOT5 (PT_R0-4)
+
+ .text
+ .align 5
+FEXPORT(__smtc_ipi_vector)
+ .set noat
+ /* Disable thread scheduling to make Status update atomic */
+ DMT 27 # dmt k1
+ ehb
+ /* Set EXL */
+ mfc0 k0,CP0_STATUS
+ ori k0,k0,ST0_EXL
+ mtc0 k0,CP0_STATUS
+ ehb
+ /* Thread scheduling now inhibited by EXL. Restore TE state. */
+ andi k1,k1,VPECONTROL_TE
+ beqz k1,1f
+ emt
+1:
+ /*
+ * The IPI sender has put some information on the anticipated
+ * kernel stack frame. If we were in user mode, this will be
+ * built above the saved kernel SP. If we were already in the
+ * kernel, it will be built above the current CPU SP.
+ *
+ * Were we in kernel mode, as indicated by CU0?
+ */
+ sll k1,k0,3
+ .set noreorder
+ bltz k1,2f
+ move k1,sp
+ .set reorder
+ /*
+ * If previously in user mode, set CU0 and use kernel stack.
+ */
+ li k1,ST0_CU0
+ or k1,k1,k0
+ mtc0 k1,CP0_STATUS
+ ehb
+ get_saved_sp
+ /* Interrupting TC will have pre-set values in slots in the new frame */
+2: subu k1,k1,PT_SIZE
+ /* Load TCStatus Value */
+ lw k0,PT_TCSTATUS(k1)
+ /* Write it to TCStatus to restore CU/KSU/IXMT state */
+ mtc0 k0,$2,1
+ ehb
+ lw k0,PT_EPC(k1)
+ mtc0 k0,CP0_EPC
+ /* Save all will redundantly recompute the SP, but use it for now */
+ SAVE_ALL
+ CLI
+ move a0,sp
+ /* Function to be invoked passed stack pad slot 5 */
+ lw t0,PT_PADSLOT5(sp)
+ /* Argument from sender passed in stack pad slot 4 */
+ lw a1,PT_PADSLOT4(sp)
+ jalr t0
+ nop
+ j ret_from_irq
+ nop
+
+/*
+ * Called from idle loop to provoke processing of queued IPIs
+ * First IPI message in queue passed as argument.
+ */
+
+LEAF(self_ipi)
+ /* Before anything else, block interrupts */
+ mfc0 t0,CP0_TCSTATUS
+ ori t1,t0,TCSTATUS_IXMT
+ mtc0 t1,CP0_TCSTATUS
+ ehb
+ /* We know we're in kernel mode, so prepare stack frame */
+ subu t1,sp,PT_SIZE
+ sw ra,PT_EPC(t1)
+ sw a0,PT_PADSLOT4(t1)
+ la t2,ipi_decode
+ sw t2,PT_PADSLOT5(t1)
+ /* Save pre-disable value of TCStatus */
+ sw t0,PT_TCSTATUS(t1)
+ j __smtc_ipi_vector
+ nop
+END(self_ipi)
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
new file mode 100644
index 000000000000..6f3709996172
--- /dev/null
+++ b/arch/mips/kernel/smtc-proc.c
@@ -0,0 +1,93 @@
+/*
+ * /proc hooks for SMTC kernel
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <linux/proc_fs.h>
+
+#include <asm/smtc_proc.h>
+
+/*
+ * /proc diagnostic and statistics hooks
+ */
+
+/*
+ * Statistics gathered
+ */
+unsigned long selfipis[NR_CPUS];
+
+struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+static struct proc_dir_entry *smtc_stats;
+
+atomic_t smtc_fpu_recoveries;
+
+static int proc_read_smtc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int totalen = 0;
+ int len;
+ int i;
+ extern unsigned long ebase;
+
+ len = sprintf(page, "SMTC Status Word: 0x%08x\n", smtc_status);
+ totalen += len;
+ page += len;
+ len = sprintf(page, "Config7: 0x%08x\n", read_c0_config7());
+ totalen += len;
+ page += len;
+ len = sprintf(page, "EBASE: 0x%08lx\n", ebase);
+ totalen += len;
+ page += len;
+ len = sprintf(page, "Counter Interrupts taken per CPU (TC)\n");
+ totalen += len;
+ page += len;
+ for (i=0; i < NR_CPUS; i++) {
+ len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+ totalen += len;
+ page += len;
+ }
+ len = sprintf(page, "Self-IPIs by CPU:\n");
+ totalen += len;
+ page += len;
+ for(i = 0; i < NR_CPUS; i++) {
+ len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+ totalen += len;
+ page += len;
+ }
+ len = sprintf(page, "%d Recoveries of \"stolen\" FPU\n",
+ atomic_read(&smtc_fpu_recoveries));
+ totalen += len;
+ page += len;
+
+ return totalen;
+}
+
+void init_smtc_stats(void)
+{
+ int i;
+
+ for (i=0; i<NR_CPUS; i++) {
+ smtc_cpu_stats[i].timerints = 0;
+ smtc_cpu_stats[i].selfipis = 0;
+ }
+
+ atomic_set(&smtc_fpu_recoveries, 0);
+
+ smtc_stats = create_proc_read_entry("smtc", 0444, NULL,
+ proc_read_smtc, NULL);
+}
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
new file mode 100644
index 000000000000..2e8e52c135e6
--- /dev/null
+++ b/arch/mips/kernel/smtc.c
@@ -0,0 +1,1322 @@
+/* Copyright (C) 2004 Mips Technologies, Inc */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/hazards.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/smtc.h>
+#include <asm/smtc_ipi.h>
+#include <asm/smtc_proc.h>
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
+ */
+
+/*
+ * MIPSCPU_INT_BASE is identically defined in both
+ * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h,
+ * but as yet there's no properly organized include structure that
+ * will ensure that the right *int.h file will be included for a
+ * given platform build.
+ */
+
+#define MIPSCPU_INT_BASE 16
+
+#define MIPS_CPU_IPI_IRQ 1
+
+#define LOCK_MT_PRA() \
+ local_irq_save(flags); \
+ mtflags = dmt()
+
+#define UNLOCK_MT_PRA() \
+ emt(mtflags); \
+ local_irq_restore(flags)
+
+#define LOCK_CORE_PRA() \
+ local_irq_save(flags); \
+ mtflags = dvpe()
+
+#define UNLOCK_CORE_PRA() \
+ evpe(mtflags); \
+ local_irq_restore(flags)
+
+/*
+ * Data structures purely associated with SMTC parallelism
+ */
+
+
+/*
+ * Table for tracking ASIDs whose lifetime is prolonged.
+ */
+
+asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+/*
+ * Clock interrupt "latch" buffers, per "CPU"
+ */
+
+unsigned int ipi_timer_latch[NR_CPUS];
+
+/*
+ * Number of InterProcessor Interupt (IPI) message buffers to allocate
+ */
+
+#define IPIBUF_PER_CPU 4
+
+struct smtc_ipi_q IPIQ[NR_CPUS];
+struct smtc_ipi_q freeIPIq;
+
+
+/* Forward declarations */
+
+void ipi_decode(struct pt_regs *, struct smtc_ipi *);
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
+void setup_cross_vpe_interrupts(void);
+void init_smtc_stats(void);
+
+/* Global SMTC Status */
+
+unsigned int smtc_status = 0;
+
+/* Boot command line configuration overrides */
+
+static int vpelimit = 0;
+static int tclimit = 0;
+static int ipibuffers = 0;
+static int nostlb = 0;
+static int asidmask = 0;
+unsigned long smtc_asid_mask = 0xff;
+
+static int __init maxvpes(char *str)
+{
+ get_option(&str, &vpelimit);
+ return 1;
+}
+
+static int __init maxtcs(char *str)
+{
+ get_option(&str, &tclimit);
+ return 1;
+}
+
+static int __init ipibufs(char *str)
+{
+ get_option(&str, &ipibuffers);
+ return 1;
+}
+
+static int __init stlb_disable(char *s)
+{
+ nostlb = 1;
+ return 1;
+}
+
+static int __init asidmask_set(char *str)
+{
+ get_option(&str, &asidmask);
+ switch(asidmask) {
+ case 0x1:
+ case 0x3:
+ case 0x7:
+ case 0xf:
+ case 0x1f:
+ case 0x3f:
+ case 0x7f:
+ case 0xff:
+ smtc_asid_mask = (unsigned long)asidmask;
+ break;
+ default:
+ printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask);
+ }
+ return 1;
+}
+
+__setup("maxvpes=", maxvpes);
+__setup("maxtcs=", maxtcs);
+__setup("ipibufs=", ipibufs);
+__setup("nostlb", stlb_disable);
+__setup("asidmask=", asidmask_set);
+
+/* Enable additional debug checks before going into CPU idle loop */
+#define SMTC_IDLE_HOOK_DEBUG
+
+#ifdef SMTC_IDLE_HOOK_DEBUG
+
+static int hang_trig = 0;
+
+static int __init hangtrig_enable(char *s)
+{
+ hang_trig = 1;
+ return 1;
+}
+
+
+__setup("hangtrig", hangtrig_enable);
+
+#define DEFAULT_BLOCKED_IPI_LIMIT 32
+
+static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT;
+
+static int __init tintq(char *str)
+{
+ get_option(&str, &timerq_limit);
+ return 1;
+}
+
+__setup("tintq=", tintq);
+
+int imstuckcount[2][8];
+/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
+int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}};
+int tcnoprog[NR_CPUS];
+static atomic_t idle_hook_initialized = {0};
+static int clock_hang_reported[NR_CPUS];
+
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
+
+void __init sanitize_tlb_entries(void)
+{
+ printk("Deprecated sanitize_tlb_entries() invoked\n");
+}
+
+
+/*
+ * Configure shared TLB - VPC configuration bit must be set by caller
+ */
+
+void smtc_configure_tlb(void)
+{
+ int i,tlbsiz,vpes;
+ unsigned long mvpconf0;
+ unsigned long config1val;
+
+ /* Set up ASID preservation table */
+ for (vpes=0; vpes<MAX_SMTC_TLBS; vpes++) {
+ for(i = 0; i < MAX_SMTC_ASIDS; i++) {
+ smtc_live_asid[vpes][i] = 0;
+ }
+ }
+ mvpconf0 = read_c0_mvpconf0();
+
+ if ((vpes = ((mvpconf0 & MVPCONF0_PVPE)
+ >> MVPCONF0_PVPE_SHIFT) + 1) > 1) {
+ /* If we have multiple VPEs, try to share the TLB */
+ if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) {
+ /*
+ * If TLB sizing is programmable, shared TLB
+ * size is the total available complement.
+ * Otherwise, we have to take the sum of all
+ * static VPE TLB entries.
+ */
+ if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE)
+ >> MVPCONF0_PTLBE_SHIFT)) == 0) {
+ /*
+ * If there's more than one VPE, there had better
+ * be more than one TC, because we need one to bind
+ * to each VPE in turn to be able to read
+ * its configuration state!
+ */
+ settc(1);
+ /* Stop the TC from doing anything foolish */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ /* No need to un-Halt - that happens later anyway */
+ for (i=0; i < vpes; i++) {
+ write_tc_c0_tcbind(i);
+ /*
+ * To be 100% sure we're really getting the right
+ * information, we exit the configuration state
+ * and do an IHB after each rebinding.
+ */
+ write_c0_mvpcontrol(
+ read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+ mips_ihb();
+ /*
+ * Only count if the MMU Type indicated is TLB
+ */
+ if(((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
+ config1val = read_vpe_c0_config1();
+ tlbsiz += ((config1val >> 25) & 0x3f) + 1;
+ }
+
+ /* Put core back in configuration state */
+ write_c0_mvpcontrol(
+ read_c0_mvpcontrol() | MVPCONTROL_VPC );
+ mips_ihb();
+ }
+ }
+ write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
+
+ /*
+ * Setup kernel data structures to use software total,
+ * rather than read the per-VPE Config1 value. The values
+ * for "CPU 0" gets copied to all the other CPUs as part
+ * of their initialization in smtc_cpu_setup().
+ */
+
+ tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */
+ cpu_data[0].tlbsize = tlbsiz;
+ smtc_status |= SMTC_TLB_SHARED;
+
+ printk("TLB of %d entry pairs shared by %d VPEs\n",
+ tlbsiz, vpes);
+ } else {
+ printk("WARNING: TLB Not Sharable on SMTC Boot!\n");
+ }
+ }
+}
+
+
+/*
+ * Incrementally build the CPU map out of constituent MIPS MT cores,
+ * using the specified available VPEs and TCs. Plaform code needs
+ * to ensure that each MIPS MT core invokes this routine on reset,
+ * one at a time(!).
+ *
+ * This version of the build_cpu_map and prepare_cpus routines assumes
+ * that *all* TCs of a MIPS MT core will be used for Linux, and that
+ * they will be spread across *all* available VPEs (to minimise the
+ * loss of efficiency due to exception service serialization).
+ * An improved version would pick up configuration information and
+ * possibly leave some TCs/VPEs as "slave" processors.
+ *
+ * Use c0_MVPConf0 to find out how many TCs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ */
+
+int __init mipsmt_build_cpu_map(int start_cpu_slot)
+{
+ int i, ntcs;
+
+ /*
+ * The CPU map isn't actually used for anything at this point,
+ * so it's not clear what else we should do apart from set
+ * everything up so that "logical" = "physical".
+ */
+ ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {
+ cpu_set(i, phys_cpu_present_map);
+ __cpu_number_map[i] = i;
+ __cpu_logical_map[i] = i;
+ }
+ /* Initialize map of CPUs with FPUs */
+ cpus_clear(mt_fpu_cpumask);
+
+ /* One of those TC's is the one booting, and not a secondary... */
+ printk("%i available secondary CPU TC(s)\n", i - 1);
+
+ return i;
+}
+
+/*
+ * Common setup before any secondaries are started
+ * Make sure all CPU's are in a sensible state before we boot any of the
+ * secondaries.
+ *
+ * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
+ * as possible across the available VPEs.
+ */
+
+static void smtc_tc_setup(int vpe, int tc, int cpu)
+{
+ settc(tc);
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ write_tc_c0_tcstatus((read_tc_c0_tcstatus()
+ & ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
+ | TCSTATUS_A);
+ write_tc_c0_tccontext(0);
+ /* Bind tc to vpe */
+ write_tc_c0_tcbind(vpe);
+ /* In general, all TCs should have the same cpu_data indications */
+ memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
+ /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
+ if (cpu_data[0].cputype == CPU_34K)
+ cpu_data[cpu].options &= ~MIPS_CPU_FPU;
+ cpu_data[cpu].vpe_id = vpe;
+ cpu_data[cpu].tc_id = tc;
+}
+
+
+void mipsmt_prepare_cpus(void)
+{
+ int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;
+ unsigned long flags;
+ unsigned long val;
+ int nipi;
+ struct smtc_ipi *pipi;
+
+ /* disable interrupts so we can disable MT */
+ local_irq_save(flags);
+ /* disable MT so we can configure */
+ dvpe();
+ dmt();
+
+ freeIPIq.lock = SPIN_LOCK_UNLOCKED;
+
+ /*
+ * We probably don't have as many VPEs as we do SMP "CPUs",
+ * but it's possible - and in any case we'll never use more!
+ */
+ for (i=0; i<NR_CPUS; i++) {
+ IPIQ[i].head = IPIQ[i].tail = NULL;
+ IPIQ[i].lock = SPIN_LOCK_UNLOCKED;
+ IPIQ[i].depth = 0;
+ ipi_timer_latch[i] = 0;
+ }
+
+ /* cpu_data index starts at zero */
+ cpu = 0;
+ cpu_data[cpu].vpe_id = 0;
+ cpu_data[cpu].tc_id = 0;
+ cpu++;
+
+ /* Report on boot-time options */
+ mips_mt_set_cpuoptions ();
+ if (vpelimit > 0)
+ printk("Limit of %d VPEs set\n", vpelimit);
+ if (tclimit > 0)
+ printk("Limit of %d TCs set\n", tclimit);
+ if (nostlb) {
+ printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n");
+ }
+ if (asidmask)
+ printk("ASID mask value override to 0x%x\n", asidmask);
+
+ /* Temporary */
+#ifdef SMTC_IDLE_HOOK_DEBUG
+ if (hang_trig)
+ printk("Logic Analyser Trigger on suspected TC hang\n");
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+ /* Put MVPE's into 'configuration state' */
+ write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
+
+ val = read_c0_mvpconf0();
+ nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+ if (vpelimit > 0 && nvpe > vpelimit)
+ nvpe = vpelimit;
+ ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ if (ntc > NR_CPUS)
+ ntc = NR_CPUS;
+ if (tclimit > 0 && ntc > tclimit)
+ ntc = tclimit;
+ tcpervpe = ntc / nvpe;
+ slop = ntc % nvpe; /* Residual TCs, < NVPE */
+
+ /* Set up shared TLB */
+ smtc_configure_tlb();
+
+ for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
+ /*
+ * Set the MVP bits.
+ */
+ settc(tc);
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);
+ if (vpe != 0)
+ printk(", ");
+ printk("VPE %d: TC", vpe);
+ for (i = 0; i < tcpervpe; i++) {
+ /*
+ * TC 0 is bound to VPE 0 at reset,
+ * and is presumably executing this
+ * code. Leave it alone!
+ */
+ if (tc != 0) {
+ smtc_tc_setup(vpe,tc, cpu);
+ cpu++;
+ }
+ printk(" %d", tc);
+ tc++;
+ }
+ if (slop) {
+ if (tc != 0) {
+ smtc_tc_setup(vpe,tc, cpu);
+ cpu++;
+ }
+ printk(" %d", tc);
+ tc++;
+ slop--;
+ }
+ if (vpe != 0) {
+ /*
+ * Clear any stale software interrupts from VPE's Cause
+ */
+ write_vpe_c0_cause(0);
+
+ /*
+ * Clear ERL/EXL of VPEs other than 0
+ * and set restricted interrupt enable/mask.
+ */
+ write_vpe_c0_status((read_vpe_c0_status()
+ & ~(ST0_BEV | ST0_ERL | ST0_EXL | ST0_IM))
+ | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7
+ | ST0_IE));
+ /*
+ * set config to be the same as vpe0,
+ * particularly kseg0 coherency alg
+ */
+ write_vpe_c0_config(read_c0_config());
+ /* Clear any pending timer interrupt */
+ write_vpe_c0_compare(0);
+ /* Propagate Config7 */
+ write_vpe_c0_config7(read_c0_config7());
+ }
+ /* enable multi-threading within VPE */
+ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
+ /* enable the VPE */
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+ }
+
+ /*
+ * Pull any physically present but unused TCs out of circulation.
+ */
+ while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) {
+ cpu_clear(tc, phys_cpu_present_map);
+ cpu_clear(tc, cpu_present_map);
+ tc++;
+ }
+
+ /* release config state */
+ write_c0_mvpcontrol( read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+
+ printk("\n");
+
+ /* Set up coprocessor affinity CPU mask(s) */
+
+ for (tc = 0; tc < ntc; tc++) {
+ if(cpu_data[tc].options & MIPS_CPU_FPU)
+ cpu_set(tc, mt_fpu_cpumask);
+ }
+
+ /* set up ipi interrupts... */
+
+ /* If we have multiple VPEs running, set up the cross-VPE interrupt */
+
+ if (nvpe > 1)
+ setup_cross_vpe_interrupts();
+
+ /* Set up queue of free IPI "messages". */
+ nipi = NR_CPUS * IPIBUF_PER_CPU;
+ if (ipibuffers > 0)
+ nipi = ipibuffers;
+
+ pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL);
+ if (pipi == NULL)
+ panic("kmalloc of IPI message buffers failed\n");
+ else
+ printk("IPI buffer pool of %d buffers\n", nipi);
+ for (i = 0; i < nipi; i++) {
+ smtc_ipi_nq(&freeIPIq, pipi);
+ pipi++;
+ }
+
+ /* Arm multithreading and enable other VPEs - but all TCs are Halted */
+ emt(EMT_ENABLE);
+ evpe(EVPE_ENABLE);
+ local_irq_restore(flags);
+ /* Initialize SMTC /proc statistics/diagnostics */
+ init_smtc_stats();
+}
+
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ * smp_bootstrap is the place to resume from
+ * __KSTK_TOS(idle) is apparently the stack pointer
+ * (unsigned long)idle->thread_info the gp
+ *
+ */
+void smtc_boot_secondary(int cpu, struct task_struct *idle)
+{
+ extern u32 kernelsp[NR_CPUS];
+ long flags;
+ int mtflags;
+
+ LOCK_MT_PRA();
+ if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ dvpe();
+ }
+ settc(cpu_data[cpu].tc_id);
+
+ /* pc */
+ write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
+
+ /* stack pointer */
+ kernelsp[cpu] = __KSTK_TOS(idle);
+ write_tc_gpr_sp(__KSTK_TOS(idle));
+
+ /* global pointer */
+ write_tc_gpr_gp((unsigned long)idle->thread_info);
+
+ smtc_status |= SMTC_MTC_ACTIVE;
+ write_tc_c0_tchalt(0);
+ if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ evpe(EVPE_ENABLE);
+ }
+ UNLOCK_MT_PRA();
+}
+
+void smtc_init_secondary(void)
+{
+ /*
+ * Start timer on secondary VPEs if necessary.
+ * mips_timer_setup should already have been invoked by init/main
+ * on "boot" TC. Like per_cpu_trap_init() hack, this assumes that
+ * SMTC init code assigns TCs consdecutively and in ascending order
+ * to across available VPEs.
+ */
+ if(((read_c0_tcbind() & TCBIND_CURTC) != 0)
+ && ((read_c0_tcbind() & TCBIND_CURVPE)
+ != cpu_data[smp_processor_id() - 1].vpe_id)){
+ write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+ }
+
+ local_irq_enable();
+}
+
+void smtc_smp_finish(void)
+{
+ printk("TC %d going on-line as CPU %d\n",
+ cpu_data[smp_processor_id()].tc_id, smp_processor_id());
+}
+
+void smtc_cpus_done(void)
+{
+}
+
+/*
+ * Support for SMTC-optimized driver IRQ registration
+ */
+
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+
+int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+ unsigned long hwmask)
+{
+ irq_hwmask[irq] = hwmask;
+
+ return setup_irq(irq, new);
+}
+
+/*
+ * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
+ * Within a VPE one TC can interrupt another by different approaches.
+ * The easiest to get right would probably be to make all TCs except
+ * the target IXMT and set a software interrupt, but an IXMT-based
+ * scheme requires that a handler must run before a new IPI could
+ * be sent, which would break the "broadcast" loops in MIPS MT.
+ * A more gonzo approach within a VPE is to halt the TC, extract
+ * its Restart, Status, and a couple of GPRs, and program the Restart
+ * address to emulate an interrupt.
+ *
+ * Within a VPE, one can be confident that the target TC isn't in
+ * a critical EXL state when halted, since the write to the Halt
+ * register could not have issued on the writing thread if the
+ * halting thread had EXL set. So k0 and k1 of the target TC
+ * can be used by the injection code. Across VPEs, one can't
+ * be certain that the target TC isn't in a critical exception
+ * state. So we try a two-step process of sending a software
+ * interrupt to the target VPE, which either handles the event
+ * itself (if it was the target) or injects the event within
+ * the VPE.
+ */
+
+void smtc_ipi_qdump(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS ;i++) {
+ printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
+ i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
+ IPIQ[i].depth);
+ }
+}
+
+/*
+ * The standard atomic.h primitives don't quite do what we want
+ * here: We need an atomic add-and-return-previous-value (which
+ * could be done with atomic_add_return and a decrement) and an
+ * atomic set/zero-and-return-previous-value (which can't really
+ * be done with the atomic.h primitives). And since this is
+ * MIPS MT, we can assume that we have LL/SC.
+ */
+static __inline__ int atomic_postincrement(unsigned int *pv)
+{
+ unsigned long result;
+
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ll %0, %2 \n"
+ " addu %1, %0, 1 \n"
+ " sc %1, %2 \n"
+ " beqz %1, 1b \n"
+ " sync \n"
+ : "=&r" (result), "=&r" (temp), "=m" (*pv)
+ : "m" (*pv)
+ : "memory");
+
+ return result;
+}
+
+/* No longer used in IPI dispatch, but retained for future recycling */
+
+static __inline__ int atomic_postclear(unsigned int *pv)
+{
+ unsigned long result;
+
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ll %0, %2 \n"
+ " or %1, $0, $0 \n"
+ " sc %1, %2 \n"
+ " beqz %1, 1b \n"
+ " sync \n"
+ : "=&r" (result), "=&r" (temp), "=m" (*pv)
+ : "m" (*pv)
+ : "memory");
+
+ return result;
+}
+
+
+void smtc_send_ipi(int cpu, int type, unsigned int action)
+{
+ int tcstatus;
+ struct smtc_ipi *pipi;
+ long flags;
+ int mtflags;
+
+ if (cpu == smp_processor_id()) {
+ printk("Cannot Send IPI to self!\n");
+ return;
+ }
+ /* Set up a descriptor, to be delivered either promptly or queued */
+ pipi = smtc_ipi_dq(&freeIPIq);
+ if (pipi == NULL) {
+ bust_spinlocks(1);
+ mips_mt_regdump(dvpe());
+ panic("IPI Msg. Buffers Depleted\n");
+ }
+ pipi->type = type;
+ pipi->arg = (void *)action;
+ pipi->dest = cpu;
+ if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ /* If not on same VPE, enqueue and send cross-VPE interupt */
+ smtc_ipi_nq(&IPIQ[cpu], pipi);
+ LOCK_CORE_PRA();
+ settc(cpu_data[cpu].tc_id);
+ write_vpe_c0_cause(read_vpe_c0_cause() | C_SW1);
+ UNLOCK_CORE_PRA();
+ } else {
+ /*
+ * Not sufficient to do a LOCK_MT_PRA (dmt) here,
+ * since ASID shootdown on the other VPE may
+ * collide with this operation.
+ */
+ LOCK_CORE_PRA();
+ settc(cpu_data[cpu].tc_id);
+ /* Halt the targeted TC */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
+ /*
+ * Inspect TCStatus - if IXMT is set, we have to queue
+ * a message. Otherwise, we set up the "interrupt"
+ * of the other TC
+ */
+ tcstatus = read_tc_c0_tcstatus();
+
+ if ((tcstatus & TCSTATUS_IXMT) != 0) {
+ /*
+ * Spin-waiting here can deadlock,
+ * so we queue the message for the target TC.
+ */
+ write_tc_c0_tchalt(0);
+ UNLOCK_CORE_PRA();
+ /* Try to reduce redundant timer interrupt messages */
+ if(type == SMTC_CLOCK_TICK) {
+ if(atomic_postincrement(&ipi_timer_latch[cpu])!=0) {
+ smtc_ipi_nq(&freeIPIq, pipi);
+ return;
+ }
+ }
+ smtc_ipi_nq(&IPIQ[cpu], pipi);
+ } else {
+ post_direct_ipi(cpu, pipi);
+ write_tc_c0_tchalt(0);
+ UNLOCK_CORE_PRA();
+ }
+ }
+}
+
+/*
+ * Send IPI message to Halted TC, TargTC/TargVPE already having been set
+ */
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
+{
+ struct pt_regs *kstack;
+ unsigned long tcstatus;
+ unsigned long tcrestart;
+ extern u32 kernelsp[NR_CPUS];
+ extern void __smtc_ipi_vector(void);
+
+ /* Extract Status, EPC from halted TC */
+ tcstatus = read_tc_c0_tcstatus();
+ tcrestart = read_tc_c0_tcrestart();
+ /* If TCRestart indicates a WAIT instruction, advance the PC */
+ if ((tcrestart & 0x80000000)
+ && ((*(unsigned int *)tcrestart & 0xfe00003f) == 0x42000020)) {
+ tcrestart += 4;
+ }
+ /*
+ * Save on TC's future kernel stack
+ *
+ * CU bit of Status is indicator that TC was
+ * already running on a kernel stack...
+ */
+ if(tcstatus & ST0_CU0) {
+ /* Note that this "- 1" is pointer arithmetic */
+ kstack = ((struct pt_regs *)read_tc_gpr_sp()) - 1;
+ } else {
+ kstack = ((struct pt_regs *)kernelsp[cpu]) - 1;
+ }
+
+ kstack->cp0_epc = (long)tcrestart;
+ /* Save TCStatus */
+ kstack->cp0_tcstatus = tcstatus;
+ /* Pass token of operation to be performed kernel stack pad area */
+ kstack->pad0[4] = (unsigned long)pipi;
+ /* Pass address of function to be called likewise */
+ kstack->pad0[5] = (unsigned long)&ipi_decode;
+ /* Set interrupt exempt and kernel mode */
+ tcstatus |= TCSTATUS_IXMT;
+ tcstatus &= ~TCSTATUS_TKSU;
+ write_tc_c0_tcstatus(tcstatus);
+ ehb();
+ /* Set TC Restart address to be SMTC IPI vector */
+ write_tc_c0_tcrestart(__smtc_ipi_vector);
+}
+
+void ipi_resched_interrupt(struct pt_regs *regs)
+{
+ /* Return from interrupt should be enough to cause scheduler check */
+}
+
+
+void ipi_call_interrupt(struct pt_regs *regs)
+{
+ /* Invoke generic function invocation code in smp.c */
+ smp_call_function_interrupt();
+}
+
+void ipi_decode(struct pt_regs *regs, struct smtc_ipi *pipi)
+{
+ void *arg_copy = pipi->arg;
+ int type_copy = pipi->type;
+ int dest_copy = pipi->dest;
+
+ smtc_ipi_nq(&freeIPIq, pipi);
+ switch (type_copy) {
+ case SMTC_CLOCK_TICK:
+ /* Invoke Clock "Interrupt" */
+ ipi_timer_latch[dest_copy] = 0;
+#ifdef SMTC_IDLE_HOOK_DEBUG
+ clock_hang_reported[dest_copy] = 0;
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+ local_timer_interrupt(0, NULL, regs);
+ break;
+ case LINUX_SMP_IPI:
+ switch ((int)arg_copy) {
+ case SMP_RESCHEDULE_YOURSELF:
+ ipi_resched_interrupt(regs);
+ break;
+ case SMP_CALL_FUNCTION:
+ ipi_call_interrupt(regs);
+ break;
+ default:
+ printk("Impossible SMTC IPI Argument 0x%x\n",
+ (int)arg_copy);
+ break;
+ }
+ break;
+ default:
+ printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
+ break;
+ }
+}
+
+void deferred_smtc_ipi(struct pt_regs *regs)
+{
+ struct smtc_ipi *pipi;
+ unsigned long flags;
+/* DEBUG */
+ int q = smp_processor_id();
+
+ /*
+ * Test is not atomic, but much faster than a dequeue,
+ * and the vast majority of invocations will have a null queue.
+ */
+ if(IPIQ[q].head != NULL) {
+ while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
+ /* ipi_decode() should be called with interrupts off */
+ local_irq_save(flags);
+ ipi_decode(regs, pipi);
+ local_irq_restore(flags);
+ }
+ }
+}
+
+/*
+ * Send clock tick to all TCs except the one executing the funtion
+ */
+
+void smtc_timer_broadcast(int vpe)
+{
+ int cpu;
+ int myTC = cpu_data[smp_processor_id()].tc_id;
+ int myVPE = cpu_data[smp_processor_id()].vpe_id;
+
+ smtc_cpu_stats[smp_processor_id()].timerints++;
+
+ for_each_online_cpu(cpu) {
+ if (cpu_data[cpu].vpe_id == myVPE &&
+ cpu_data[cpu].tc_id != myTC)
+ smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+ }
+}
+
+/*
+ * Cross-VPE interrupts in the SMTC prototype use "software interrupts"
+ * set via cross-VPE MTTR manipulation of the Cause register. It would be
+ * in some regards preferable to have external logic for "doorbell" hardware
+ * interrupts.
+ */
+
+static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
+
+static irqreturn_t ipi_interrupt(int irq, void *dev_idm, struct pt_regs *regs)
+{
+ int my_vpe = cpu_data[smp_processor_id()].vpe_id;
+ int my_tc = cpu_data[smp_processor_id()].tc_id;
+ int cpu;
+ struct smtc_ipi *pipi;
+ unsigned long tcstatus;
+ int sent;
+ long flags;
+ unsigned int mtflags;
+ unsigned int vpflags;
+
+ /*
+ * So long as cross-VPE interrupts are done via
+ * MFTR/MTTR read-modify-writes of Cause, we need
+ * to stop other VPEs whenever the local VPE does
+ * anything similar.
+ */
+ local_irq_save(flags);
+ vpflags = dvpe();
+ clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ);
+ set_c0_status(0x100 << MIPS_CPU_IPI_IRQ);
+ irq_enable_hazard();
+ evpe(vpflags);
+ local_irq_restore(flags);
+
+ /*
+ * Cross-VPE Interrupt handler: Try to directly deliver IPIs
+ * queued for TCs on this VPE other than the current one.
+ * Return-from-interrupt should cause us to drain the queue
+ * for the current TC, so we ought not to have to do it explicitly here.
+ */
+
+ for_each_online_cpu(cpu) {
+ if (cpu_data[cpu].vpe_id != my_vpe)
+ continue;
+
+ pipi = smtc_ipi_dq(&IPIQ[cpu]);
+ if (pipi != NULL) {
+ if (cpu_data[cpu].tc_id != my_tc) {
+ sent = 0;
+ LOCK_MT_PRA();
+ settc(cpu_data[cpu].tc_id);
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ tcstatus = read_tc_c0_tcstatus();
+ if ((tcstatus & TCSTATUS_IXMT) == 0) {
+ post_direct_ipi(cpu, pipi);
+ sent = 1;
+ }
+ write_tc_c0_tchalt(0);
+ UNLOCK_MT_PRA();
+ if (!sent) {
+ smtc_ipi_req(&IPIQ[cpu], pipi);
+ }
+ } else {
+ /*
+ * ipi_decode() should be called
+ * with interrupts off
+ */
+ local_irq_save(flags);
+ ipi_decode(regs, pipi);
+ local_irq_restore(flags);
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void ipi_irq_dispatch(struct pt_regs *regs)
+{
+ do_IRQ(cpu_ipi_irq, regs);
+}
+
+static struct irqaction irq_ipi;
+
+void setup_cross_vpe_interrupts(void)
+{
+ if (!cpu_has_vint)
+ panic("SMTC Kernel requires Vectored Interupt support");
+
+ set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
+
+ irq_ipi.handler = ipi_interrupt;
+ irq_ipi.flags = SA_INTERRUPT;
+ irq_ipi.name = "SMTC_IPI";
+
+ setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
+
+ irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
+}
+
+/*
+ * SMTC-specific hacks invoked from elsewhere in the kernel.
+ */
+
+void smtc_idle_loop_hook(void)
+{
+#ifdef SMTC_IDLE_HOOK_DEBUG
+ int im;
+ int flags;
+ int mtflags;
+ int bit;
+ int vpe;
+ int tc;
+ int hook_ntcs;
+ /*
+ * printk within DMT-protected regions can deadlock,
+ * so buffer diagnostic messages for later output.
+ */
+ char *pdb_msg;
+ char id_ho_db_msg[768]; /* worst-case use should be less than 700 */
+
+ if (atomic_read(&idle_hook_initialized) == 0) { /* fast test */
+ if (atomic_add_return(1, &idle_hook_initialized) == 1) {
+ int mvpconf0;
+ /* Tedious stuff to just do once */
+ mvpconf0 = read_c0_mvpconf0();
+ hook_ntcs = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ if (hook_ntcs > NR_CPUS)
+ hook_ntcs = NR_CPUS;
+ for (tc = 0; tc < hook_ntcs; tc++) {
+ tcnoprog[tc] = 0;
+ clock_hang_reported[tc] = 0;
+ }
+ for (vpe = 0; vpe < 2; vpe++)
+ for (im = 0; im < 8; im++)
+ imstuckcount[vpe][im] = 0;
+ printk("Idle loop test hook initialized for %d TCs\n", hook_ntcs);
+ atomic_set(&idle_hook_initialized, 1000);
+ } else {
+ /* Someone else is initializing in parallel - let 'em finish */
+ while (atomic_read(&idle_hook_initialized) < 1000)
+ ;
+ }
+ }
+
+ /* Have we stupidly left IXMT set somewhere? */
+ if (read_c0_tcstatus() & 0x400) {
+ write_c0_tcstatus(read_c0_tcstatus() & ~0x400);
+ ehb();
+ printk("Dangling IXMT in cpu_idle()\n");
+ }
+
+ /* Have we stupidly left an IM bit turned off? */
+#define IM_LIMIT 2000
+ local_irq_save(flags);
+ mtflags = dmt();
+ pdb_msg = &id_ho_db_msg[0];
+ im = read_c0_status();
+ vpe = cpu_data[smp_processor_id()].vpe_id;
+ for (bit = 0; bit < 8; bit++) {
+ /*
+ * In current prototype, I/O interrupts
+ * are masked for VPE > 0
+ */
+ if (vpemask[vpe][bit]) {
+ if (!(im & (0x100 << bit)))
+ imstuckcount[vpe][bit]++;
+ else
+ imstuckcount[vpe][bit] = 0;
+ if (imstuckcount[vpe][bit] > IM_LIMIT) {
+ set_c0_status(0x100 << bit);
+ ehb();
+ imstuckcount[vpe][bit] = 0;
+ pdb_msg += sprintf(pdb_msg,
+ "Dangling IM %d fixed for VPE %d\n", bit,
+ vpe);
+ }
+ }
+ }
+
+ /*
+ * Now that we limit outstanding timer IPIs, check for hung TC
+ */
+ for (tc = 0; tc < NR_CPUS; tc++) {
+ /* Don't check ourself - we'll dequeue IPIs just below */
+ if ((tc != smp_processor_id()) &&
+ ipi_timer_latch[tc] > timerq_limit) {
+ if (clock_hang_reported[tc] == 0) {
+ pdb_msg += sprintf(pdb_msg,
+ "TC %d looks hung with timer latch at %d\n",
+ tc, ipi_timer_latch[tc]);
+ clock_hang_reported[tc]++;
+ }
+ }
+ }
+ emt(mtflags);
+ local_irq_restore(flags);
+ if (pdb_msg != &id_ho_db_msg[0])
+ printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+ /*
+ * To the extent that we've ever turned interrupts off,
+ * we may have accumulated deferred IPIs. This is subtle.
+ * If we use the smtc_ipi_qdepth() macro, we'll get an
+ * exact number - but we'll also disable interrupts
+ * and create a window of failure where a new IPI gets
+ * queued after we test the depth but before we re-enable
+ * interrupts. So long as IXMT never gets set, however,
+ * we should be OK: If we pick up something and dispatch
+ * it here, that's great. If we see nothing, but concurrent
+ * with this operation, another TC sends us an IPI, IXMT
+ * is clear, and we'll handle it as a real pseudo-interrupt
+ * and not a pseudo-pseudo interrupt.
+ */
+ if (IPIQ[smp_processor_id()].depth > 0) {
+ struct smtc_ipi *pipi;
+ extern void self_ipi(struct smtc_ipi *);
+
+ if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
+ self_ipi(pipi);
+ smtc_cpu_stats[smp_processor_id()].selfipis++;
+ }
+ }
+}
+
+void smtc_soft_dump(void)
+{
+ int i;
+
+ printk("Counter Interrupts taken per CPU (TC)\n");
+ for (i=0; i < NR_CPUS; i++) {
+ printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+ }
+ printk("Self-IPI invocations:\n");
+ for (i=0; i < NR_CPUS; i++) {
+ printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+ }
+ smtc_ipi_qdump();
+ printk("Timer IPI Backlogs:\n");
+ for (i=0; i < NR_CPUS; i++) {
+ printk("%d: %d\n", i, ipi_timer_latch[i]);
+ }
+ printk("%d Recoveries of \"stolen\" FPU\n",
+ atomic_read(&smtc_fpu_recoveries));
+}
+
+
+/*
+ * TLB management routines special to SMTC
+ */
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
+{
+ unsigned long flags, mtflags, tcstat, prevhalt, asid;
+ int tlb, i;
+
+ /*
+ * It would be nice to be able to use a spinlock here,
+ * but this is invoked from within TLB flush routines
+ * that protect themselves with DVPE, so if a lock is
+ * held by another TC, it'll never be freed.
+ *
+ * DVPE/DMT must not be done with interrupts enabled,
+ * so even so most callers will already have disabled
+ * them, let's be really careful...
+ */
+
+ local_irq_save(flags);
+ if (smtc_status & SMTC_TLB_SHARED) {
+ mtflags = dvpe();
+ tlb = 0;
+ } else {
+ mtflags = dmt();
+ tlb = cpu_data[cpu].vpe_id;
+ }
+ asid = asid_cache(cpu);
+
+ do {
+ if (!((asid += ASID_INC) & ASID_MASK) ) {
+ if (cpu_has_vtag_icache)
+ flush_icache_all();
+ /* Traverse all online CPUs (hack requires contigous range) */
+ for (i = 0; i < num_online_cpus(); i++) {
+ /*
+ * We don't need to worry about our own CPU, nor those of
+ * CPUs who don't share our TLB.
+ */
+ if ((i != smp_processor_id()) &&
+ ((smtc_status & SMTC_TLB_SHARED) ||
+ (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))) {
+ settc(cpu_data[i].tc_id);
+ prevhalt = read_tc_c0_tchalt() & TCHALT_H;
+ if (!prevhalt) {
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ }
+ tcstat = read_tc_c0_tcstatus();
+ smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
+ if (!prevhalt)
+ write_tc_c0_tchalt(0);
+ }
+ }
+ if (!asid) /* fix version if needed */
+ asid = ASID_FIRST_VERSION;
+ local_flush_tlb_all(); /* start new asid cycle */
+ }
+ } while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
+
+ /*
+ * SMTC shares the TLB within VPEs and possibly across all VPEs.
+ */
+ for (i = 0; i < num_online_cpus(); i++) {
+ if ((smtc_status & SMTC_TLB_SHARED) ||
+ (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+ cpu_context(i, mm) = asid_cache(i) = asid;
+ }
+
+ if (smtc_status & SMTC_TLB_SHARED)
+ evpe(mtflags);
+ else
+ emt(mtflags);
+ local_irq_restore(flags);
+}
+
+/*
+ * Invoked from macros defined in mmu_context.h
+ * which must already have disabled interrupts
+ * and done a DVPE or DMT as appropriate.
+ */
+
+void smtc_flush_tlb_asid(unsigned long asid)
+{
+ int entry;
+ unsigned long ehi;
+
+ entry = read_c0_wired();
+
+ /* Traverse all non-wired entries */
+ while (entry < current_cpu_data.tlbsize) {
+ write_c0_index(entry);
+ ehb();
+ tlb_read();
+ ehb();
+ ehi = read_c0_entryhi();
+ if((ehi & ASID_MASK) == asid) {
+ /*
+ * Invalidate only entries with specified ASID,
+ * makiing sure all entries differ.
+ */
+ write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ }
+ entry++;
+ }
+ write_c0_index(PARKED_INDEX);
+ tlbw_use_hazard();
+}
+
+/*
+ * Support for single-threading cache flush operations.
+ */
+
+int halt_state_save[NR_CPUS];
+
+/*
+ * To really, really be sure that nothing is being done
+ * by other TCs, halt them all. This code assumes that
+ * a DVPE has already been done, so while their Halted
+ * state is theoretically architecturally unstable, in
+ * practice, it's not going to change while we're looking
+ * at it.
+ */
+
+void smtc_cflush_lockdown(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id()) {
+ settc(cpu_data[cpu].tc_id);
+ halt_state_save[cpu] = read_tc_c0_tchalt();
+ write_tc_c0_tchalt(TCHALT_H);
+ }
+ }
+ mips_ihb();
+}
+
+/* It would be cheating to change the cpu_online states during a flush! */
+
+void smtc_cflush_release(void)
+{
+ int cpu;
+
+ /*
+ * Start with a hazard barrier to ensure
+ * that all CACHE ops have played through.
+ */
+ mips_ihb();
+
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id()) {
+ settc(cpu_data[cpu].tc_id);
+ write_tc_c0_tchalt(halt_state_save[cpu]);
+ }
+ }
+ mips_ihb();
+}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 5e51a2d8f3f0..13ff4da598cd 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -116,8 +116,7 @@ static void c0_timer_ack(void)
write_c0_compare(expirelo);
/* Check to see if we have missed any timer interrupts. */
- count = read_c0_count();
- if ((count - expirelo) < 0x7fffffff) {
+ while (((count = read_c0_count()) - expirelo) < 0x7fffffff) {
/* missed_timer_count++; */
expirelo = count + cycles_per_jiffy;
write_c0_compare(expirelo);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index bed0eb6cf55d..4901f0a37fca 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -42,6 +42,7 @@
#include <asm/watch.h>
#include <asm/types.h>
+extern asmlinkage void handle_int(void);
extern asmlinkage void handle_tlbm(void);
extern asmlinkage void handle_tlbl(void);
extern asmlinkage void handle_tlbs(void);
@@ -279,9 +280,16 @@ static DEFINE_SPINLOCK(die_lock);
NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
{
static int die_counter;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long dvpret = dvpe();
+#endif /* CONFIG_MIPS_MT_SMTC */
console_verbose();
spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+#ifdef CONFIG_MIPS_MT_SMTC
+ mips_mt_regdump(dvpret);
+#endif /* CONFIG_MIPS_MT_SMTC */
printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
spin_unlock_irq(&die_lock);
@@ -750,12 +758,43 @@ asmlinkage void do_cpu(struct pt_regs *regs)
&current->thread.fpu.soft);
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 */
}
return;
case 2:
case 3:
+ die_if_kernel("do_cpu invoked from kernel context!", regs);
break;
}
@@ -793,6 +832,36 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
asmlinkage void do_mt(struct pt_regs *regs)
{
+ int subcode;
+
+ die_if_kernel("MIPS MT Thread exception in kernel", regs);
+
+ subcode = (read_vpe_c0_vpecontrol() & VPECONTROL_EXCPT)
+ >> VPECONTROL_EXCPT_SHIFT;
+ switch (subcode) {
+ case 0:
+ printk(KERN_ERR "Thread Underflow\n");
+ break;
+ case 1:
+ printk(KERN_ERR "Thread Overflow\n");
+ break;
+ case 2:
+ printk(KERN_ERR "Invalid YIELD Qualifier\n");
+ break;
+ case 3:
+ printk(KERN_ERR "Gating Storage Exception\n");
+ break;
+ case 4:
+ printk(KERN_ERR "YIELD Scheduler Exception\n");
+ break;
+ case 5:
+ printk(KERN_ERR "Gating Storage Schedulier Exception\n");
+ break;
+ default:
+ printk(KERN_ERR "*** UNKNOWN THREAD EXCEPTION %d ***\n",
+ subcode);
+ break;
+ }
die_if_kernel("MIPS MT Thread exception in kernel", regs);
force_sig(SIGILL, current);
@@ -928,7 +997,15 @@ void ejtag_exception_handler(struct pt_regs *regs)
*/
void nmi_exception_handler(struct pt_regs *regs)
{
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long dvpret = dvpe();
+ bust_spinlocks(1);
+ printk("NMI taken!!!!\n");
+ mips_mt_regdump(dvpret);
+#else
+ bust_spinlocks(1);
printk("NMI taken!!!!\n");
+#endif /* CONFIG_MIPS_MT_SMTC */
die("NMI", regs);
while(1) ;
}
@@ -960,27 +1037,29 @@ void *set_except_vector(int n, void *addr)
#ifdef CONFIG_CPU_MIPSR2
/*
- * Shadow register allocation
+ * MIPSR2 shadow register set allocation
* FIXME: SMP...
*/
-/* MIPSR2 shadow register sets */
-struct shadow_registers {
- spinlock_t sr_lock; /* */
- int sr_supported; /* Number of shadow register sets supported */
- int sr_allocated; /* Bitmap of allocated shadow registers */
+static struct shadow_registers {
+ /*
+ * Number of shadow register sets supported
+ */
+ unsigned long sr_supported;
+ /*
+ * Bitmap of allocated shadow registers
+ */
+ unsigned long sr_allocated;
} shadow_registers;
-void mips_srs_init(void)
+static void mips_srs_init(void)
{
#ifdef CONFIG_CPU_MIPSR2_SRS
shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
- printk ("%d MIPSR2 register sets available\n", shadow_registers.sr_supported);
-#else
- shadow_registers.sr_supported = 1;
+ printk(KERN_INFO "%d MIPSR2 register sets available\n",
+ shadow_registers.sr_supported);
#endif
shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */
- spin_lock_init(&shadow_registers.sr_lock);
}
int mips_srs_max(void)
@@ -988,38 +1067,30 @@ int mips_srs_max(void)
return shadow_registers.sr_supported;
}
-int mips_srs_alloc (void)
+int mips_srs_alloc(void)
{
struct shadow_registers *sr = &shadow_registers;
- unsigned long flags;
int set;
- spin_lock_irqsave(&sr->sr_lock, flags);
+again:
+ set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported);
+ if (set >= sr->sr_supported)
+ return -1;
- for (set = 0; set < sr->sr_supported; set++) {
- if ((sr->sr_allocated & (1 << set)) == 0) {
- sr->sr_allocated |= 1 << set;
- spin_unlock_irqrestore(&sr->sr_lock, flags);
- return set;
- }
- }
+ if (test_and_set_bit(set, &sr->sr_allocated))
+ goto again;
- /* None available */
- spin_unlock_irqrestore(&sr->sr_lock, flags);
- return -1;
+ return set;
}
-void mips_srs_free (int set)
+void mips_srs_free(int set)
{
struct shadow_registers *sr = &shadow_registers;
- unsigned long flags;
- spin_lock_irqsave(&sr->sr_lock, flags);
- sr->sr_allocated &= ~(1 << set);
- spin_unlock_irqrestore(&sr->sr_lock, flags);
+ clear_bit(set, &sr->sr_allocated);
}
-void *set_vi_srs_handler (int n, void *addr, int srs)
+static void *set_vi_srs_handler(int n, void *addr, int srs)
{
unsigned long handler;
unsigned long old_handler = vi_handlers[n];
@@ -1032,8 +1103,7 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
if (addr == NULL) {
handler = (unsigned long) do_default_vi;
srs = 0;
- }
- else
+ } else
handler = (unsigned long) addr;
vi_handlers[n] = (unsigned long) addr;
@@ -1045,8 +1115,7 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
if (cpu_has_veic) {
if (board_bind_eic_interrupt)
board_bind_eic_interrupt (n, srs);
- }
- else if (cpu_has_vint) {
+ } else if (cpu_has_vint) {
/* SRSMap is only defined if shadow sets are implemented */
if (mips_srs_max() > 1)
change_c0_srsmap (0xf << n*4, srs << n*4);
@@ -1060,6 +1129,15 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
extern char except_vec_vi, except_vec_vi_lui;
extern char except_vec_vi_ori, except_vec_vi_end;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * We need to provide the SMTC vectored interrupt handler
+ * not only with the address of the handler, but with the
+ * Status.IM bit to be masked before going there.
+ */
+ extern char except_vec_vi_mori;
+ const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+#endif /* CONFIG_MIPS_MT_SMTC */
const int handler_len = &except_vec_vi_end - &except_vec_vi;
const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
@@ -1073,6 +1151,12 @@ void *set_vi_srs_handler (int n, void *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);
+ w = (u32 *)(b + mori_offset);
+ *w = (*w & 0xffff0000) | (0x100 << n);
+#endif /* CONFIG_MIPS_MT_SMTC */
w = (u32 *)(b + lui_offset);
*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
w = (u32 *)(b + ori_offset);
@@ -1095,9 +1179,9 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
return (void *)old_handler;
}
-void *set_vi_handler (int n, void *addr)
+void *set_vi_handler(int n, void *addr)
{
- return set_vi_srs_handler (n, addr, 0);
+ return set_vi_srs_handler(n, addr, 0);
}
#endif
@@ -1113,8 +1197,29 @@ extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+#ifdef CONFIG_SMP
+static int smp_save_fp_context(struct sigcontext *sc)
+{
+ return cpu_has_fpu
+ ? _save_fp_context(sc)
+ : fpu_emulator_save_context(sc);
+}
+
+static int smp_restore_fp_context(struct sigcontext *sc)
+{
+ return cpu_has_fpu
+ ? _restore_fp_context(sc)
+ : fpu_emulator_restore_context(sc);
+}
+#endif
+
static inline void signal_init(void)
{
+#ifdef CONFIG_SMP
+ /* For now just do the cpu_has_fpu check when the functions are invoked */
+ save_fp_context = smp_save_fp_context;
+ restore_fp_context = smp_restore_fp_context;
+#else
if (cpu_has_fpu) {
save_fp_context = _save_fp_context;
restore_fp_context = _restore_fp_context;
@@ -1122,6 +1227,7 @@ static inline void signal_init(void)
save_fp_context = fpu_emulator_save_context;
restore_fp_context = fpu_emulator_restore_context;
}
+#endif
}
#ifdef CONFIG_MIPS32_COMPAT
@@ -1158,6 +1264,20 @@ void __init per_cpu_trap_init(void)
{
unsigned int cpu = smp_processor_id();
unsigned int status_set = ST0_CU0;
+#ifdef CONFIG_MIPS_MT_SMTC
+ int secondaryTC = 0;
+ int bootTC = (cpu == 0);
+
+ /*
+ * Only do per_cpu_trap_init() for first TC of Each VPE.
+ * Note that this hack assumes that the SMTC init code
+ * assigns TCs consecutively and in ascending order.
+ */
+
+ if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
+ ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
+ secondaryTC = 1;
+#endif /* CONFIG_MIPS_MT_SMTC */
/*
* Disable coprocessors and select 32-bit or 64-bit addressing
@@ -1180,6 +1300,10 @@ void __init per_cpu_trap_init(void)
write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
#endif
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (!secondaryTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+
/*
* Interrupt handling.
*/
@@ -1196,6 +1320,9 @@ void __init per_cpu_trap_init(void)
} else
set_c0_cause(CAUSEF_IV);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ }
+#endif /* CONFIG_MIPS_MT_SMTC */
cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
TLBMISS_HANDLER_SETUP();
@@ -1205,8 +1332,14 @@ void __init per_cpu_trap_init(void)
BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
- cpu_cache_init();
- tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (bootTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+ cpu_cache_init();
+ tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+ }
+#endif /* CONFIG_MIPS_MT_SMTC */
}
/* Install CPU exception handler */
@@ -1278,7 +1411,7 @@ void __init trap_init(void)
if (cpu_has_veic || cpu_has_vint) {
int nvec = cpu_has_veic ? 64 : 8;
for (i = 0; i < nvec; i++)
- set_vi_handler (i, NULL);
+ set_vi_handler(i, NULL);
}
else if (cpu_has_divec)
set_handler(0x200, &except_vec4, 0x8);
@@ -1297,6 +1430,7 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();
+ set_except_vector(0, handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 2ad0cedf29fe..14fa00e3cdfa 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -2,7 +2,7 @@
#include <asm/asm-offsets.h>
#include <asm-generic/vmlinux.lds.h>
-#undef mips /* CPP really sucks for this job */
+#undef mips
#define mips mips
OUTPUT_ARCH(mips)
ENTRY(kernel_entry)
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index ae83b755cf4a..85d7df7b18e1 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -13,7 +13,6 @@
* You 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.
- *
*/
/*
@@ -27,11 +26,8 @@
*
* To load and run, simply cat a SP 'program file' to /dev/vpe1.
* i.e cat spapp >/dev/vpe1.
- *
- * You'll need to have the following device files.
- * mknod /dev/vpe0 c 63 0
- * mknod /dev/vpe1 c 63 1
*/
+
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -55,6 +51,8 @@
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
+#include <asm/vpe.h>
+#include <asm/kspd.h>
typedef void *vpe_handle;
@@ -68,6 +66,11 @@ typedef void *vpe_handle;
static char module_name[] = "vpe";
static int major;
+#ifdef CONFIG_MIPS_APSP_KSPD
+ static struct kspd_notifications kspd_events;
+static int kspd_events_reqd = 0;
+#endif
+
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
@@ -76,7 +79,10 @@ static int major;
#define P_SIZE (256 * 1024)
#endif
+extern unsigned long physical_memsize;
+
#define MAX_VPES 16
+#define VPE_PATH_MAX 256
enum vpe_state {
VPE_STATE_UNUSED = 0,
@@ -102,6 +108,8 @@ struct vpe {
unsigned long len;
char *pbuffer;
unsigned long plen;
+ unsigned int uid, gid;
+ char cwd[VPE_PATH_MAX];
unsigned long __start;
@@ -113,6 +121,9 @@ struct vpe {
/* shared symbol address */
void *shared_ptr;
+
+ /* the list of who wants to know when something major happens */
+ struct list_head notify;
};
struct tc {
@@ -138,7 +149,7 @@ struct vpecontrol_ {
} vpecontrol;
static void release_progmem(void *ptr);
-static void dump_vpe(struct vpe * v);
+/* static __attribute_used__ void dump_vpe(struct vpe * v); */
extern void save_gp_address(unsigned int secbase, unsigned int rel);
/* get the vpe associated with this minor */
@@ -146,12 +157,14 @@ struct vpe *get_vpe(int minor)
{
struct vpe *v;
+ if (!cpu_has_mipsmt)
+ return NULL;
+
list_for_each_entry(v, &vpecontrol.vpe_list, list) {
if (v->minor == minor)
return v;
}
- printk(KERN_DEBUG "VPE: get_vpe minor %d not found\n", minor);
return NULL;
}
@@ -165,8 +178,6 @@ struct tc *get_tc(int index)
return t;
}
- printk(KERN_DEBUG "VPE: get_tc index %d not found\n", index);
-
return NULL;
}
@@ -179,8 +190,6 @@ struct tc *get_tc_unused(void)
return t;
}
- printk(KERN_DEBUG "VPE: All TC's are in use\n");
-
return NULL;
}
@@ -190,13 +199,13 @@ struct vpe *alloc_vpe(int minor)
struct vpe *v;
if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "VPE: alloc_vpe no mem\n");
return NULL;
}
INIT_LIST_HEAD(&v->tc);
list_add_tail(&v->list, &vpecontrol.vpe_list);
+ INIT_LIST_HEAD(&v->notify);
v->minor = minor;
return v;
}
@@ -207,7 +216,6 @@ struct tc *alloc_tc(int index)
struct tc *t;
if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "VPE: alloc_tc no mem\n");
return NULL;
}
@@ -236,20 +244,16 @@ void dump_mtregs(void)
printk("config3 0x%lx MT %ld\n", val,
(val & CONFIG3_MT) >> CONFIG3_MT_SHIFT);
- val = read_c0_mvpconf0();
- printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
- (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
- val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
-
val = read_c0_mvpcontrol();
printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val,
(val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT,
(val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT,
(val & MVPCONTROL_EVP));
- val = read_c0_vpeconf0();
- printk("VPEConf0 0x%lx MVP %ld\n", val,
- (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+ val = read_c0_mvpconf0();
+ printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
+ (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
+ val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
}
/* Find some VPE program space */
@@ -354,9 +358,9 @@ static int apply_r_mips_gprel16(struct module *me, uint32_t *location,
}
if( (rel > 32768) || (rel < -32768) ) {
- printk(KERN_ERR
- "apply_r_mips_gprel16: relative address out of range 0x%x %d\n",
- rel, rel);
+ printk(KERN_DEBUG "VPE loader: apply_r_mips_gprel16: "
+ "relative address 0x%x out of range of gp register\n",
+ rel);
return -ENOEXEC;
}
@@ -374,8 +378,8 @@ static int apply_r_mips_pc16(struct module *me, uint32_t *location,
rel -= 1; // and one instruction less due to the branch delay slot.
if( (rel > 32768) || (rel < -32768) ) {
- printk(KERN_ERR
- "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
+ printk(KERN_DEBUG "VPE loader: "
+ "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
return -ENOEXEC;
}
@@ -396,7 +400,8 @@ static int apply_r_mips_26(struct module *me, uint32_t *location,
Elf32_Addr v)
{
if (v % 4) {
- printk(KERN_ERR "module %s: dangerous relocation mod4\n", me->name);
+ printk(KERN_DEBUG "VPE loader: apply_r_mips_26 "
+ " unaligned relocation\n");
return -ENOEXEC;
}
@@ -459,12 +464,13 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
/*
* The value for the HI16 had best be the same.
*/
- if (v != l->value) {
- printk("%d != %d\n", v, l->value);
- goto out_danger;
+ if (v != l->value) {
+ printk(KERN_DEBUG "VPE loader: "
+ "apply_r_mips_lo16/hi16: "
+ "inconsistent value information\n");
+ return -ENOEXEC;
}
-
/*
* Do the HI16 relocation. Note that we actually don't
* need to know anything about the LO16 itself, except
@@ -500,11 +506,6 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
*location = insnlo;
return 0;
-
-out_danger:
- printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
-
- return -ENOEXEC;
}
static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
@@ -518,6 +519,15 @@ static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
[R_MIPS_PC16] = apply_r_mips_pc16
};
+static char *rstrs[] = {
+ [R_MIPS_NONE] = "MIPS_NONE",
+ [R_MIPS_32] = "MIPS_32",
+ [R_MIPS_26] = "MIPS_26",
+ [R_MIPS_HI16] = "MIPS_HI16",
+ [R_MIPS_LO16] = "MIPS_LO16",
+ [R_MIPS_GPREL16] = "MIPS_GPREL16",
+ [R_MIPS_PC16] = "MIPS_PC16"
+};
int apply_relocations(Elf32_Shdr *sechdrs,
const char *strtab,
@@ -552,15 +562,13 @@ int apply_relocations(Elf32_Shdr *sechdrs,
res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
if( res ) {
- printk(KERN_DEBUG
- "relocation error 0x%x sym refer <%s> value 0x%x "
- "type 0x%x r_info 0x%x\n",
- (unsigned int)location, strtab + sym->st_name, v,
- r_info, ELF32_R_TYPE(r_info));
- }
-
- if (res)
+ char *r = rstrs[ELF32_R_TYPE(r_info)];
+ printk(KERN_WARNING "VPE loader: .text+0x%x "
+ "relocation type %s for symbol \"%s\" failed\n",
+ rel[i].r_offset, r ? r : "UNKNOWN",
+ strtab + sym->st_name);
return res;
+ }
}
return 0;
@@ -576,7 +584,7 @@ void save_gp_address(unsigned int secbase, unsigned int rel)
/* Change all symbols so that sh_value encodes the pointer directly. */
-static int simplify_symbols(Elf_Shdr * sechdrs,
+static void simplify_symbols(Elf_Shdr * sechdrs,
unsigned int symindex,
const char *strtab,
const char *secstrings,
@@ -585,18 +593,21 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
unsigned long secbase, bssbase = 0;
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
- int ret = 0, size;
+ int size;
/* find the .bss section for COMMON symbols */
for (i = 0; i < nsecs; i++) {
- if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0)
+ if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0) {
bssbase = sechdrs[i].sh_addr;
+ break;
+ }
}
for (i = 1; i < n; i++) {
switch (sym[i].st_shndx) {
case SHN_COMMON:
- /* Allocate space for the symbol in the .bss section. st_value is currently size.
+ /* Allocate space for the symbol in the .bss section.
+ st_value is currently size.
We want it to have the address of the symbol. */
size = sym[i].st_value;
@@ -614,11 +625,9 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
break;
case SHN_MIPS_SCOMMON:
-
- printk(KERN_DEBUG
- "simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n",
- strtab + sym[i].st_name, sym[i].st_shndx);
-
+ printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON"
+ "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name,
+ sym[i].st_shndx);
// .sbss section
break;
@@ -632,10 +641,7 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
sym[i].st_value += secbase;
break;
}
-
}
-
- return ret;
}
#ifdef DEBUG_ELFLOADER
@@ -655,9 +661,26 @@ static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,
static void dump_tc(struct tc *t)
{
- printk(KERN_WARNING "VPE: TC index %d TCStatus 0x%lx halt 0x%lx\n",
- t->index, read_tc_c0_tcstatus(), read_tc_c0_tchalt());
- printk(KERN_WARNING "VPE: tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+ unsigned long val;
+
+ settc(t->index);
+ printk(KERN_DEBUG "VPE loader: TC index %d targtc %ld "
+ "TCStatus 0x%lx halt 0x%lx\n",
+ t->index, read_c0_vpecontrol() & VPECONTROL_TARGTC,
+ read_tc_c0_tcstatus(), read_tc_c0_tchalt());
+
+ printk(KERN_DEBUG " tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+ printk(KERN_DEBUG " tcbind 0x%lx\n", read_tc_c0_tcbind());
+
+ val = read_c0_vpeconf0();
+ printk(KERN_DEBUG " VPEConf0 0x%lx MVP %ld\n", val,
+ (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+
+ printk(KERN_DEBUG " c0 status 0x%lx\n", read_vpe_c0_status());
+ printk(KERN_DEBUG " c0 cause 0x%lx\n", read_vpe_c0_cause());
+
+ printk(KERN_DEBUG " c0 badvaddr 0x%lx\n", read_vpe_c0_badvaddr());
+ printk(KERN_DEBUG " c0 epc 0x%lx\n", read_vpe_c0_epc());
}
static void dump_tclist(void)
@@ -672,96 +695,108 @@ static void dump_tclist(void)
/* We are prepared so configure and start the VPE... */
int vpe_run(struct vpe * v)
{
- unsigned long val;
+ struct vpe_notifications *n;
+ unsigned long val, dmt_flag;
struct tc *t;
/* check we are the Master VPE */
val = read_c0_vpeconf0();
if (!(val & VPECONF0_MVP)) {
printk(KERN_WARNING
- "VPE: only Master VPE's are allowed to configure MT\n");
+ "VPE loader: only Master VPE's are allowed to configure MT\n");
return -1;
}
/* disable MT (using dvpe) */
dvpe();
+ if (!list_empty(&v->tc)) {
+ if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+ printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
+ t->index);
+ return -ENOEXEC;
+ }
+ } else {
+ printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
+ v->minor);
+ return -ENOEXEC;
+ }
+
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
- if (!list_empty(&v->tc)) {
- if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
- printk(KERN_WARNING "VPE: TC %d is already in use.\n",
- t->index);
- return -ENOEXEC;
- }
- } else {
- printk(KERN_WARNING "VPE: No TC's associated with VPE %d\n",
- v->minor);
- return -ENOEXEC;
- }
-
settc(t->index);
- val = read_vpe_c0_vpeconf0();
-
/* should check it is halted, and not activated */
if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {
- printk(KERN_WARNING "VPE: TC %d is already doing something!\n",
+ printk(KERN_WARNING "VPE loader: TC %d is already doing something!\n",
t->index);
-
dump_tclist();
return -ENOEXEC;
}
+ /*
+ * Disable multi-threaded execution whilst we activate, clear the
+ * halt bit and bound the tc to the other VPE...
+ */
+ dmt_flag = dmt();
+
/* Write the address we want it to start running from in the TCPC register. */
write_tc_c0_tcrestart((unsigned long)v->__start);
-
- /* write the sivc_info address to tccontext */
write_tc_c0_tccontext((unsigned long)0);
-
- /* Set up the XTC bit in vpeconf0 to point at our tc */
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (t->index << VPECONF0_XTC_SHIFT));
-
- /* mark the TC as activated, not interrupt exempt and not dynamically allocatable */
+ /*
+ * Mark the TC as activated, not interrupt exempt and not dynamically
+ * allocatable
+ */
val = read_tc_c0_tcstatus();
val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
write_tc_c0_tcstatus(val);
write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
- /* set up VPE1 */
- write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); // no multiple TC's
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); // enable this VPE
-
/*
* The sde-kit passes 'memsize' to __start in $a3, so set something
- * here...
- * Or set $a3 (register 7) to zero and define DFLT_STACK_SIZE and
+ * here... Or set $a3 to zero and define DFLT_STACK_SIZE and
* DFLT_HEAP_SIZE when you compile your program
*/
+ mttgpr(7, physical_memsize);
+
+
+ /* set up VPE1 */
+ /*
+ * bind the TC to VPE 1 as late as possible so we only have the final
+ * VPE registers to set up, and so an EJTAG probe can trigger on it
+ */
+ write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
- mttgpr(7, 0);
+ /* Set up the XTC bit in vpeconf0 to point at our tc */
+ write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+ | (t->index << VPECONF0_XTC_SHIFT));
- /* set config to be the same as vpe0, particularly kseg0 coherency alg */
- write_vpe_c0_config(read_c0_config());
+ /* enable this VPE */
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
/* clear out any left overs from a previous program */
+ write_vpe_c0_status(0);
write_vpe_c0_cause(0);
/* take system out of configuration state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
- /* clear interrupts enabled IE, ERL, EXL, and KSU from c0 status */
- write_vpe_c0_status(read_vpe_c0_status() & ~(ST0_ERL | ST0_KSU | ST0_IE | ST0_EXL));
+ /* now safe to re-enable multi-threading */
+ emt(dmt_flag);
/* set it running */
evpe(EVPE_ENABLE);
+ list_for_each_entry(n, &v->notify, list) {
+ n->start(v->minor);
+ }
+
return 0;
}
-static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
+static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
unsigned int symindex, const char *strtab,
struct module *mod)
{
@@ -778,26 +813,28 @@ static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
}
}
+ if ( (v->__start == 0) || (v->shared_ptr == NULL))
+ return -1;
+
return 0;
}
/*
- * Allocates a VPE with some program code space(the load address), copies
- * the contents of the program (p)buffer performing relocatations/etc,
- * free's it when finished.
-*/
+ * Allocates a VPE with some program code space(the load address), copies the
+ * contents of the program (p)buffer performing relocatations/etc, free's it
+ * when finished.
+ */
int vpe_elfload(struct vpe * v)
{
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
long err = 0;
char *secstrings, *strtab = NULL;
- unsigned int len, i, symindex = 0, strindex = 0;
-
+ unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;
struct module mod; // so we can re-use the relocations code
memset(&mod, 0, sizeof(struct module));
- strcpy(mod.name, "VPE dummy prog module");
+ strcpy(mod.name, "VPE loader");
hdr = (Elf_Ehdr *) v->pbuffer;
len = v->plen;
@@ -805,16 +842,22 @@ int vpe_elfload(struct vpe * v)
/* Sanity checks against insmoding binaries or wrong arch,
weird elf version */
if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
- || hdr->e_type != ET_REL || !elf_check_arch(hdr)
+ || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)
+ || !elf_check_arch(hdr)
|| hdr->e_shentsize != sizeof(*sechdrs)) {
printk(KERN_WARNING
- "VPE program, wrong arch or weird elf version\n");
+ "VPE loader: program wrong arch or weird elf version\n");
return -ENOEXEC;
}
+ if (hdr->e_type == ET_REL)
+ relocate = 1;
+
if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
- printk(KERN_ERR "VPE program length %u truncated\n", len);
+ printk(KERN_ERR "VPE loader: program length %u truncated\n",
+ len);
+
return -ENOEXEC;
}
@@ -826,82 +869,126 @@ int vpe_elfload(struct vpe * v)
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = 0;
- for (i = 1; i < hdr->e_shnum; i++) {
-
- if (sechdrs[i].sh_type != SHT_NOBITS
- && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
- printk(KERN_ERR "VPE program length %u truncated\n",
- len);
- return -ENOEXEC;
- }
+ if (relocate) {
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_type != SHT_NOBITS
+ && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
+ printk(KERN_ERR "VPE program length %u truncated\n",
+ len);
+ return -ENOEXEC;
+ }
- /* Mark all sections sh_addr with their address in the
- temporary image. */
- sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ /* Mark all sections sh_addr with their address in the
+ temporary image. */
+ sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
- /* Internal symbols and strings. */
- if (sechdrs[i].sh_type == SHT_SYMTAB) {
- symindex = i;
- strindex = sechdrs[i].sh_link;
- strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+ }
}
+ layout_sections(&mod, hdr, sechdrs, secstrings);
}
- layout_sections(&mod, hdr, sechdrs, secstrings);
-
v->load_addr = alloc_progmem(mod.core_size);
memset(v->load_addr, 0, mod.core_size);
- printk("VPE elf_loader: loading to %p\n", v->load_addr);
+ printk("VPE loader: loading to %p\n", v->load_addr);
- for (i = 0; i < hdr->e_shnum; i++) {
- void *dest;
+ if (relocate) {
+ for (i = 0; i < hdr->e_shnum; i++) {
+ void *dest;
- if (!(sechdrs[i].sh_flags & SHF_ALLOC))
- continue;
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+ continue;
- dest = v->load_addr + sechdrs[i].sh_entsize;
+ dest = v->load_addr + sechdrs[i].sh_entsize;
- if (sechdrs[i].sh_type != SHT_NOBITS)
- memcpy(dest, (void *)sechdrs[i].sh_addr,
- sechdrs[i].sh_size);
- /* Update sh_addr to point to copy in image. */
- sechdrs[i].sh_addr = (unsigned long)dest;
- }
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ memcpy(dest, (void *)sechdrs[i].sh_addr,
+ sechdrs[i].sh_size);
+ /* Update sh_addr to point to copy in image. */
+ sechdrs[i].sh_addr = (unsigned long)dest;
- /* Fix up syms, so that st_value is a pointer to location. */
- err =
- simplify_symbols(sechdrs, symindex, strtab, secstrings,
- hdr->e_shnum, &mod);
- if (err < 0) {
- printk(KERN_WARNING "VPE: unable to simplify symbols\n");
- goto cleanup;
- }
+ printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
+ secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);
+ }
- /* Now do relocations. */
- for (i = 1; i < hdr->e_shnum; i++) {
- const char *strtab = (char *)sechdrs[strindex].sh_addr;
- unsigned int info = sechdrs[i].sh_info;
-
- /* Not a valid relocation section? */
- if (info >= hdr->e_shnum)
- continue;
-
- /* Don't bother with non-allocated sections */
- if (!(sechdrs[info].sh_flags & SHF_ALLOC))
- continue;
-
- if (sechdrs[i].sh_type == SHT_REL)
- err =
- apply_relocations(sechdrs, strtab, symindex, i, &mod);
- else if (sechdrs[i].sh_type == SHT_RELA)
- err = apply_relocate_add(sechdrs, strtab, symindex, i,
- &mod);
- if (err < 0) {
- printk(KERN_WARNING
- "vpe_elfload: error in relocations err %ld\n",
- err);
- goto cleanup;
+ /* Fix up syms, so that st_value is a pointer to location. */
+ simplify_symbols(sechdrs, symindex, strtab, secstrings,
+ hdr->e_shnum, &mod);
+
+ /* Now do relocations. */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ const char *strtab = (char *)sechdrs[strindex].sh_addr;
+ unsigned int info = sechdrs[i].sh_info;
+
+ /* Not a valid relocation section? */
+ if (info >= hdr->e_shnum)
+ continue;
+
+ /* Don't bother with non-allocated sections */
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+ continue;
+
+ if (sechdrs[i].sh_type == SHT_REL)
+ err = apply_relocations(sechdrs, strtab, symindex, i,
+ &mod);
+ else if (sechdrs[i].sh_type == SHT_RELA)
+ err = apply_relocate_add(sechdrs, strtab, symindex, i,
+ &mod);
+ if (err < 0)
+ return err;
+
+ }
+ } else {
+ for (i = 0; i < hdr->e_shnum; i++) {
+
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+
+ /* mark the symtab's address for when we try to find the
+ magic symbols */
+ sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ }
+
+ /* filter sections we dont want in the final image */
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
+ (sechdrs[i].sh_type == SHT_MIPS_REGINFO)) {
+ printk( KERN_DEBUG " ignoring section, "
+ "name %s type %x address 0x%x \n",
+ secstrings + sechdrs[i].sh_name,
+ sechdrs[i].sh_type, sechdrs[i].sh_addr);
+ continue;
+ }
+
+ if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) {
+ printk( KERN_WARNING "VPE loader: "
+ "fully linked image has invalid section, "
+ "name %s type %x address 0x%x, before load "
+ "address of 0x%x\n",
+ secstrings + sechdrs[i].sh_name,
+ sechdrs[i].sh_type, sechdrs[i].sh_addr,
+ (unsigned int)v->load_addr);
+ return -ENOEXEC;
+ }
+
+ printk(KERN_DEBUG " copying section sh_name %s, sh_addr 0x%x "
+ "size 0x%x0 from x%p\n",
+ secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr,
+ sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);
+
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ memcpy((void *)sechdrs[i].sh_addr,
+ (char *)hdr + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size);
+ else
+ memset((void *)sechdrs[i].sh_addr, 0, sechdrs[i].sh_size);
}
}
@@ -910,71 +997,104 @@ int vpe_elfload(struct vpe * v)
(unsigned long)v->load_addr + v->len);
if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+ if (v->__start == 0) {
+ printk(KERN_WARNING "VPE loader: program does not contain "
+ "a __start symbol\n");
+ return -ENOEXEC;
+ }
- printk(KERN_WARNING
- "VPE: program doesn't contain __start or vpe_shared symbols\n");
- err = -ENOEXEC;
+ if (v->shared_ptr == NULL)
+ printk(KERN_WARNING "VPE loader: "
+ "program does not contain vpe_shared symbol.\n"
+ " Unable to use AMVP (AP/SP) facilities.\n");
}
printk(" elf loaded\n");
-
-cleanup:
- return err;
+ return 0;
}
-static void dump_vpe(struct vpe * v)
+__attribute_used__ void dump_vpe(struct vpe * v)
{
struct tc *t;
+ settc(v->minor);
+
printk(KERN_DEBUG "VPEControl 0x%lx\n", read_vpe_c0_vpecontrol());
printk(KERN_DEBUG "VPEConf0 0x%lx\n", read_vpe_c0_vpeconf0());
- list_for_each_entry(t, &vpecontrol.tc_list, list) {
+ list_for_each_entry(t, &vpecontrol.tc_list, list)
dump_tc(t);
- }
}
-/* checks for VPE is unused and gets ready to load program */
+static void cleanup_tc(struct tc *tc)
+{
+ int tmp;
+
+ /* Put MVPE's into 'configuration state' */
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ settc(tc->index);
+ tmp = read_tc_c0_tcstatus();
+
+ /* mark not allocated and not dynamically allocatable */
+ tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+ tmp |= TCSTATUS_IXMT; /* interrupt exempt */
+ write_tc_c0_tcstatus(tmp);
+
+ write_tc_c0_tchalt(TCHALT_H);
+
+ /* bind it to anything other than VPE1 */
+ write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE
+
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+}
+
+static int getcwd(char *buff, int size)
+{
+ mm_segment_t old_fs;
+ int ret;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ ret = sys_getcwd(buff,size);
+
+ set_fs(old_fs);
+
+ return ret;
+}
+
+/* checks VPE is unused and gets ready to load program */
static int vpe_open(struct inode *inode, struct file *filp)
{
- int minor;
+ int minor, ret;
struct vpe *v;
+ struct vpe_notifications *not;
/* assume only 1 device at the mo. */
- if ((minor = MINOR(inode->i_rdev)) != 1) {
- printk(KERN_WARNING "VPE: only vpe1 is supported\n");
+ if ((minor = iminor(inode)) != 1) {
+ printk(KERN_WARNING "VPE loader: only vpe1 is supported\n");
return -ENODEV;
}
if ((v = get_vpe(minor)) == NULL) {
- printk(KERN_WARNING "VPE: unable to get vpe\n");
+ printk(KERN_WARNING "VPE loader: unable to get vpe\n");
return -ENODEV;
}
if (v->state != VPE_STATE_UNUSED) {
- unsigned long tmp;
- struct tc *t;
-
- printk(KERN_WARNING "VPE: device %d already in use\n", minor);
-
dvpe();
- dump_vpe(v);
-
- printk(KERN_WARNING "VPE: re-initialising %d\n", minor);
-
- release_progmem(v->load_addr);
- t = get_tc(minor);
- settc(minor);
- tmp = read_tc_c0_tcstatus();
+ printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
- /* mark not allocated and not dynamically allocatable */
- tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
- tmp |= TCSTATUS_IXMT; /* interrupt exempt */
- write_tc_c0_tcstatus(tmp);
+ dump_tc(get_tc(minor));
- write_tc_c0_tchalt(TCHALT_H);
+ list_for_each_entry(not, &v->notify, list) {
+ not->stop(minor);
+ }
+ release_progmem(v->load_addr);
+ cleanup_tc(get_tc(minor));
}
// allocate it so when we get write ops we know it's expected.
@@ -986,6 +1106,24 @@ static int vpe_open(struct inode *inode, struct file *filp)
v->load_addr = NULL;
v->len = 0;
+ v->uid = filp->f_uid;
+ v->gid = filp->f_gid;
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+ /* get kspd to tell us when a syscall_exit happens */
+ if (!kspd_events_reqd) {
+ kspd_notify(&kspd_events);
+ kspd_events_reqd++;
+ }
+#endif
+
+ v->cwd[0] = 0;
+ ret = getcwd(v->cwd, VPE_PATH_MAX);
+ if (ret < 0)
+ printk(KERN_WARNING "VPE loader: open, getcwd returned %d\n", ret);
+
+ v->shared_ptr = NULL;
+ v->__start = 0;
return 0;
}
@@ -995,7 +1133,7 @@ static int vpe_release(struct inode *inode, struct file *filp)
struct vpe *v;
Elf_Ehdr *hdr;
- minor = MINOR(inode->i_rdev);
+ minor = iminor(inode);
if ((v = get_vpe(minor)) == NULL)
return -ENODEV;
@@ -1006,14 +1144,22 @@ static int vpe_release(struct inode *inode, struct file *filp)
if (vpe_elfload(v) >= 0)
vpe_run(v);
else {
- printk(KERN_WARNING "VPE: ELF load failed.\n");
+ printk(KERN_WARNING "VPE loader: ELF load failed.\n");
ret = -ENOEXEC;
}
} else {
- printk(KERN_WARNING "VPE: only elf files are supported\n");
+ printk(KERN_WARNING "VPE loader: only elf files are supported\n");
ret = -ENOEXEC;
}
+ /* It's good to be able to run the SP and if it chokes have a look at
+ the /dev/rt?. But if we reset the pointer to the shared struct we
+ loose what has happened. So perhaps if garbage is sent to the vpe
+ device, use it as a trigger for the reset. Hopefully a nice
+ executable will be along shortly. */
+ if (ret < 0)
+ v->shared_ptr = NULL;
+
// cleanup any temp buffers
if (v->pbuffer)
vfree(v->pbuffer);
@@ -1028,26 +1174,24 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
size_t ret = count;
struct vpe *v;
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ minor = iminor(file->f_dentry->d_inode);
if ((v = get_vpe(minor)) == NULL)
return -ENODEV;
if (v->pbuffer == NULL) {
- printk(KERN_ERR "vpe_write: no pbuffer\n");
+ printk(KERN_ERR "VPE loader: no buffer for program\n");
return -ENOMEM;
}
if ((count + v->len) > v->plen) {
printk(KERN_WARNING
- "VPE Loader: elf size too big. Perhaps strip uneeded symbols\n");
+ "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
return -ENOMEM;
}
count -= copy_from_user(v->pbuffer + v->len, buffer, count);
- if (!count) {
- printk("vpe_write: copy_to_user failed\n");
+ if (!count)
return -EFAULT;
- }
v->len += count;
return ret;
@@ -1149,16 +1293,70 @@ void *vpe_get_shared(int index)
{
struct vpe *v;
- if ((v = get_vpe(index)) == NULL) {
- printk(KERN_WARNING "vpe: invalid vpe index %d\n", index);
+ if ((v = get_vpe(index)) == NULL)
return NULL;
- }
return v->shared_ptr;
}
EXPORT_SYMBOL(vpe_get_shared);
+int vpe_getuid(int index)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return -1;
+
+ return v->uid;
+}
+
+EXPORT_SYMBOL(vpe_getuid);
+
+int vpe_getgid(int index)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return -1;
+
+ return v->gid;
+}
+
+EXPORT_SYMBOL(vpe_getgid);
+
+int vpe_notify(int index, struct vpe_notifications *notify)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return -1;
+
+ list_add(&notify->list, &v->notify);
+ return 0;
+}
+
+EXPORT_SYMBOL(vpe_notify);
+
+char *vpe_getcwd(int index)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return NULL;
+
+ return v->cwd;
+}
+
+EXPORT_SYMBOL(vpe_getcwd);
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+static void kspd_sp_exit( int sp_id)
+{
+ cleanup_tc(get_tc(sp_id));
+}
+#endif
+
static int __init vpe_module_init(void)
{
struct vpe *v = NULL;
@@ -1201,7 +1399,8 @@ static int __init vpe_module_init(void)
return -ENODEV;
}
- list_add(&t->tc, &v->tc); /* add the tc to the list of this vpe's tc's. */
+ /* add the tc to the list of this vpe's tc's. */
+ list_add(&t->tc, &v->tc);
/* deactivate all but vpe0 */
if (i != 0) {
@@ -1222,10 +1421,12 @@ static int __init vpe_module_init(void)
~(ST0_IM | ST0_IE | ST0_KSU))
| ST0_CU0);
- /* set config to be the same as vpe0, particularly kseg0 coherency alg */
+ /*
+ * Set config to be the same as vpe0,
+ * particularly kseg0 coherency alg
+ */
write_vpe_c0_config(read_c0_config());
}
-
}
/* TC's */
@@ -1234,23 +1435,28 @@ static int __init vpe_module_init(void)
if (i != 0) {
unsigned long tmp;
- /* tc 0 will of course be running.... */
- if (i == 0)
- t->state = TC_STATE_RUNNING;
-
settc(i);
- /* bind a TC to each VPE, May as well put all excess TC's
- on the last VPE */
- if (i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1))
- write_tc_c0_tcbind(read_tc_c0_tcbind() |
- ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT));
- else
- write_tc_c0_tcbind(read_tc_c0_tcbind() | i);
+ /* Any TC that is bound to VPE0 gets left as is - in case
+ we are running SMTC on VPE0. A TC that is bound to any
+ other VPE gets bound to VPE0, ideally I'd like to make
+ it homeless but it doesn't appear to let me bind a TC
+ to a non-existent VPE. Which is perfectly reasonable.
+
+ The (un)bound state is visible to an EJTAG probe so may
+ notify GDB...
+ */
+
+ if (((tmp = read_tc_c0_tcbind()) & TCBIND_CURVPE)) {
+ /* tc is bound >vpe0 */
+ write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE);
+
+ t->pvpe = get_vpe(0); /* set the parent vpe */
+ }
tmp = read_tc_c0_tcstatus();
- /* mark not allocated and not dynamically allocatable */
+ /* mark not activated and not dynamically allocatable */
tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
tmp |= TCSTATUS_IXMT; /* interrupt exempt */
write_tc_c0_tcstatus(tmp);
@@ -1262,6 +1468,9 @@ static int __init vpe_module_init(void)
/* release config state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
+#ifdef CONFIG_MIPS_APSP_KSPD
+ kspd_events.kspd_sp_exit = kspd_sp_exit;
+#endif
return 0;
}
@@ -1281,5 +1490,5 @@ static void __exit vpe_module_exit(void)
module_init(vpe_module_init);
module_exit(vpe_module_exit);
MODULE_DESCRIPTION("MIPS VPE Loader");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
index 0d5aec436725..99f5046fdf49 100644
--- a/arch/mips/lasat/Makefile
+++ b/arch/mips/lasat/Makefile
@@ -3,7 +3,7 @@
#
obj-y += reset.o setup.o prom.o lasat_board.o \
- at93c.o interrupt.o lasatIRQ.o
+ at93c.o interrupt.o
obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o
obj-$(CONFIG_DS1603) += ds1603.o
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 852a41901a5e..2d3472b21ebb 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -27,14 +27,13 @@
#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;
-extern asmlinkage void lasatIRQ(void);
-
void disable_lasat_irq(unsigned int irq_nr)
{
unsigned long flags;
@@ -109,11 +108,17 @@ static unsigned long get_int_status_200(void)
return int_status;
}
-void lasat_hw0_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned long int_status;
+ unsigned int cause = read_c0_cause();
int irq;
+ if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */
+ ll_timer_interrupt(7, regs);
+ return;
+ }
+
int_status = get_int_status();
/* if int_status == 0, then the interrupt has already been cleared */
@@ -147,9 +152,6 @@ void __init arch_init_irq(void)
panic("arch_init_irq: mips_machtype incorrect");
}
- /* Now safe to set the exception vector. */
- set_except_vector(0, lasatIRQ);
-
for (i = 0; i <= LASATINT_END; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S
deleted file mode 100644
index 2a2b0d056561..000000000000
--- a/arch/mips/lasat/lasatIRQ.S
+++ /dev/null
@@ -1,69 +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.
- *
- * Interrupt exception dispatch code.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .set noreorder
- .align 5
- NESTED(lasatIRQ, PT_SIZE, sp)
- .set noat
- SAVE_ALL
- CLI
- .set at
- .set noreorder
-
- mfc0 s0, CP0_CAUSE # get irq mask
-
- /* First we check for r4k counter/timer IRQ. */
- andi a0, s0, CAUSEF_IP7
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt
-
- /* Wheee, a timer interrupt. */
- li a0, 7
- jal ll_timer_interrupt
- move a1, sp
-
- j ret_from_irq
- nop
-
-1:
- /* Wheee, combined hardware level zero interrupt. */
- jal lasat_hw0_irqdispatch
- move a0, sp # delay slot
-
- j ret_from_irq
- nop # delay slot
-
-1:
- /*
- * Here by mistake? This is possible, what can happen is that by the
- * time we take the exception the IRQ pin goes low, so just leave if
- * this is the case.
- */
- move a1,s0
- mfc0 a1, CP0_EPC
-
- j ret_from_irq
- nop
- END(lasatIRQ)
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index bc0ebc69bfb3..db53950b7cfb 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -39,8 +39,6 @@
static struct atlas_ictrl_regs *atlas_hw0_icregs;
-extern asmlinkage void mipsIRQ(void);
-
#if 0
#define DEBUG_INT(x...) printk(x)
#else
@@ -98,7 +96,7 @@ static inline int ls1bit32(unsigned int x)
return b;
}
-void atlas_hw0_irqdispatch(struct pt_regs *regs)
+static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
{
unsigned long int_status;
int irq;
@@ -116,6 +114,91 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs)
do_IRQ(irq, regs);
}
+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
+}
+
+/*
+ * IRQs on the Atlas board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq == MIPSCPU_INT_ATLAS)
+ atlas_hw0_irqdispatch(regs);
+ else if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
+
void __init arch_init_irq(void)
{
int i;
@@ -128,9 +211,6 @@ void __init arch_init_irq(void)
*/
atlas_hw0_icregs->intrsten = 0xffffffff;
- /* Now safe to set the exception vector. */
- set_except_vector(0, mipsIRQ);
-
for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
index b21bc6887fa8..be47c1c2bc80 100644
--- a/arch/mips/mips-boards/generic/Makefile
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -18,8 +18,8 @@
# Makefile for the MIPS boards generic routines under Linux.
#
-obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
- printf.o cmdline.o time.o
+obj-y := reset.o display.o init.o memory.o printf.o \
+ cmdline.o time.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
index 91a2ccbe3730..6a1854de4579 100644
--- a/arch/mips/mips-boards/generic/gdb_hook.c
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -25,7 +25,7 @@
#include <asm/serial.h>
#include <asm/io.h>
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
+static struct serial_state rs_table[] = {
SERIAL_PORT_DFNS /* Defined in serial.h */
};
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index eab5a705e989..df4e94735604 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -220,7 +220,6 @@ void __init kgdb_config (void)
generic_putDebugChar (*s++);
}
- kgdb_enabled = 1;
/* Breakpoint is invoked after interrupts are initialised */
}
}
@@ -338,6 +337,7 @@ void __init prom_init(void)
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:
_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index 32c9210373ac..bc4d093685bb 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -22,10 +22,12 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
+#include <asm/sections.h>
#include <asm/mips-boards/prom.h>
@@ -46,9 +48,6 @@ static char *mtypes[3] = {
};
#endif
-/* References to section boundaries */
-extern char _end;
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
char *memsize_str;
@@ -106,10 +105,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
mdesc[3].type = yamon_dontuse;
mdesc[3].base = 0x00100000;
- mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base;
+ mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base;
mdesc[4].type = yamon_free;
- mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end));
+ mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
mdesc[4].size = memsize - mdesc[4].base;
return &mdesc[0];
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
deleted file mode 100644
index ddd5c73a2971..000000000000
--- a/arch/mips/mips-boards/generic/mipsIRQ.S
+++ /dev/null
@@ -1,155 +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.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#ifdef CONFIG_MIPS_ATLAS
-#include <asm/mips-boards/atlasint.h>
-#define CASCADE_IRQ MIPSCPU_INT_ATLAS
-#define CASCADE_DISPATCH atlas_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/maltaint.h>
-#define CASCADE_IRQ MIPSCPU_INT_I8259A
-#define CASCADE_DISPATCH malta_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_SEAD
-#include <asm/mips-boards/seadint.h>
-#endif
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the MIPS board look basically (barring software
- * IRQs which we don't use at all and all external interrupt sources are
- * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Combined hardware interrupt (hw0)
- * 3 Hardware (ignored)
- * 4 Hardware (ignored)
- * 5 Hardware (ignored)
- * 6 Hardware (ignored)
- * 7 R4k timer (what we use)
- *
- * Note: On the SEAD board thing are a little bit different.
- * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
- * wired to UART1.
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Lowest ---- Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(mipsIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 s0, CP0_CAUSE # get irq bits
- mfc0 s1, CP0_STATUS # get irq mask
- andi s0, ST0_IM # CAUSE.CE may be non-zero!
- and s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
- .set mips32
- clz a0, s0
- .set mips0
- negu a0
- addu a0, 31-CAUSEB_IP
- bltz a0, spurious
-#else
- beqz s0, spurious
- li a0, 7
-
- and t0, s0, 0xf000
- sltiu t0, t0, 1
- sll t0, 2
- subu a0, t0
- sll s0, t0
-
- and t0, s0, 0xc000
- sltiu t0, t0, 1
- sll t0, 1
- subu a0, t0
- sll s0, t0
-
- and t0, s0, 0x8000
- sltiu t0, t0, 1
- # sll t0, 0
- subu a0, t0
- # sll s0, t0
-#endif
-
-#ifdef CASCADE_IRQ
- li a1, CASCADE_IRQ
- bne a0, a1, 1f
- addu a0, MIPSCPU_INT_BASE
-
- jal CASCADE_DISPATCH
- move a0, sp
-
- j ret_from_irq
- nop
-1:
-#else
- addu a0, MIPSCPU_INT_BASE
-#endif
-
- jal do_IRQ
- move a1, sp
-
- j ret_from_irq
- nop
-
-
-spurious:
- j spurious_interrupt
- nop
- END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index 1f6f9df74ab2..9337f6c8873a 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -198,6 +198,7 @@ void __init mips_pcibios_init(void)
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:
/* Set up resource ranges from the controller's registers. */
MSC_READ(MSC01_PCI_SC2PMBASL, start);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 93f3bf2c2b22..a9f6124b3a22 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -30,6 +30,7 @@
#include <linux/mc146818rtc.h>
#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
#include <asm/ptrace.h>
#include <asm/hardirq.h>
#include <asm/irq.h>
@@ -50,16 +51,23 @@ unsigned long cpu_khz;
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 = 0;
+static unsigned int display_count;
#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-static unsigned int timer_tick_count=0;
+#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
+
+static unsigned int timer_tick_count;
static int mips_cpu_timer_irq;
+extern void smtc_timer_broadcast(int);
static inline void scroll_display_message(void)
{
@@ -75,15 +83,55 @@ static void mips_timer_dispatch (struct pt_regs *regs)
do_IRQ (mips_cpu_timer_irq, regs);
}
+/*
+ * Redeclare until I get around mopping the timer code insanity on MIPS.
+ */
extern int null_perf_irq(struct pt_regs *regs);
extern int (*perf_irq)(struct pt_regs *regs);
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- int r2 = cpu_has_mips_r2;
int cpu = smp_processor_id();
+ int r2 = cpu_has_mips_r2;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * In an SMTC system, one Count/Compare set exists per VPE.
+ * Which TC within a VPE gets the interrupt is essentially
+ * random - we only know that it shouldn't be one with
+ * IXMT set. Whichever TC gets the interrupt needs to
+ * send special interprocessor interrupts to the other
+ * TCs to make sure that they schedule, etc.
+ *
+ * That code is specific to the SMTC kernel, not to
+ * the a particular platform, so it's invoked from
+ * the general MIPS timer_interrupt routine.
+ */
+
+ /*
+ * DVPE is necessary so long as cross-VPE interrupts
+ * are done via read-modify-write of Cause register.
+ */
+ int vpflags = dvpe();
+ write_c0_compare (read_c0_count() - 1);
+ clear_c0_cause(CPUCTR_IMASKBIT);
+ evpe(vpflags);
+
+ if (cpu_data[cpu].vpe_id == 0) {
+ timer_interrupt(irq, dev_id, regs);
+ scroll_display_message();
+ } else
+ write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+ if (cpu != 0)
+ /*
+ * Other CPUs should do profiling and process accounting
+ */
+ local_timer_interrupt(irq, dev_id, regs);
+
+#else /* CONFIG_MIPS_MT_SMTC */
if (cpu == 0) {
/*
* CPU 0 handles the global timer interrupt job and process
@@ -107,12 +155,14 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* More support needs to be added to kernel/time for
* counter/timer interrupts on multiple CPU's
*/
- write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+ write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+
/*
- * other CPUs should do profiling and process accounting
+ * Other CPUs should do profiling and process accounting
*/
- local_timer_interrupt (irq, dev_id, regs);
+ local_timer_interrupt(irq, dev_id, regs);
}
+#endif /* CONFIG_MIPS_MT_SMTC */
out:
return IRQ_HANDLED;
@@ -126,7 +176,7 @@ static unsigned int __init estimate_cpu_frequency(void)
unsigned int prid = read_c0_prid() & 0xffff00;
unsigned int count;
-#ifdef CONFIG_MIPS_SEAD
+#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_SIM)
/*
* The SEAD board doesn't have a real time clock, so we can't
* really calculate the timer frequency
@@ -211,7 +261,11 @@ void __init mips_timer_setup(struct irqaction *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);
+#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
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index fd4c143c0e2f..77ee5c6d33c1 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -20,3 +20,4 @@
#
obj-y := malta_int.o malta_setup.o
+obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index d06dc5ad6c9e..7cc0ba4f553a 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -40,7 +40,6 @@
#include <asm/mips-boards/msc01_pci.h>
#include <asm/msc01_ic.h>
-extern asmlinkage void mipsIRQ(void);
extern void mips_timer_interrupt(void);
static DEFINE_SPINLOCK(mips_irq_lock);
@@ -58,6 +57,7 @@ static inline int mips_pcibios_iack(void)
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:
MSC_READ(MSC01_PCI_IACK, irq);
irq &= 0xff;
@@ -114,13 +114,14 @@ static inline int get_int(void)
return irq;
}
-void malta_hw0_irqdispatch(struct pt_regs *regs)
+static void malta_hw0_irqdispatch(struct pt_regs *regs)
{
int irq;
irq = get_int();
- if (irq < 0)
+ if (irq < 0) {
return; /* interrupt has already been cleared */
+ }
do_IRQ(MALTA_INT_BASE+irq, regs);
}
@@ -143,6 +144,7 @@ void corehi_irqdispatch(struct pt_regs *regs)
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:
ll_msc_irq(regs);
break;
@@ -182,6 +184,92 @@ void corehi_irqdispatch(struct pt_regs *regs)
die("CoreHi interrupt", regs);
}
+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
+}
+
+/*
+ * IRQs on the Malta board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq == MIPSCPU_INT_I8259A)
+ malta_hw0_irqdispatch(regs);
+ else if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
+
static struct irqaction i8259irq = {
.handler = no_action,
.name = "XT-PIC cascade"
@@ -214,7 +302,6 @@ int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t);
void __init arch_init_irq(void)
{
- set_except_vector(0, mipsIRQ);
init_i8259_irqs();
if (!cpu_has_veic)
@@ -224,6 +311,7 @@ void __init arch_init_irq(void)
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:
if (cpu_has_veic)
init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
@@ -240,12 +328,17 @@ void __init arch_init_irq(void)
else if (cpu_has_vint) {
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,
+ (0x100 << MIPSCPU_INT_I8259A));
+ setup_irq_smtc (MIPSCPU_INT_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);
+#endif /* CONFIG_MIPS_MT_SMTC */
}
else {
- set_except_vector(0, mipsIRQ);
setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
}
diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c
new file mode 100644
index 000000000000..6c6c8eeedbce
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_smp.c
@@ -0,0 +1,128 @@
+/*
+ * Malta Platform-specific hooks for SMP operation
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.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 */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
+ */
+
+void __init prom_build_cpu_map(void)
+{
+ int nextslot;
+
+ /*
+ * As of November, 2004, MIPSsim only simulates one core
+ * at a time. However, that core may be a MIPS MT core
+ * with multiple virtual processors and thread contexts.
+ */
+
+ if (read_c0_config3() & (1<<2)) {
+ nextslot = mipsmt_build_cpu_map(1);
+ }
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_init_secondary(void);
+ int myvpe;
+
+ /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
+ myvpe = read_c0_tcbind() & TCBIND_CURVPE;
+ if (myvpe != 0) {
+ /* Ideally, this should be done only once per VPE, but... */
+ clear_c0_status(STATUSF_IP2);
+ set_c0_status(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP3
+ | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6
+ | STATUSF_IP7);
+ }
+
+ smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ *
+ * As noted above, we can assume a single CPU for now
+ * but it may be multithreaded.
+ */
+
+void plat_smp_setup(void)
+{
+ if (read_c0_config3() & (1<<2))
+ mipsmt_build_cpu_map(0);
+}
+
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
+ if (read_c0_config3() & (1<<2))
+ mipsmt_prepare_cpus();
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+}
+
+#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index 90fda0d9915f..9168d934c661 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -24,16 +24,94 @@
#include <linux/irq.h>
#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/mips-boards/seadint.h>
-extern asmlinkage void mipsIRQ(void);
+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
+}
+
+/*
+ * IRQs on the SEAD board look basically are combined together on hardware
+ * interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 UART0 (hw0)
+ * 3 UART1 (hw1)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq >= 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
void __init arch_init_irq(void)
{
mips_cpu_irq_init(MIPSCPU_INT_BASE);
-
- /* Now safe to set the exception vector. */
- set_except_vector(0, mipsIRQ);
}
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
deleted file mode 100644
index fef9fbd8e710..000000000000
--- a/arch/mips/mips-boards/sim/cmdline.c
+++ /dev/null
@@ -1,59 +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.
- *
- * Kernel command line creation using the prom monitor (YAMON) argc/argv.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-
-extern int prom_argc;
-extern int *_prom_argv;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension.
- */
-#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
-
-char arcs_cmdline[CL_SIZE];
-
-char * __init prom_getcmdline(void)
-{
- return &(arcs_cmdline[0]);
-}
-
-
-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';
-}
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
index 9df37c6fca36..c63021a5dc6c 100644
--- a/arch/mips/mips-boards/sim/sim_cmdline.c
+++ b/arch/mips/mips-boards/sim/sim_cmdline.c
@@ -26,8 +26,10 @@ char * __init prom_getcmdline(void)
return arcs_cmdline;
}
-
void __init prom_init_cmdline(void)
{
- /* nothing to do */
+ char *cp;
+ cp = arcs_cmdline;
+ /* Get boot line from environment? */
+ *cp = '\0';
}
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index a4d0a2c05031..2c15c8efec4e 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -25,17 +25,71 @@
extern void mips_cpu_irq_init(int);
-extern asmlinkage void simIRQ(void);
+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;
-asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ //t0 = t0 << 2;
+ a0 = a0 - t0;
+ //s0 = s0 << t0;
+
+ return a0;
+#endif
+}
+
+static inline void sim_hw0_irqdispatch(struct pt_regs *regs)
{
do_IRQ(2, regs);
}
-void __init arch_init_irq(void)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
- /* Now safe to set the exception vector. */
- set_except_vector(0, simIRQ);
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+ if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
+
+void __init arch_init_irq(void)
+{
mips_cpu_irq_init(MIPSCPU_INT_BASE);
}
diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S
index da52297a2216..d16cf3822076 100644
--- a/arch/mips/mips-boards/sim/sim_irq.S
+++ b/arch/mips/mips-boards/sim/sim_irq.S
@@ -94,6 +94,8 @@
spurious:
- j spurious_interrupt
+ jal spurious_interrupt
+ nop
+ j ret_from_irq
nop
END(simIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
index e57f737bab10..f7ce76983328 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -18,9 +18,11 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
+#include <asm/sections.h>
#include <asm/mips-boards/prom.h>
@@ -39,9 +41,6 @@ static char *mtypes[3] = {
};
#endif
-/* References to section boundaries */
-extern char _end;
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
unsigned int memsize;
@@ -61,10 +60,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
mdesc[2].type = simmem_reserved;
mdesc[2].base = 0x00100000;
- mdesc[2].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[2].base;
+ mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
mdesc[3].type = simmem_free;
- mdesc[3].base = CPHYSADDR(PAGE_ALIGN(&_end));
+ mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
mdesc[3].size = memsize - mdesc[3].base;
return &mdesc[0];
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
index a9f0c2bfe4ad..b7084e7c4bf9 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -44,8 +44,6 @@
void core_send_ipi(int cpu, unsigned int action)
{
#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_send_ipi(int, int, unsigned int);
-
smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
#endif /* CONFIG_MIPS_MT_SMTC */
/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
@@ -59,15 +57,8 @@ void core_send_ipi(int cpu, unsigned int action)
void __init prom_build_cpu_map(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
- extern int mipsmt_build_cpu_map(int startslot);
int nextslot;
- cpus_clear(phys_cpu_present_map);
-
- /* Register the boot CPU */
-
- smp_prepare_boot_cpu();
-
/*
* As of November, 2004, MIPSsim only simulates one core
* at a time. However, that core may be a MIPS MT core
@@ -87,8 +78,6 @@ void __init prom_build_cpu_map(void)
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
#ifdef CONFIG_MIPS_MT_SMTC
- extern void smtc_boot_secondary(int cpu, struct task_struct *t);
-
smtc_boot_secondary(cpu, idle);
#endif /* CONFIG_MIPS_MT_SMTC */
}
@@ -113,7 +102,6 @@ void prom_init_secondary(void)
void prom_prepare_cpus(unsigned int max_cpus)
{
#ifdef CONFIG_MIPS_MT_SMTC
- void mipsmt_prepare_cpus(int c);
/*
* As noted above, we can assume a single CPU for now
* but it may be multithreaded.
@@ -132,8 +120,6 @@ void prom_prepare_cpus(unsigned int max_cpus)
void prom_smp_finish(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_smp_finish(void);
-
smtc_smp_finish();
#endif /* CONFIG_MIPS_MT_SMTC */
}
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 9dd1352d5748..bb041a22f20a 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -260,6 +260,10 @@ static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page,
{
}
+static void local_r3k_flush_data_cache_page(unsigned long addr)
+{
+}
+
static void r3k_flush_data_cache_page(unsigned long addr)
{
}
@@ -335,6 +339,7 @@ void __init r3k_cache_init(void)
flush_icache_range = r3k_flush_icache_range;
flush_cache_sigtramp = r3k_flush_cache_sigtramp;
+ local_flush_data_cache_page = local_r3k_flush_data_cache_page;
flush_data_cache_page = r3k_flush_data_cache_page;
_dma_cache_wback_inv = r3k_dma_cache_wback_inv;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 32b7f6aeb983..4182e1176fae 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -154,7 +154,8 @@ static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
static inline void tx49_blast_icache32_page_indexed(unsigned long page)
{
- unsigned long start = page;
+ unsigned long indexmask = current_cpu_data.icache.waysize - 1;
+ unsigned long start = INDEX_BASE + (page & indexmask);
unsigned long end = start + PAGE_SIZE;
unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -749,12 +750,12 @@ static void __init probe_pcache(void)
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 2;
- c->icache.waybit = ffs(icache_size/2) - 1;
+ c->icache.waybit = __ffs(icache_size/2);
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
- c->dcache.waybit= ffs(dcache_size/2) - 1;
+ c->dcache.waybit= __ffs(dcache_size/2);
c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
@@ -837,12 +838,12 @@ static void __init probe_pcache(void)
icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 2;
- c->icache.waybit = ffs(icache_size/2) - 1;
+ c->icache.waybit = __ffs(icache_size/2);
dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
- c->dcache.waybit = ffs(dcache_size/2) - 1;
+ c->dcache.waybit = __ffs(dcache_size/2);
c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
@@ -873,12 +874,12 @@ static void __init probe_pcache(void)
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 4;
- c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+ c->icache.waybit = __ffs(icache_size / c->icache.ways);
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 4;
- c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+ c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
#if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
c->options |= MIPS_CPU_CACHE_CDEX_P;
@@ -906,7 +907,7 @@ static void __init probe_pcache(void)
icache_size = c->icache.sets *
c->icache.ways *
c->icache.linesz;
- c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
+ c->icache.waybit = __ffs(icache_size/c->icache.ways);
if (config & 0x8) /* VI bit */
c->icache.flags |= MIPS_CACHE_VTAG;
@@ -926,7 +927,7 @@ static void __init probe_pcache(void)
dcache_size = c->dcache.sets *
c->dcache.ways *
c->dcache.linesz;
- c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+ c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
c->options |= MIPS_CPU_PREFETCH;
break;
@@ -1198,6 +1199,7 @@ void __init r4k_cache_init(void)
flush_cache_sigtramp = r4k_flush_cache_sigtramp;
flush_icache_all = r4k_flush_icache_all;
+ local_flush_data_cache_page = local_r4k_flush_data_cache_page;
flush_data_cache_page = r4k_flush_data_cache_page;
flush_icache_range = r4k_flush_icache_range;
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 2f08b535f20e..f9b129491b1e 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -528,6 +528,7 @@ void sb1_cache_init(void)
flush_cache_page = sb1_flush_cache_page;
flush_cache_sigtramp = sb1_flush_cache_sigtramp;
+ local_flush_data_cache_page = (void *) sb1_nop;
flush_data_cache_page = (void *) sb1_nop;
/* Full flush */
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index fe232e3988e3..5dfc9b1901f6 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -216,6 +216,11 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
tx39_blast_icache_page_indexed(page);
}
+static void local_tx39_flush_data_cache_page(void * addr)
+{
+ tx39_blast_dcache_page(addr);
+}
+
static void tx39_flush_data_cache_page(unsigned long addr)
{
tx39_blast_dcache_page(addr);
@@ -381,6 +386,7 @@ void __init tx39_cache_init(void)
flush_icache_range = (void *) tx39h_flush_icache_all;
flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
+ local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
flush_data_cache_page = (void *) tx39h_flush_icache_all;
_dma_cache_wback_inv = tx39h_dma_cache_wback_inv;
@@ -406,6 +412,7 @@ void __init tx39_cache_init(void)
flush_icache_range = tx39_flush_icache_range;
flush_cache_sigtramp = tx39_flush_cache_sigtramp;
+ local_flush_data_cache_page = local_tx39_flush_data_cache_page;
flush_data_cache_page = tx39_flush_data_cache_page;
_dma_cache_wback_inv = tx39_dma_cache_wback_inv;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 591c22b080e4..83a56296be86 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -30,6 +30,7 @@ void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
/* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr);
+void (*local_flush_data_cache_page)(void * addr);
void (*flush_data_cache_page)(unsigned long addr);
void (*flush_icache_all)(void);
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 2d9624fd10ec..e3a617224868 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -157,7 +157,6 @@ no_context:
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/
-
bust_spinlocks(1);
printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at "
@@ -188,11 +187,20 @@ do_sigbus:
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs))
goto no_context;
-
+ else
/*
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
+#if 0
+ printk("do_page_fault() #3: sending SIGBUS to %s for "
+ "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
+ tsk->comm,
+ write ? "write access to" : "read access from",
+ field, address,
+ field, (unsigned long) regs->cp0_epc,
+ field, (unsigned long) regs->regs[31]);
+#endif
tsk->thread.cp0_badvaddr = address;
info.si_signo = SIGBUS;
info.si_errno = 0;
@@ -201,7 +209,6 @@ do_sigbus:
force_sig_info(SIGBUS, &info, tsk);
return;
-
vmalloc_fault:
{
/*
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 1f7b37b38f5c..0c544375b856 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
preempt_check_resched();
}
+#ifndef CONFIG_LIMITED_DMA
/*
* This is the same as kmap_atomic() but can map memory that doesn't
* have a struct page associated with it.
@@ -101,6 +102,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
return (void*) vaddr;
}
+#endif /* CONFIG_LIMITED_DMA */
struct page *__kmap_atomic_to_page(void *ptr)
{
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index ad89c442f299..c22308b93ff0 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -276,6 +276,20 @@ void __init mem_init(void)
}
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+ unsigned long addr;
+
+ for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ init_page_count(virt_to_page(addr));
+ memset((void *)addr, 0xcc, PAGE_SIZE);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
@@ -284,16 +298,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
start = (unsigned long)phys_to_virt(CPHYSADDR(start));
end = (unsigned long)phys_to_virt(CPHYSADDR(end));
#endif
- if (start < end)
- printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
- (end - start) >> 10);
-
- for (; start < end; start += PAGE_SIZE) {
- ClearPageReserved(virt_to_page(start));
- init_page_count(virt_to_page(start));
- free_page(start);
- totalram_pages++;
- }
+ free_init_pages("initrd memory", start, end);
}
#endif
@@ -301,24 +306,17 @@ extern unsigned long prom_free_prom_memory(void);
void free_initmem(void)
{
- unsigned long addr, page, freed;
+ unsigned long start, end, freed;
freed = prom_free_prom_memory();
+ if (freed)
+ printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
- addr = (unsigned long) &__init_begin;
- while (addr < (unsigned long) &__init_end) {
+ start = (unsigned long)(&__init_begin);
+ end = (unsigned long)(&__init_end);
#ifdef CONFIG_64BIT
- page = PAGE_OFFSET | CPHYSADDR(addr);
-#else
- page = addr;
+ start = PAGE_OFFSET | CPHYSADDR(start);
+ end = PAGE_OFFSET | CPHYSADDR(end);
#endif
- ClearPageReserved(virt_to_page(page));
- init_page_count(virt_to_page(page));
- free_page(page);
- totalram_pages++;
- freed += PAGE_SIZE;
- addr += PAGE_SIZE;
- }
- printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
- freed >> 10);
+ free_init_pages("unused kernel memory", start, end);
}
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 3b6cc9ba1b05..31ec73052423 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -138,7 +138,7 @@ void __init rm7k_sc_init(void)
c->scache.linesz = sc_lsize;
c->scache.ways = 4;
- c->scache.waybit= ffs(scache_size / c->scache.ways) - 1;
+ c->scache.waybit= __ffs(scache_size / c->scache.ways);
c->scache.waysize = scache_size / c->scache.ways;
c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index a865f2394cb0..9dca099ba16b 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -32,13 +32,35 @@ extern void build_tlb_refill_handler(void);
"nop; nop; nop; nop; nop; nop;\n\t" \
".set reorder\n\t")
+/* Atomicity and interruptability */
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#include <asm/smtc.h>
+#include <asm/mipsmtregs.h>
+
+#define ENTER_CRITICAL(flags) \
+ { \
+ unsigned int mvpflags; \
+ local_irq_save(flags);\
+ mvpflags = dvpe()
+#define EXIT_CRITICAL(flags) \
+ evpe(mvpflags); \
+ local_irq_restore(flags); \
+ }
+#else
+
+#define ENTER_CRITICAL(flags) local_irq_save(flags)
+#define EXIT_CRITICAL(flags) local_irq_restore(flags)
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
void local_flush_tlb_all(void)
{
unsigned long flags;
unsigned long old_ctx;
int entry;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
write_c0_entrylo0(0);
@@ -57,7 +79,7 @@ void local_flush_tlb_all(void)
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
/* All entries common to a mm share an asid. To effectively flush
@@ -87,6 +109,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long flags;
int size;
+ ENTER_CRITICAL(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
local_irq_save(flags);
@@ -120,7 +143,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
} else {
drop_mmu_context(mm, cpu);
}
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
}
@@ -129,9 +152,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
unsigned long flags;
int size;
+ ENTER_CRITICAL(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
- local_irq_save(flags);
if (size <= current_cpu_data.tlbsize / 2) {
int pid = read_c0_entryhi();
@@ -162,7 +185,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
} else {
local_flush_tlb_all();
}
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -175,7 +198,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
newpid = cpu_asid(cpu, vma->vm_mm);
page &= (PAGE_MASK << 1);
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
oldpid = read_c0_entryhi();
write_c0_entryhi(page | newpid);
mtc0_tlbw_hazard();
@@ -194,7 +217,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
}
@@ -207,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
unsigned long flags;
int oldpid, idx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
oldpid = read_c0_entryhi();
page &= (PAGE_MASK << 1);
write_c0_entryhi(page);
@@ -226,7 +249,7 @@ void local_flush_tlb_one(unsigned long page)
}
write_c0_entryhi(oldpid);
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
/*
@@ -249,7 +272,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
if (current->active_mm != vma->vm_mm)
return;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
pid = read_c0_entryhi() & ASID_MASK;
address &= (PAGE_MASK << 1);
@@ -277,7 +300,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
else
tlb_write_indexed();
tlbw_use_hazard();
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
#if 0
@@ -291,7 +314,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
pte_t *ptep;
int idx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
address &= (PAGE_MASK << 1);
asid = read_c0_entryhi() & ASID_MASK;
write_c0_entryhi(address | asid);
@@ -310,7 +333,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
else
tlb_write_indexed();
tlbw_use_hazard();
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
#endif
@@ -322,7 +345,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
unsigned long old_pagemask;
unsigned long old_ctx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
@@ -342,7 +365,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
BARRIER;
write_c0_pagemask(old_pagemask);
local_flush_tlb_all();
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
/*
@@ -362,7 +385,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
unsigned long old_pagemask;
unsigned long old_ctx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
@@ -386,10 +409,11 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
write_c0_entryhi(old_ctx);
write_c0_pagemask(old_pagemask);
out:
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
return ret;
}
+extern void __init sanitize_tlb_entries(void);
static void __init probe_tlb(unsigned long config)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -402,6 +426,14 @@ static void __init probe_tlb(unsigned long config)
*/
if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
return;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * If TLB is shared in SMTC system, total size already
+ * has been calculated and written into cpu_data tlbsize
+ */
+ if((smtc_status & SMTC_TLB_SHARED) == SMTC_TLB_SHARED)
+ return;
+#endif /* CONFIG_MIPS_MT_SMTC */
reg = read_c0_config1();
if (!((config >> 7) & 3))
@@ -410,6 +442,15 @@ static void __init probe_tlb(unsigned long config)
c->tlbsize = ((reg >> 25) & 0x3f) + 1;
}
+static int __initdata ntlb = 0;
+static int __init set_ntlb(char *str)
+{
+ get_option(&str, &ntlb);
+ return 1;
+}
+
+__setup("ntlb=", set_ntlb);
+
void __init tlb_init(void)
{
unsigned int config = read_c0_config();
@@ -432,5 +473,15 @@ void __init tlb_init(void)
/* Did I tell you that ARC SUCKS? */
+ if (ntlb) {
+ if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
+ int wired = current_cpu_data.tlbsize - ntlb;
+ write_c0_wired(wired);
+ write_c0_index(wired-1);
+ printk ("Restricting TLB to %d entries\n", ntlb);
+ } else
+ printk("Ignoring invalid argument ntlb=%d\n", ntlb);
+ }
+
build_tlb_refill_handler();
}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 599b3c297186..053dbacac56b 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -7,6 +7,16 @@
*
* Copyright (C) 2004,2005 by Thiemo Seufer
* Copyright (C) 2005 Maciej W. Rozycki
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * ... and the days got worse and worse and now you see
+ * I've gone completly out of my mind.
+ *
+ * They're coming to take me a away haha
+ * they're coming to take me a away hoho hihi haha
+ * to the funny farm where code is beautiful all the time ...
+ *
+ * (Condolences to Napoleon XIV)
*/
#include <stdarg.h>
@@ -68,6 +78,7 @@ enum fields
BIMM = 0x040,
JIMM = 0x080,
FUNC = 0x100,
+ SET = 0x200
};
#define OP_MASK 0x2f
@@ -86,6 +97,8 @@ enum fields
#define JIMM_SH 0
#define FUNC_MASK 0x2f
#define FUNC_SH 0
+#define SET_MASK 0x7
+#define SET_SH 0
enum opcode {
insn_invalid,
@@ -129,8 +142,8 @@ static __initdata struct insn insn_table[] = {
{ insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
{ insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
{ insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
- { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD },
- { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD },
+ { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET},
+ { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET},
{ insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
{ insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
{ insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
@@ -145,8 +158,8 @@ static __initdata struct insn insn_table[] = {
{ insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
{ insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
{ insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD },
- { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD },
+ { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET},
+ { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET},
{ insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
{ insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
{ insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
@@ -242,6 +255,14 @@ static __init u32 build_func(u32 arg)
return arg & FUNC_MASK;
}
+static __init u32 build_set(u32 arg)
+{
+ if (arg & ~SET_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return arg & SET_MASK;
+}
+
/*
* The order of opcode arguments is implicitly left to right,
* starting with RS and ending with FUNC or IMM.
@@ -273,6 +294,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...)
if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
+ if (ip->fields & SET) op |= build_set(va_arg(ap, u32));
va_end(ap);
**buf = op;
@@ -358,8 +380,8 @@ I_u1s2(_bgezl);
I_u1s2(_bltz);
I_u1s2(_bltzl);
I_u1u2s3(_bne);
-I_u1u2(_dmfc0);
-I_u1u2(_dmtc0);
+I_u1u2u3(_dmfc0);
+I_u1u2u3(_dmtc0);
I_u2u1s3(_daddiu);
I_u3u1u2(_daddu);
I_u2u1u3(_dsll);
@@ -376,8 +398,8 @@ I_u2s3u1(_ll);
I_u2s3u1(_lld);
I_u1s2(_lui);
I_u2s3u1(_lw);
-I_u1u2(_mfc0);
-I_u1u2(_mtc0);
+I_u1u2u3(_mfc0);
+I_u1u2u3(_mtc0);
I_u2u1u3(_ori);
I_0(_rfe);
I_u2s3u1(_sc);
@@ -451,8 +473,8 @@ L_LA(_r3000_write_probe_fail)
# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
# define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
# define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd)
# define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
# define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
# define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
@@ -464,8 +486,8 @@ L_LA(_r3000_write_probe_fail)
# define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
# define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
# define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd)
# define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
# define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
# define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
@@ -670,14 +692,15 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
#define K1 27
/* Some CP0 registers */
-#define C0_INDEX 0
-#define C0_ENTRYLO0 2
-#define C0_ENTRYLO1 3
-#define C0_CONTEXT 4
-#define C0_BADVADDR 8
-#define C0_ENTRYHI 10
-#define C0_EPC 14
-#define C0_XCONTEXT 20
+#define C0_INDEX 0, 0
+#define C0_ENTRYLO0 2, 0
+#define C0_TCBIND 2, 2
+#define C0_ENTRYLO1 3, 0
+#define C0_CONTEXT 4, 0
+#define C0_BADVADDR 8, 0
+#define C0_ENTRYHI 10, 0
+#define C0_EPC 14, 0
+#define C0_XCONTEXT 20, 0
#ifdef CONFIG_64BIT
# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
@@ -742,7 +765,7 @@ static void __init build_r3000_tlb_refill_handler(void)
}
#endif
- memcpy((void *)CAC_BASE, tlb_handler, 0x80);
+ memcpy((void *)ebase, tlb_handler, 0x80);
}
/*
@@ -951,12 +974,20 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
/* No i_nop needed here, since the next insn doesn't touch TMP. */
#ifdef CONFIG_SMP
+# ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC uses TCBind value as "CPU" index
+ */
+ i_mfc0(p, ptr, C0_TCBIND);
+ i_dsrl(p, ptr, ptr, 19);
+# else
/*
* 64 bit SMP running in XKPHYS has smp_processor_id() << 3
* stored in CONTEXT.
*/
i_dmfc0(p, ptr, C0_CONTEXT);
i_dsrl(p, ptr, ptr, 23);
+#endif
i_LA_mostly(p, tmp, pgdc);
i_daddu(p, ptr, ptr, tmp);
i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1014,9 +1045,21 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
#ifdef CONFIG_SMP
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC uses TCBind value as "CPU" index
+ */
+ i_mfc0(p, ptr, C0_TCBIND);
+ i_LA_mostly(p, tmp, pgdc);
+ i_srl(p, ptr, ptr, 19);
+#else
+ /*
+ * smp_processor_id() << 3 is stored in CONTEXT.
+ */
i_mfc0(p, ptr, C0_CONTEXT);
i_LA_mostly(p, tmp, pgdc);
i_srl(p, ptr, ptr, 23);
+#endif
i_addu(p, ptr, tmp, ptr);
#else
i_LA_mostly(p, ptr, pgdc);
@@ -1247,7 +1290,7 @@ static void __init build_r4000_tlb_refill_handler(void)
}
#endif
- memcpy((void *)CAC_BASE, final_handler, 0x100);
+ memcpy((void *)ebase, final_handler, 0x100);
}
/*
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
index 20bbd3ea44a8..67372f3f9654 100644
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ b/arch/mips/momentum/jaguar_atx/Makefile
@@ -6,7 +6,7 @@
# unless it's something special (ie not a .c file).
#
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
deleted file mode 100644
index 55bc789733f2..000000000000
--- a/arch/mips/momentum/jaguar_atx/int-handler.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work:
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Jaguar-ATX board.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
- .align 5
- NESTED(jaguar_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */
- bnez t1, ll_sw0_irq
- andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */
- bnez t1, ll_sw1_irq
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_pcixa_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_pcixb_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_pcia_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_pcib_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_uart_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- nop
- nop
-
- /* now look at extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line */
- bnez t1, ll_mv64340_decode_irq
-
- nop
- nop
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(jaguar_handle_int)
-
- .align 5
-ll_sw0_irq:
- li a0, 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_sw1_irq:
- li a0, 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_pcixa_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pcixb_irq:
- li a0, 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pcia_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pcib_irq:
- li a0, 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_irq:
- li a0, 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal ll_timer_interrupt
- j ret_from_irq
-
-ll_mv64340_decode_irq:
- move a0, sp
- jal ll_mv64340_irq
- j ret_from_irq
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
index 15588f91ace2..ec4032b38f19 100644
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -10,7 +10,7 @@
* 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) 2000, 01, 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
@@ -38,8 +38,37 @@
#include <linux/types.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
+#include <asm/time.h>
-extern asmlinkage void jaguar_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(1, regs);
+ else if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7)
+ ll_timer_interrupt(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+ if (pending & STATUSF_IP8)
+ ll_mv64340_irq(regs);
+ }
+}
static struct irqaction cascade_mv64340 = {
no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
@@ -53,8 +82,6 @@ void __init arch_init_irq(void)
*/
clear_c0_status(ST0_IM);
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, jaguar_handle_int);
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 91d9637143d7..1379c76845dc 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -381,24 +381,24 @@ void __init plat_setup(void)
* shut down ethernet ports, just to be sure our memory doesn't get
* corrupted by random ethernet traffic.
*/
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
+ 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_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 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);
+ MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2),
+ MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
/* Turn off the Bit-Error LED */
JAGUAR_FPGA_WRITE(0x80, CLR);
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
index aab8fd89f830..8bcea64dd27b 100644
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ b/arch/mips/momentum/ocelot_3/Makefile
@@ -5,4 +5,4 @@
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/int-handler.S b/arch/mips/momentum/ocelot_3/int-handler.S
deleted file mode 100644
index 4522f09ed769..000000000000
--- a/arch/mips/momentum/ocelot_3/int-handler.S
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.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
- *
- * First-level interrupt dispatcher for Ocelot-3 board.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-3 board
- */
- .align 5
- NESTED(ocelot3_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP0 /* sw0 software interrupt (IRQ0) */
- bnez t1, ll_sw0_irq
-
- andi t1, t0, STATUSF_IP1 /* sw1 software interrupt (IRQ1) */
- bnez t1, ll_sw1_irq
-
- andi t1, t0, STATUSF_IP2 /* int0 hardware line (IRQ2) */
- bnez t1, ll_pci0slot1_irq
-
- andi t1, t0, STATUSF_IP3 /* int1 hardware line (IRQ3) */
- bnez t1, ll_pci0slot2_irq
-
- andi t1, t0, STATUSF_IP4 /* int2 hardware line (IRQ4) */
- bnez t1, ll_pci1slot1_irq
-
- andi t1, t0, STATUSF_IP5 /* int3 hardware line (IRQ5) */
- bnez t1, ll_pci1slot2_irq
-
- andi t1, t0, STATUSF_IP6 /* int4 hardware line (IRQ6) */
- bnez t1, ll_uart_irq
-
- andi t1, t0, STATUSF_IP7 /* cpu timer (IRQ7) */
- bnez t1, ll_cputimer_irq
-
- /* now look at extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line (IRQ9) */
- bnez t1, ll_mv64340_decode_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot3_handle_int)
-
- .align 5
-ll_sw0_irq:
- li a0, 0 /* IRQ 1 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_sw1_irq:
- li a0, 1 /* IRQ 2 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci0slot1_irq:
- li a0, 2 /* IRQ 3 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci0slot2_irq:
- li a0, 3 /* IRQ 4 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci1slot1_irq:
- li a0, 4 /* IRQ 5 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci1slot2_irq:
- li a0, 5 /* IRQ 6 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_irq:
- li a0, 6 /* IRQ 7 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7 /* IRQ 8 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_mv64340_decode_irq:
- move a0, sp
- jal ll_mv64340_irq
- j ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
index 42464dbd4ad2..87c63c340ae3 100644
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -53,8 +53,6 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot3_handle_int(void);
-
static struct irqaction cascade_mv64340 = {
no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
};
@@ -67,9 +65,6 @@ void __init arch_init_irq(void)
*/
clear_c0_status(ST0_IM | ST0_BEV);
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot3_handle_int);
- mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
/* set up the cascading interrupts */
@@ -79,3 +74,36 @@ void __init arch_init_irq(void)
set_c0_status(ST0_IM); /* IE in the status register */
}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(1, regs);
+ else if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7)
+ do_IRQ(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+ if (pending & STATUSF_IP8)
+ ll_mv64340_irq(regs);
+ else
+ spurious_interrupt(regs);
+ }
+}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index 370e75d0e75c..c69195234309 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -329,22 +329,22 @@ void __init plat_setup(void)
/* shut down ethernet ports, just to be sure our memory doesn't get
* corrupted by random ethernet traffic.
*/
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ 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(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
do {}
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
do {}
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
do {}
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+ 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);
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
index 91240777f978..94802b4db472 100644
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ b/arch/mips/momentum/ocelot_c/Makefile
@@ -2,7 +2,7 @@
# Makefile for Momentum Computer's Ocelot-C and -CS boards.
#
-obj-y += cpci-irq.o int-handler.o irq.o prom.o reset.o \
+obj-y += cpci-irq.o irq.o prom.o reset.o \
setup.o uart-irq.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
deleted file mode 100644
index 52349d9bf1be..000000000000
--- a/arch/mips/momentum/ocelot_c/int-handler.S
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Ocelot-CS board.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include "ocelot_c_fpga.h"
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
- .align 5
- NESTED(ocelot_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */
- bnez t1, ll_sw0_irq
- andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */
- bnez t1, ll_sw1_irq
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_scsi_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_uart_decode_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_pmc_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_cpci_decode_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_mv64340_decode_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot_handle_int)
-
- .align 5
-ll_sw0_irq:
- li a0, 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_sw1_irq:
- li a0, 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_scsi_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_decode_irq:
- move a0, sp
- jal ll_uart_irq
- j ret_from_irq
-
-ll_pmc_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_decode_irq:
- move a0, sp
- jal ll_cpci_irq
- j ret_from_irq
-
-ll_mv64340_decode_irq:
- move a0, sp
- jal ll_mv64340_irq
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
index a5764bc20e36..86f61ce59e53 100644
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -48,7 +48,6 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot_handle_int(void);
extern void uart_irq_init(void);
extern void cpci_irq_init(void);
@@ -60,6 +59,33 @@ static struct irqaction cascade_mv64340 = {
no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
};
+extern void ll_uart_irq(struct pt_regs *regs);
+extern void ll_cpci_irq(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(1, regs);
+ else if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ ll_uart_irq(regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ ll_cpci_irq(regs);
+ else if (pending & STATUSF_IP6)
+ ll_mv64340_irq(regs);
+ else if (pending & STATUSF_IP7)
+ do_IRQ(7, regs);
+ else
+ spurious_interrupt(regs);
+}
+
void __init arch_init_irq(void)
{
/*
@@ -68,8 +94,6 @@ void __init arch_init_irq(void)
*/
clear_c0_status(ST0_IM);
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot_handle_int);
mips_cpu_irq_init(0);
/* set up the cascading interrupts */
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
index e5f1cb086973..adb5665d40a9 100644
--- a/arch/mips/momentum/ocelot_g/Makefile
+++ b/arch/mips/momentum/ocelot_g/Makefile
@@ -2,7 +2,7 @@
# Makefile for Momentum Computer's Ocelot-G board.
#
-obj-y += int-handler.o irq.o gt-irq.o prom.o reset.o setup.o
+obj-y += irq.o gt-irq.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S
deleted file mode 100644
index 772e8f713176..000000000000
--- a/arch/mips/momentum/ocelot_g/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ocelot_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_pri_enet_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_sec_enet_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_uart_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_cpci_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_galileo_p0_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- /* now look at the extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line */
- bnez t1, ll_galileo_p1_irq
- andi t1, t0, STATUSF_IP9 /* int7 hardware line */
- bnez t1, ll_pmc_irq
- andi t1, t0, STATUSF_IP10 /* int8 hardware line */
- bnez t1, ll_cpci_abcd_irq
- andi t1, t0, STATUSF_IP11 /* int9 hardware line */
- bnez t1, ll_testpoint_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot_handle_int)
-
- .align 5
-ll_pri_enet_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_sec_enet_irq:
- li a0, 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_irq:
- li a0, 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_galileo_p0_irq:
- li a0, 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_galileo_p1_irq:
- li a0, 8
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pmc_irq:
- li a0, 9
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_abcd_irq:
- li a0, 10
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_testpoint_irq:
- li a0, 11
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
index 5eb85b164205..7a4a419804f1 100644
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -48,7 +48,41 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7)
+ do_IRQ(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+ if (pending & STATUSF_IP8)
+ do_IRQ(8, regs);
+ else if (pending & STATUSF_IP9)
+ do_IRQ(9, regs);
+ else if (pending & STATUSF_IP10)
+ do_IRQ(10, regs);
+ else if (pending & STATUSF_IP11)
+ do_IRQ(11, regs);
+ else
+ spurious_interrupt(regs);
+ }
+}
+
extern void gt64240_irq_init(void);
void __init arch_init_irq(void)
@@ -60,8 +94,6 @@ void __init arch_init_irq(void)
clear_c0_status(ST0_IM);
local_irq_disable();
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot_handle_int);
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 935dd851f480..f2b4862aaae5 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -27,7 +27,7 @@ static int op_mips_setup(void)
model->reg_setup(ctr);
/* Configure the registers on all cpus. */
- on_each_cpu(model->cpu_setup, 0, 0, 1);
+ on_each_cpu(model->cpu_setup, NULL, 0, 1);
return 0;
}
@@ -114,5 +114,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
void oprofile_arch_exit(void)
{
- model->exit();
+ if (model)
+ model->exit();
}
diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
index 6e38f3bc443c..b7c638166e9f 100644
--- a/arch/mips/philips/pnx8550/common/Makefile
+++ b/arch/mips/philips/pnx8550/common/Makefile
@@ -22,6 +22,6 @@
# under Linux.
#
-obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index c500e2d41f2c..39ee6314f627 100644
--- a/arch/mips/philips/pnx8550/common/int.c
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -38,8 +38,6 @@
#include <int.h>
#include <uart.h>
-extern asmlinkage void cp0_irqdispatch(void);
-
static DEFINE_SPINLOCK(irq_lock);
/* default prio for interrupts */
@@ -55,7 +53,7 @@ static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
1 // 70
};
-void hw0_irqdispatch(int irq, struct pt_regs *regs)
+static void hw0_irqdispatch(int irq, struct pt_regs *regs)
{
/* find out which interrupt */
irq = PNX8550_GIC_VECTOR_0 >> 3;
@@ -68,7 +66,7 @@ void hw0_irqdispatch(int irq, struct pt_regs *regs)
}
-void timer_irqdispatch(int irq, struct pt_regs *regs)
+static void timer_irqdispatch(int irq, struct pt_regs *regs)
{
irq = (0x01c0 & read_c0_config7()) >> 6;
@@ -88,6 +86,20 @@ void timer_irqdispatch(int irq, struct pt_regs *regs)
}
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP7) {
+ if (read_c0_config7() & 0x01c0)
+ timer_irqdispatch(7, regs);
+ }
+
+ spurious_interrupt(regs);
+}
+
static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
{
unsigned long status = read_c0_status();
@@ -223,9 +235,6 @@ void __init arch_init_irq(void)
int i;
int configPR;
- /* init of cp0 interrupts */
- set_except_vector(0, cp0_irqdispatch);
-
for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
irq_desc[i].handler = &level_irq_type;
pnx8550_ack(i); /* mask the irq just in case */
diff --git a/arch/mips/philips/pnx8550/common/mipsIRQ.S b/arch/mips/philips/pnx8550/common/mipsIRQ.S
deleted file mode 100644
index 338bffda3fab..000000000000
--- a/arch/mips/philips/pnx8550/common/mipsIRQ.S
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2002 Philips, Inc. All rights.
- * Copyright (c) 2002 Red Hat, Inc. All rights.
- *
- * This software may be freely redistributed under the terms of the
- * GNU General Public License.
- *
- * You 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.
- *
- * Based upon arch/mips/galileo-boards/ev64240/int-handler.S
- *
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * cp0_irqdispatch
- *
- * Code to handle in-core interrupt exception.
- */
-
- .align 5
- .set reorder
- .set noat
- NESTED(cp0_irqdispatch, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0,CP0_CAUSE
- mfc0 t2,CP0_STATUS
-
- and t0,t2
-
- andi t1,t0,STATUSF_IP2 /* int0 hardware line */
- bnez t1,ll_hw0_irq
- nop
-
- andi t1,t0,STATUSF_IP7 /* int5 hardware line */
- bnez t1,ll_timer_irq
- nop
-
- /* wrong alarm or masked ... */
-
- j spurious_interrupt
- nop
- END(cp0_irqdispatch)
-
- .align 5
- .set reorder
-ll_hw0_irq:
- li a0,2
- move a1,sp
- jal hw0_irqdispatch
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_timer_irq:
- mfc0 t3,CP0_CONFIG,7
- andi t4,t3,0x01c0
- beqz t4,ll_timer_out
- nop
- li a0,7
- move a1,sp
- jal timer_irqdispatch
- nop
-
-ll_timer_out: j ret_from_irq
- nop
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index a592260fd673..5436b4b97455 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -18,6 +18,7 @@
#include <linux/resource.h>
#include <linux/serial.h>
#include <linux/serial_ip3106.h>
+#include <linux/platform_device.h>
#include <int.h>
#include <usb.h>
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
index ae96a71a3089..e931e0d44229 100644
--- a/arch/mips/pmc-sierra/yosemite/Makefile
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PMC-Sierra Titan
#
-obj-y += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+obj-y += irq.o i2c-yosemite.o prom.o py-console.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
deleted file mode 100644
index 33b9c40d4f5c..000000000000
--- a/arch/mips/pmc-sierra/yosemite/irq-handler.S
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2003, 04 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com
- * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
- *
- * First-level interrupt router for the PMC-Sierra Titan board
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
- * line is shared between the PCI slot A and Hypertransport. This is the
- * Processor INTB #0.
- */
-
-#include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .align 5
- NESTED(titan_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- la ra, ret_from_irq
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t2, t0, STATUSF_IP7 /* INTB5 hardware line */
- bnez t2, ll_timer_irq /* Timer */
- andi t1, t0, STATUSF_IP2 /* INTB0 hardware line */
- bnez t1, ll_pcia_irq /* 64-bit PCI */
- andi t2, t0, STATUSF_IP3 /* INTB1 hardware line */
- bnez t2, ll_pcib_irq /* second 64-bit PCI slot */
- andi t1, t0, STATUSF_IP4 /* INTB2 hardware line */
- bnez t1, ll_duart_irq /* UART */
- andi t2, t0, STATUSF_IP5 /* SMP inter-core interrupts */
- bnez t2, ll_smp_irq
- andi t1, t0, STATUSF_IP6
- bnez t1, ll_ht_irq /* Hypertransport */
-
- move a0, sp
- j do_extended_irq
- END(titan_handle_int)
-
- .set reorder
- .align 5
-
-ll_pcia_irq:
- li a0, 2
- move a1, sp
-#ifdef CONFIG_HYPERTRANSPORT
- j ll_ht_smp_irq_handler
-#else
- j do_IRQ
-#endif
-
-ll_pcib_irq:
- li a0, 3
- move a1, sp
- j do_IRQ
-
-ll_duart_irq:
- li a0, 4
- move a1, sp
- j do_IRQ
-
-ll_smp_irq:
- li a0, 5
- move a1, sp
-#ifdef CONFIG_SMP
- j titan_mailbox_irq
-#else
- j do_IRQ
-#endif
-
-ll_ht_irq:
- li a0, 6
- move a1, sp
- j ll_ht_smp_irq_handler
-
-ll_timer_irq:
- li a0, 7
- move a1, sp
- j do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
index f4e2897d9bf7..a1f524fc4c10 100644
--- a/arch/mips/pmc-sierra/yosemite/irq.c
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -2,6 +2,8 @@
* Copyright (C) 2003 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
+ * Copyright (C) 2006 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
@@ -55,7 +57,6 @@
#define HYPERTRANSPORT_INTC 0x7a /* INTC# */
#define HYPERTRANSPORT_INTD 0x7b /* INTD# */
-extern asmlinkage void titan_handle_int(void);
extern void jaguar_mailbox_irq(struct pt_regs *);
/*
@@ -125,6 +126,35 @@ asmlinkage void do_extended_irq(struct pt_regs *regs)
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int cause = read_c0_cause();
+ unsigned int status = read_c0_status();
+ unsigned int pending = cause & status;
+
+ if (pending & STATUSF_IP7) {
+ do_IRQ(7, regs);
+ } else if (pending & STATUSF_IP2) {
+#ifdef CONFIG_HYPERTRANSPORT
+ ll_ht_smp_irq_handler(2, regs);
+#else
+ do_IRQ(2, regs);
+#endif
+ } else if (pending & STATUSF_IP3) {
+ do_IRQ(3, regs);
+ } else if (pending & STATUSF_IP4) {
+ do_IRQ(4, regs);
+ } else if (pending & STATUSF_IP5) {
+#ifdef CONFIG_SMP
+ titan_mailbox_irq(regs);
+#else
+ do_IRQ(5, regs);
+#endif
+ } else if (pending & STATUSF_IP6) {
+ do_IRQ(4, regs);
+ }
+}
+
#ifdef CONFIG_KGDB
extern void init_second_port(void);
#endif
@@ -136,7 +166,6 @@ void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
- set_except_vector(0, titan_handle_int);
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
rm9k_cpu_irq_init(12);
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
index 6a8e8bcef552..730f459f3e99 100644
--- a/arch/mips/qemu/Makefile
+++ b/arch/mips/qemu/Makefile
@@ -2,6 +2,6 @@
# Makefile for Qemu specific kernel interface routines under Linux.
#
-obj-y = q-firmware.o q-int.o q-irq.o q-mem.o q-setup.o
+obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o
obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-int.S b/arch/mips/qemu/q-int.S
deleted file mode 100644
index 6e3dfe5eb14b..000000000000
--- a/arch/mips/qemu/q-int.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Qemu interrupt handler code.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .align 5
- NESTED(qemu_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- move a0, sp
- PTR_LA ra, ret_from_irq
- j do_qemu_int
- END(qemu_handle_int)
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 2c4e0704ff10..3352374c4c7d 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -9,7 +9,7 @@
extern asmlinkage void qemu_handle_int(void);
-asmlinkage void do_qemu_int(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_status() & read_c0_cause();
@@ -29,7 +29,6 @@ asmlinkage void do_qemu_int(struct pt_regs *regs)
void __init arch_init_irq(void)
{
- set_except_vector(0, qemu_handle_int);
mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK; /* 100MHz */
init_i8259_irqs();
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index eb0820fe50bd..6aa4c0cd169c 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -3,7 +3,7 @@
# under Linux.
#
-obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
+obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
obj-$(CONFIG_EISA) += ip22-eisa.o
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index d16fb43b1a93..fc6a7e2b189c 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -37,7 +37,6 @@ static char lc1msk_to_irqnr[256];
static char lc2msk_to_irqnr[256];
static char lc3msk_to_irqnr[256];
-extern asmlinkage void indyIRQ(void);
extern int ip22_eisa_init(void);
static void enable_local0_irq(unsigned int irq)
@@ -224,7 +223,7 @@ static struct hw_interrupt_type ip22_local3_irq_type = {
.end = end_local3_irq,
};
-void indy_local0_irqdispatch(struct pt_regs *regs)
+static void indy_local0_irqdispatch(struct pt_regs *regs)
{
u8 mask = sgint->istat0 & sgint->imask0;
u8 mask2;
@@ -242,7 +241,7 @@ void indy_local0_irqdispatch(struct pt_regs *regs)
return;
}
-void indy_local1_irqdispatch(struct pt_regs *regs)
+static void indy_local1_irqdispatch(struct pt_regs *regs)
{
u8 mask = sgint->istat1 & sgint->imask1;
u8 mask2;
@@ -262,7 +261,7 @@ void indy_local1_irqdispatch(struct pt_regs *regs)
extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
-void indy_buserror_irq(struct pt_regs *regs)
+static void indy_buserror_irq(struct pt_regs *regs)
{
int irq = SGI_BUSERR_IRQ;
@@ -307,6 +306,56 @@ static struct irqaction map1_cascade = {
#define SGI_INTERRUPTS SGINT_LOCAL3
#endif
+extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
+extern void indy_8254timer_irq(struct pt_regs *regs);
+
+/*
+ * IRQs on the INDY look basically (barring software IRQs which we don't use
+ * at all) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Local IRQ level zero
+ * 3 Local IRQ level one
+ * 4 8254 Timer zero
+ * 5 8254 Timer one
+ * 6 Bus Error
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Local IRQ zero
+ * Local IRQ one
+ * Bus Error
+ * 8254 Timer zero
+ * Lowest ---- 8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause();
+
+ /*
+ * First we check for r4k counter/timer IRQ.
+ */
+ if (pending & CAUSEF_IP7)
+ indy_r4k_timer_interrupt(regs);
+ else if (pending & CAUSEF_IP2)
+ indy_local0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP3)
+ indy_local1_irqdispatch(regs);
+ else if (pending & CAUSEF_IP6)
+ indy_buserror_irq(regs);
+ else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+ indy_8254timer_irq(regs);
+}
+
extern void mips_cpu_irq_init(unsigned int irq_base);
void __init arch_init_irq(void)
@@ -369,8 +418,6 @@ void __init arch_init_irq(void)
sgint->cmeimask0 = 0;
sgint->cmeimask1 = 0;
- set_except_vector(0, indyIRQ);
-
/* init CPU irqs */
mips_cpu_irq_init(SGINT_CPU);
diff --git a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S
deleted file mode 100644
index 6ccbd9e1d967..000000000000
--- a/arch/mips/sgi-ip22/ip22-irq.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
- * Guiness.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Local IRQ level zero
- * 3 Local IRQ level one
- * 4 8254 Timer zero
- * 5 8254 Timer one
- * 6 Bus Error
- * 7 R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Local IRQ zero
- * Local IRQ one
- * Bus Error
- * 8254 Timer zero
- * Lowest ---- 8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(indyIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 s0, CP0_CAUSE # get irq mask
-
- /* First we check for r4k counter/timer IRQ. */
- andi a0, s0, CAUSEF_IP7
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
-
- /* Wheee, a timer interrupt. */
- jal indy_r4k_timer_interrupt
- move a0, sp # delay slot
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
-
- /* Wheee, local level zero interrupt. */
- jal indy_local0_irqdispatch
- move a0, sp # delay slot
-
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
-
- /* Wheee, local level one interrupt. */
- jal indy_local1_irqdispatch
- move a0, sp # delay slot
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) # delay slot
-
- /* Wheee, an asynchronous bus error... */
- jal indy_buserror_irq
- move a0, sp # delay slot
- j ret_from_irq
- nop # delay slot
-
-1:
- /* Here by mistake? It is possible, that by the time we take
- * the exception the IRQ pin goes low, so just leave if this
- * is the case.
- */
- beq a0, zero, 1f
- nop # delay slot
-
- /* Must be one of the 8254 timers... */
- jal indy_8254timer_irq
- move a0, sp # delay slot
-1:
- j ret_from_irq
- nop # delay slot
- END(indyIRQ)
diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile
index 4ba340780c35..686ba14e2882 100644
--- a/arch/mips/sgi-ip27/Makefile
+++ b/arch/mips/sgi-ip27/Makefile
@@ -2,7 +2,7 @@
# Makefile for the IP27 specific kernel interface routines under Linux.
#
-obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o \
ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
ip27-timer.o ip27-hubio.o ip27-xtalk.o
diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO
index 32106131b0d0..19f1512c8f2e 100644
--- a/arch/mips/sgi-ip27/TODO
+++ b/arch/mips/sgi-ip27/TODO
@@ -9,10 +9,6 @@ ip27-init.c:find_lbaord_real. DONE
in irix?
6. Investigate why things do not work without the setup_test() call
being invoked on all nodes in ip27-memory.c.
-7. Too many CLIs in the locore handlers :
-For the low level handlers set up by set_except_vector(),
-__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
-investigate whether the code should do CLI, STI or KMODE.
8. Too many do_page_faults invoked - investigate.
9. start_thread must turn off UX64 ... and define tlb_refill_debug.
10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
diff --git a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S
deleted file mode 100644
index c304df715e0a..000000000000
--- a/arch/mips/sgi-ip27/ip27-irq-glue.S
+++ /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) 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .align 5
-NESTED(ip27_irq, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
- mfc0 s0, CP0_CAUSE
- mfc0 t0, CP0_STATUS
- and s0, t0
- move a0, sp
- PTR_LA ra, ret_from_irq
-
- /* First check for RT interrupt. */
- andi t0, s0, CAUSEF_IP4
- bnez t0, ip4
- andi t0, s0, CAUSEF_IP2
- bnez t0, ip2
- andi t0, s0, CAUSEF_IP3
- bnez t0, ip3
- andi t0, s0, CAUSEF_IP5
- bnez t0, ip5
- andi t0, s0, CAUSEF_IP6
- bnez t0, ip6
- j ra
-
-ip2: j ip27_do_irq_mask0 # PI_INT_PEND_0 or CC_PEND_{A|B}
-ip3: j ip27_do_irq_mask1 # PI_INT_PEND_1
-ip4: j ip27_rt_timer_interrupt
-ip5: j ip27_prof_timer
-ip6: j ip27_hub_error
-
- END(ip27_irq)
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 2854ac4c9be1..2e643d2f51cb 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -130,7 +130,7 @@ static int ms1bit(unsigned long x)
* Kanoj 05.13.00
*/
-void ip27_do_irq_mask0(struct pt_regs *regs)
+static void ip27_do_irq_mask0(struct pt_regs *regs)
{
int irq, swlevel;
hubreg_t pend0, mask0;
@@ -171,7 +171,7 @@ void ip27_do_irq_mask0(struct pt_regs *regs)
LOCAL_HUB_L(PI_INT_PEND0);
}
-void ip27_do_irq_mask1(struct pt_regs *regs)
+static void ip27_do_irq_mask1(struct pt_regs *regs)
{
int irq, swlevel;
hubreg_t pend1, mask1;
@@ -196,12 +196,12 @@ void ip27_do_irq_mask1(struct pt_regs *regs)
LOCAL_HUB_L(PI_INT_PEND1);
}
-void ip27_prof_timer(struct pt_regs *regs)
+static void ip27_prof_timer(struct pt_regs *regs)
{
panic("CPU %d got a profiling interrupt", smp_processor_id());
}
-void ip27_hub_error(struct pt_regs *regs)
+static void ip27_hub_error(struct pt_regs *regs)
{
panic("CPU %d got a hub error interrupt", smp_processor_id());
}
@@ -421,9 +421,26 @@ int __devinit request_bridge_irq(struct bridge_controller *bc)
return irq;
}
+extern void ip27_rt_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned long pending = read_c0_cause() & read_c0_status();
+
+ if (pending & CAUSEF_IP4)
+ ip27_rt_timer_interrupt(regs);
+ else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */
+ ip27_do_irq_mask0(regs);
+ else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */
+ ip27_do_irq_mask1(regs);
+ else if (pending & CAUSEF_IP5)
+ ip27_prof_timer(regs);
+ else if (pending & CAUSEF_IP6)
+ ip27_hub_error(regs);
+}
+
void __init arch_init_irq(void)
{
- set_except_vector(0, ip27_irq);
}
void install_ipi(void)
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index cddf1cedf007..36b662e27b6e 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -122,7 +122,7 @@ again:
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_set_time(xtime.tv_sec) == 0) {
+ if (rtc_mips_set_time(xtime.tv_sec) == 0) {
last_rtc_update = xtime.tv_sec;
} else {
last_rtc_update = xtime.tv_sec - 600;
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
index 470898f4afe1..530bf848c3d0 100644
--- a/arch/mips/sgi-ip32/Makefile
+++ b/arch/mips/sgi-ip32/Makefile
@@ -3,7 +3,7 @@
# under Linux.
#
-obj-y += ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
+obj-y += ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
crime.o ip32-memory.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
deleted file mode 100644
index 200924e1c4f5..000000000000
--- a/arch/mips/sgi-ip32/ip32-irq-glue.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
- *
- * 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 Harald Koerfgen
- * Copyright (C) 2001 Keith M Wesolowski
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/addrspace.h>
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(ip32_handle_int, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI # TEST: interrupts should be off
- .set at
- .set noreorder
-
- mfc0 s0,CP0_CAUSE
-
- andi t1, s0, IE_IRQ0
- bnez t1, handle_irq0
- andi t1, s0, IE_IRQ1
- bnez t1, handle_irq1
- andi t1, s0, IE_IRQ2
- bnez t1, handle_irq2
- andi t1, s0, IE_IRQ3
- bnez t1, handle_irq3
- andi t1, s0, IE_IRQ4
- bnez t1, handle_irq4
- andi t1, s0, IE_IRQ5
- bnez t1, handle_irq5
- nop
-
- /* Either someone has triggered the "software interrupts"
- * or we lost an interrupt somehow. Ignore it.
- */
- j ret_from_irq
- nop
-
-handle_irq0:
- jal ip32_irq0
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq1:
- jal ip32_irq1
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq2:
- jal ip32_irq2
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq3:
- jal ip32_irq3
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq4:
- jal ip32_irq4
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq5:
- jal ip32_irq5
- move a0, sp
- j ret_from_irq
- nop
-
- END(ip32_handle_int)
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index 2eb22d692ed9..de01c9815bdd 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -130,8 +130,6 @@ struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT,
struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
CPU_MASK_NONE, "CRIME CPU error", NULL, NULL };
-extern void ip32_handle_int(void);
-
/*
* For interrupts wired from a single device to the CPU. Only the clock
* uses this it seems, which is IRQ 0 and IP7.
@@ -503,48 +501,67 @@ static void ip32_unknown_interrupt(struct pt_regs *regs)
/* CRIME 1.1 appears to deliver all interrupts to this one pin. */
/* change this to loop over all edge-triggered irqs, exception masked out ones */
-void ip32_irq0(struct pt_regs *regs)
+static void ip32_irq0(struct pt_regs *regs)
{
uint64_t crime_int;
int irq = 0;
crime_int = crime->istat & crime_mask;
- irq = ffs(crime_int);
- crime_int = 1 << (irq - 1);
+ irq = __ffs(crime_int);
+ crime_int = 1 << irq;
if (crime_int & CRIME_MACEISA_INT_MASK) {
unsigned long mace_int = mace->perif.ctrl.istat;
- irq = ffs(mace_int & maceisa_mask) + 32;
+ irq = __ffs(mace_int & maceisa_mask) + 32;
}
+ irq++;
DBG("*irq %u*\n", irq);
do_IRQ(irq, regs);
}
-void ip32_irq1(struct pt_regs *regs)
+static void ip32_irq1(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq2(struct pt_regs *regs)
+static void ip32_irq2(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq3(struct pt_regs *regs)
+static void ip32_irq3(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq4(struct pt_regs *regs)
+static void ip32_irq4(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq5(struct pt_regs *regs)
+static void ip32_irq5(struct pt_regs *regs)
{
ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause();
+
+ if (likely(pending & IE_IRQ0))
+ ip32_irq0(regs);
+ else if (unlikely(pending & IE_IRQ1))
+ ip32_irq1(regs);
+ else if (unlikely(pending & IE_IRQ2))
+ ip32_irq2(regs);
+ else if (unlikely(pending & IE_IRQ3))
+ ip32_irq3(regs);
+ else if (unlikely(pending & IE_IRQ4))
+ ip32_irq4(regs);
+ else if (likely(pending & IE_IRQ5))
+ ip32_irq5(regs);
+}
+
void __init arch_init_irq(void)
{
unsigned int irq;
@@ -556,7 +573,6 @@ void __init arch_init_irq(void)
crime->soft_int = 0;
mace->perif.ctrl.istat = 0;
mace->perif.ctrl.imask = 0;
- set_except_vector(0, ip32_handle_int);
for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
hw_irq_controller *controller;
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
index 538d5a51ae94..7b36ff3873b7 100644
--- a/arch/mips/sibyte/bcm1480/Makefile
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 9cf7d713b13c..e61760b14d99 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -187,9 +187,6 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
#endif
-/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
-extern void bcm1480_irq_handler(void);
-
/*****************************************************************************/
static unsigned int startup_bcm1480_irq(unsigned int irq)
@@ -422,7 +419,6 @@ void __init arch_init_irq(void)
#endif
/* Enable necessary IPs, disable the rest */
change_c0_status(ST0_IM, imask);
- set_except_vector(0, bcm1480_irq_handler);
#ifdef CONFIG_KGDB
if (kgdb_flag) {
@@ -473,3 +469,76 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
}
#endif /* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+ int lz;
+
+ __asm__ (
+ " .set push \n"
+ " .set mips64 \n"
+ " dclz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (lz)
+ : "r" (x));
+
+ return lz;
+}
+
+extern void bcm1480_timer_interrupt(struct pt_regs *regs);
+extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
+extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+ /* Set compare to count to silence count/compare timer interrupts */
+ write_c0_compare(read_c0_count());
+#endif
+
+ pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+ if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
+ sbprof_cpu_intr(exception_epc(regs));
+#endif
+
+ if (pending & CAUSEF_IP4)
+ bcm1480_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+ if (pending & CAUSEF_IP3)
+ bcm1480_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+ if (pending & CAUSEF_IP6)
+ bcm1480_kgdb_interrupt(regs); /* KGDB (uart 1) */
+#endif
+
+ if (pending & CAUSEF_IP2) {
+ unsigned long long mask_h, mask_l;
+ unsigned long base;
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've
+ * got to check the 1480 interrupt registers to figure out what
+ * to do. Need to detect which CPU we're on, now that
+ * smp_affinity is supported.
+ */
+ base = A_BCM1480_IMR_MAPPER(smp_processor_id());
+ mask_h = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+ mask_l = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+ if (!mask_h) {
+ if (mask_h ^ 1)
+ do_IRQ(63 - dclz(mask_h), regs);
+ else
+ do_IRQ(127 - dclz(mask_l), regs);
+ }
+ }
+}
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
deleted file mode 100644
index 408db88d050f..000000000000
--- a/arch/mips/sibyte/bcm1480/irq_handler.S
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2000,2001,2002,2003,2004 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.
- */
-
-/*
- * bcm1480_irq_handler() is the routine that is actually called when an
- * interrupt occurs. It is installed as the exception vector handler in
- * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that
- * to call the dispatcher, which will take care of actually calling
- * registered handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call. Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
- .text
- .set push
- .set noreorder
- .set noat
- .set mips64
- #.set mips4
- .align 5
- NESTED(bcm1480_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- mfc0 t1, CP0_COUNT
- mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
- /* Read cause */
- mfc0 s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- /* Cpu performance counter interrupt is routed to IP[7] */
- andi t1, s0, CAUSEF_IP7
- beqz t1, 0f
- srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
- and t1, t1, 0x4 /* mask to get just BD bit */
-#ifdef CONFIG_MIPS64
- dmfc0 a0, CP0_EPC
- daddu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
-#else
- mfc0 a0, CP0_EPC
- addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
-#endif
- jal sbprof_cpu_intr
- nop
- j ret_from_irq
- nop
-0:
-#endif
-
- /* Timer interrupt is routed to IP[4] */
- andi t1, s0, CAUSEF_IP4
- beqz t1, 1f
- nop
- jal bcm1480_timer_interrupt
- move a0, sp /* Pass the registers along */
- j ret_from_irq
- nop /* delay slot */
-1:
-
-#ifdef CONFIG_SMP
- /* Mailbox interrupt is routed to IP[3] */
- andi t1, s0, CAUSEF_IP3
- beqz t1, 2f
- nop
- jal bcm1480_mailbox_interrupt
- move a0, sp
- j ret_from_irq
- nop /* delay slot */
-2:
-#endif
-
-#ifdef CONFIG_KGDB
- /* KGDB (uart 1) interrupt is routed to IP[6] */
- andi t1, s0, CAUSEF_IP6
- beqz t1, 3f
- nop /* delay slot */
- jal bcm1480_kgdb_interrupt
- move a0, sp
- j ret_from_irq
- nop /* delay slot */
-3:
-#endif
-
- and t1, s0, CAUSEF_IP2
- beqz t1, 9f
- nop
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've got
- * to check the 1480 interrupt registers to figure out what to do
- * Need to detect which CPU we're on, now that smp_affinity is
- * supported.
- */
- PTR_LA v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
- lw t1, TI_CPU($28)
- sll t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
- addu v0, v0, t1
-#endif
-
- /* Read IP[2] status (get both high and low halves of status) */
- ld s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
- ld s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
-
- move s2, zero /* intr number */
- li s3, 64
-
- beqz s0, 9f /* No interrupts. Return. */
- move a1, sp
-
- xori s4, s0, 1 /* if s0 (_H) == 1, it's a low intr, so... */
- movz s2, s3, s4 /* start the intr number at 64, and */
- movz s0, s1, s4 /* look at the low status value. */
-
- dclz s1, s0 /* Find the next interrupt. */
- dsubu a0, zero, s1
- daddiu a0, a0, 63
- jal do_IRQ
- daddu a0, a0, s2
-
-9: j ret_from_irq
- nop
-
- .set pop
- END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
index a8af84697588..a2fdbd62f8ac 100644
--- a/arch/mips/sibyte/sb1250/Makefile
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 589537bfcc3d..0f6e54db4888 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -163,10 +163,6 @@ static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
}
#endif
-
-/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */
-extern void sb1250_irq_handler(void);
-
/*****************************************************************************/
static unsigned int startup_sb1250_irq(unsigned int irq)
@@ -379,7 +375,6 @@ void __init arch_init_irq(void)
#endif
/* Enable necessary IPs, disable the rest */
change_c0_status(ST0_IM, imask);
- set_except_vector(0, sb1250_irq_handler);
#ifdef CONFIG_KGDB
if (kgdb_flag) {
@@ -409,7 +404,7 @@ void __init arch_init_irq(void)
#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static void sb1250_kgdb_interrupt(struct pt_regs *regs)
{
/*
* Clear break-change status (allow some time for the remote
@@ -424,3 +419,74 @@ void sb1250_kgdb_interrupt(struct pt_regs *regs)
}
#endif /* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+ int lz;
+
+ __asm__ (
+ " .set push \n"
+ " .set mips64 \n"
+ " dclz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (lz)
+ : "r" (x));
+
+ return lz;
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+ /* Set compare to count to silence count/compare timer interrupts */
+ write_c0_count(read_c0_count());
+#endif
+
+ /*
+ * What a pain. We have to be really careful saving the upper 32 bits
+ * of any * register across function calls if we don't want them
+ * trashed--since were running in -o32, the calling routing never saves
+ * the full 64 bits of a register across a function call. Being the
+ * interrupt handler, we're guaranteed that interrupts are disabled
+ * during this code so we don't have to worry about random interrupts
+ * blasting the high 32 bits.
+ */
+
+ pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+ if (pending & CAUSEF_IP7) { /* Cpu performance counter interrupt */
+ sbprof_cpu_intr(exception_epc(regs));
+ }
+#endif
+
+ if (pending & CAUSEF_IP4)
+ sb1250_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+ if (pending & CAUSEF_IP3)
+ sb1250_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+ if (pending & CAUSEF_IP6) /* KGDB (uart 1) */
+ sb1250_kgdb_interrupt(regs);
+#endif
+
+ if (pending & CAUSEF_IP2) {
+ unsigned long long mask;
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've
+ * got to check the 1250 interrupt registers to figure out what
+ * to do. Need to detect which CPU we're on, now that
+ ~ smp_affinity is supported.
+ */
+ mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
+ R_IMR_INTERRUPT_STATUS_BASE)));
+ if (mask)
+ do_IRQ(63 - dclz(mask), regs);
+ }
+}
diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S
deleted file mode 100644
index 60edc8fb302b..000000000000
--- a/arch/mips/sibyte/sb1250/irq_handler.S
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 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.
- */
-
-/*
- * sb1250_handle_int() is the routine that is actually called when an interrupt
- * occurs. It is installed as the exception vector handler in arch_init_irq()
- * in arch/mips/sibyte/sb1250/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that to
- * call the dispatcher, which will take care of actually calling registered
- * handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call. Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
- .text
- .set push
- .set noreorder
- .set noat
- .set mips64
- .align 5
- NESTED(sb1250_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- mfc0 t1, CP0_COUNT
- mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
- /* Read cause */
- mfc0 s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
- /* Cpu performance counter interrupt is routed to IP[7] */
- andi t1, s0, CAUSEF_IP7
- beqz t1, 0f
- srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
- and t1, t1, 0x4 /* mask to get just BD bit */
- mfc0 a0, CP0_EPC
- jal sbprof_cpu_intr
- addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
- j ret_from_irq
- nop
-0:
-#endif
-
- /* Timer interrupt is routed to IP[4] */
- andi t1, s0, CAUSEF_IP4
- beqz t1, 1f
- nop
- jal sb1250_timer_interrupt
- move a0, sp /* Pass the registers along */
- j ret_from_irq
- nop # delay slot
-1:
-
-#ifdef CONFIG_SMP
- /* Mailbox interrupt is routed to IP[3] */
- andi t1, s0, CAUSEF_IP3
- beqz t1, 2f
- nop
- jal sb1250_mailbox_interrupt
- move a0, sp
- j ret_from_irq
- nop # delay slot
-2:
-#endif
-
-#ifdef CONFIG_KGDB
- /* KGDB (uart 1) interrupt is routed to IP[6] */
- andi t1, s0, CAUSEF_IP6
- beqz t1, 1f
- nop # delay slot
- jal sb1250_kgdb_interrupt
- move a0, sp
- j ret_from_irq
- nop # delay slot
-1:
-#endif
-
- and t1, s0, CAUSEF_IP2
- beqz t1, 4f
- nop
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've got to
- * check the 1250 interrupt registers to figure out what to do
- * Need to detect which CPU we're on, now that smp_affinity is supported.
- */
- PTR_LA v0, CKSEG1 + A_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
- lw t1, TI_CPU($28)
- sll t1, IMR_REGISTER_SPACING_SHIFT
- addu v0, t1
-#endif
- ld s0, R_IMR_INTERRUPT_STATUS_BASE(v0) /* read IP[2] status */
-
- beqz s0, 4f /* No interrupts. Return */
- move a1, sp
-
-3: dclz s1, s0 /* Find the next interrupt */
- dsubu a0, zero, s1
- daddiu a0, a0, 63
- jal do_IRQ
- nop
-
-4: j ret_from_irq
- nop
-
- .set pop
- END(sb1250_irq_handler)
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index 1e5676e4be86..9c7eaa5fb210 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,6 +2,6 @@
# Makefile for the SNI specific part of the kernel
#
-obj-y += int-handler.o irq.o pcimt_scache.o reset.o setup.o
+obj-y += irq.o pcimt_scache.o reset.o setup.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
deleted file mode 100644
index 2cdc09f55f18..000000000000
--- a/arch/mips/sni/int-handler.S
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SNI RM200 PCI specific interrupt handler code.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000, 01 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sni.h>
-#include <asm/stackframe.h>
-
-/*
- * The PCI ASIC has the nasty property that it may delay writes if it is busy.
- * As a consequence from writes that have not graduated when we exit from the
- * interrupt handler we might catch a spurious interrupt. To avoid this we
- * force the PCI ASIC to graduate all writes by executing a read from the
- * PCI bus.
- */
- .set noreorder
- .set noat
- .align 5
- NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- /* Blinken light ... */
- lb t0, led_cache
- addiu t0, 1
- sb t0, led_cache
- sb t0, PCIMT_CSLED # write only register
- .data
-led_cache: .byte 0
- .text
-
- mfc0 t0, CP0_STATUS
- mfc0 t1, CP0_CAUSE
- and t0, t1
-
- andi t1, t0, 0x0800 # hardware interrupt 1
- bnez t1, _hwint1
- andi t1, t0, 0x4000 # hardware interrupt 4
- bnez t1, _hwint4
- andi t1, t0, 0x2000 # hardware interrupt 3
- bnez t1, _hwint3
- andi t1, t0, 0x1000 # hardware interrupt 2
- bnez t1, _hwint2
- andi t1, t0, 0x8000 # hardware interrupt 5
- bnez t1, _hwint5
- andi t1, t0, 0x0400 # hardware interrupt 0
- bnez t1, _hwint0
- nop
-
- j restore_all # spurious interrupt
- nop
-
- ##############################################################################
-
-/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
- button interrupts. */
-_hwint0: jal pciasic_hwint0
- move a0, sp
- j ret_from_irq
- nop
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts
- */
-_hwint1: jal pciasic_hwint1
- move a0, sp
- j ret_from_irq
- nop
-
-
-/*
- * This interrupt was used for the com1 console on the first prototypes;
- * it's unsed otherwise
- */
-_hwint2: jal pciasic_hwint2
- move a0, sp
- j ret_from_irq
- nop
-
-/*
- * hwint 3 are the PCI interrupts A - D
- */
-_hwint3: jal pciasic_hwint3
- move a0, sp
- j ret_from_irq
- nop
-
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-_hwint4: jal pciasic_hwint4
- move a0, sp
- j ret_from_irq
- nop
-
-/* hwint5 is the r4k count / compare interrupt */
-_hwint5: jal pciasic_hwint5
- move a0, sp
- j ret_from_irq
- nop
-
- END(sni_rm200_pci_handle_int)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 952038aa4b90..7365b4853ddb 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -19,8 +19,6 @@
DEFINE_SPINLOCK(pciasic_lock);
-extern asmlinkage void sni_rm200_pci_handle_int(void);
-
static void enable_pciasic_irq(unsigned int irq)
{
unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
@@ -71,20 +69,20 @@ static struct hw_interrupt_type pciasic_irq_type = {
* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
* button interrupts. Later ...
*/
-void pciasic_hwint0(struct pt_regs *regs)
+static void pciasic_hwint0(struct pt_regs *regs)
{
panic("Received int0 but no handler yet ...");
}
/* This interrupt was used for the com1 console on the first prototypes. */
-void pciasic_hwint2(struct pt_regs *regs)
+static void pciasic_hwint2(struct pt_regs *regs)
{
/* I think this shouldn't happen on production machines. */
panic("hwint2 and no handler yet");
}
/* hwint5 is the r4k count / compare interrupt */
-void pciasic_hwint5(struct pt_regs *regs)
+static void pciasic_hwint5(struct pt_regs *regs)
{
panic("hwint5 and no handler yet");
}
@@ -105,7 +103,7 @@ static unsigned int ls1bit8(unsigned int x)
*
* The EISA_INT bit in CSITPEND is high active, all others are low active.
*/
-void pciasic_hwint1(struct pt_regs *regs)
+static void pciasic_hwint1(struct pt_regs *regs)
{
u8 pend = *(volatile char *)PCIMT_CSITPEND;
unsigned long flags;
@@ -135,7 +133,7 @@ void pciasic_hwint1(struct pt_regs *regs)
/*
* hwint 3 should deal with the PCI A - D interrupts,
*/
-void pciasic_hwint3(struct pt_regs *regs)
+static void pciasic_hwint3(struct pt_regs *regs)
{
u8 pend = *(volatile char *)PCIMT_CSITPEND;
int irq;
@@ -150,13 +148,34 @@ void pciasic_hwint3(struct pt_regs *regs)
/*
* hwint 4 is used for only the onboard PCnet 32.
*/
-void pciasic_hwint4(struct pt_regs *regs)
+static void pciasic_hwint4(struct pt_regs *regs)
{
clear_c0_status(IE_IRQ4);
do_IRQ(PCIMT_IRQ_ETHERNET, regs);
set_c0_status(IE_IRQ4);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+ static unsigned char led_cache;
+
+ *(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
+
+ if (pending & 0x0800)
+ pciasic_hwint1(regs);
+ else if (pending & 0x4000)
+ pciasic_hwint4(regs);
+ else if (pending & 0x2000)
+ pciasic_hwint3(regs);
+ else if (pending & 0x1000)
+ pciasic_hwint2(regs);
+ else if (pending & 0x8000)
+ pciasic_hwint5(regs);
+ else if (pending & 0x0400)
+ pciasic_hwint0(regs);
+}
+
void __init init_pciasic(void)
{
unsigned long flags;
@@ -176,8 +195,6 @@ void __init arch_init_irq(void)
{
int i;
- set_except_vector(0, sni_rm200_pci_handle_int);
-
init_i8259_irqs(); /* Integrated i8259 */
init_pciasic();
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile
index 8fa126b296e1..9cb9535ebacb 100644
--- a/arch/mips/tx4927/common/Makefile
+++ b/arch/mips/tx4927/common/Makefile
@@ -6,7 +6,7 @@
# unless it's something special (ie not a .c file).
#
-obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o
+obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o
obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o
obj-$(CONFIG_KGDB) += tx4927_dbgio.o
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index 5ab2e2b76018..8ca68015cf40 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -525,8 +525,6 @@ static void tx4927_irq_pic_end(unsigned int irq)
*/
void __init tx4927_irq_init(void)
{
- extern asmlinkage void tx4927_irq_handler(void);
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
@@ -535,16 +533,12 @@ void __init tx4927_irq_init(void)
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
tx4927_irq_pic_init();
- TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
- "=Calling set_except_vector(tx4927_irq_handler)\n");
- set_except_vector(0, tx4927_irq_handler);
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
return;
}
-int tx4927_irq_nested(void)
+static int tx4927_irq_nested(void)
{
int sw_irq = 0;
u32 level2;
@@ -582,3 +576,25 @@ int tx4927_irq_nested(void)
return (sw_irq);
}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+ else if (pending & STATUSF_IP2) { /* tx4927 pic */
+ unsigned int irq = tx4927_irq_nested();
+
+ if (unlikely(irq == 0)) {
+ spurious_interrupt(regs);
+ return;
+ }
+ do_IRQ(irq, regs);
+ } else if (pending & STATUSF_IP0) /* user line 0 */
+ do_IRQ(TX4927_IRQ_USER0, regs);
+ else if (pending & STATUSF_IP1) /* user line 1 */
+ do_IRQ(TX4927_IRQ_USER1, regs);
+ else
+ spurious_interrupt(regs);
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
deleted file mode 100644
index dd3ceda9d712..000000000000
--- a/arch/mips/tx4927/common/tx4927_irq_handler.S
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/arch/mips/tx4927/common/tx4927_irq_handler.S
- *
- * Primary interrupt handler for tx4927 based systems
- *
- * Author: MontaVista Software, Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- * source@mvista.com
- *
- * Copyright 2001-2002 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4927/tx4927.h>
-
- .align 5
- NESTED(tx4927_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 t0, CP0_CAUSE
- mfc0 t1, CP0_STATUS
- and t0, t1
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_ip7
-
- /* IP6..IP3 multiplexed -- do not use */
-
- andi t1, t0, STATUSF_IP2 /* tx4927 pic */
- bnez t1, ll_ip2
-
- andi t1, t0, STATUSF_IP0 /* user line 0 */
- bnez t1, ll_ip0
-
- andi t1, t0, STATUSF_IP1 /* user line 1 */
- bnez t1, ll_ip1
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(tx4927_irq_handler)
-
- .align 5
-
-
-ll_ip7:
- li a0, TX4927_IRQ_CPU_TIMER
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_ip2:
- jal tx4927_irq_nested
- nop
- beqz v0, goto_spurious_interrupt
- nop
- move a0, v0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-goto_spurious_interrupt:
- j spurious_interrupt
- nop
-
-ll_ip1:
- li a0, TX4927_IRQ_USER1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_ip0:
- li a0, TX4927_IRQ_USER0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 74c95c5bcdbf..2033ae77f632 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 irq_handler.o rtc_rx5c348.o
+obj-y += prom.o setup.o irq.o rtc_rx5c348.o
obj-$(CONFIG_KGDB) += dbgio.o
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index 4f90d7faf634..873805178d8e 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -392,11 +392,8 @@ tx4938_irq_pic_end(unsigned int irq)
void __init
tx4938_irq_init(void)
{
- extern asmlinkage void tx4938_irq_handler(void);
-
tx4938_irq_cp0_init();
tx4938_irq_pic_init();
- set_except_vector(0, tx4938_irq_handler);
return;
}
@@ -422,3 +419,21 @@ tx4938_irq_nested(void)
wbflush();
return (sw_irq);
}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(TX4938_IRQ_CPU_TIMER, regs);
+ else if (pending & STATUSF_IP2) {
+ int irq = tx4938_irq_nested();
+ if (irq)
+ do_IRQ(irq, regs);
+ else
+ spurious_interrupt(regs);
+ } else if (pending & STATUSF_IP1)
+ do_IRQ(TX4938_IRQ_USER1, regs);
+ else if (pending & STATUSF_IP0)
+ do_IRQ(TX4938_IRQ_USER0, regs);
+}
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S
deleted file mode 100644
index 1b2f72bac42d..000000000000
--- a/arch/mips/tx4938/common/irq_handler.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/arch/mips/tx4938/common/handler.S
- *
- * Primary interrupt handler for tx4938 based systems
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4938/rbtx4938.h>
-
-
- .align 5
- NESTED(tx4938_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 t0, CP0_CAUSE
- mfc0 t1, CP0_STATUS
- and t0, t1
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_ip7
-
- /* IP6..IP3 multiplexed -- do not use */
-
- andi t1, t0, STATUSF_IP2 /* tx4938 pic */
- bnez t1, ll_ip2
-
- andi t1, t0, STATUSF_IP1 /* user line 1 */
- bnez t1, ll_ip1
-
- andi t1, t0, STATUSF_IP0 /* user line 0 */
- bnez t1, ll_ip0
-
- .set reorder
-
- nop
- END(tx4938_irq_handler)
-
- .align 5
-
-
-ll_ip7:
- li a0, TX4938_IRQ_CPU_TIMER
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-
-ll_ip2:
- jal tx4938_irq_nested
- nop
- beqz v0, goto_spurious_interrupt
- nop
- move a0, v0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-goto_spurious_interrupt:
- j ret_from_irq
-
-ll_ip1:
- li a0, TX4938_IRQ_USER1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_ip0:
- li a0, TX4938_IRQ_USER0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index a7add16c9aa4..055a2cdfc841 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -4,6 +4,8 @@ config CASIO_E55
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config IBM_WORKPAD
@@ -12,6 +14,8 @@ config IBM_WORKPAD
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config NEC_CMBVR4133
@@ -21,6 +25,9 @@ config NEC_CMBVR4133
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
config ROCKHOPPER
bool "Support for Rockhopper baseboard"
@@ -34,6 +41,8 @@ config TANBAC_TB022X
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
help
The TANBAC VR4131 multichip module(TB0225) and
@@ -65,6 +74,8 @@ config VICTOR_MPC30X
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config ZAO_CAPCELLA
@@ -73,6 +84,8 @@ config ZAO_CAPCELLA
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config PCI_VR41XX
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index 9096302a7ecc..aa373974c80f 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,7 +2,7 @@
# Makefile for common code of the NEC VR4100 series.
#
-obj-y += bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o
+obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
obj-$(CONFIG_VRC4173) += vrc4173.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
deleted file mode 100644
index 2b6043f16d09..000000000000
--- a/arch/mips/vr41xx/common/int-handler.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * FILE NAME
- * arch/mips/vr41xx/common/int-handler.S
- *
- * BRIEF MODULE DESCRIPTION
- * Interrupt dispatcher for the NEC VR4100 series.
- *
- * Author: Yoichi Yuasa
- * yyuasa@mvista.com or source@mvista.com
- *
- * Copyright 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License 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.
- */
-/*
- * Changes:
- * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- * - New creation, NEC VR4100 series are supported.
- *
- * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- * - Coped with INTASSIGN of NEC VR4133.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
- .text
- .set noreorder
-
- .align 5
- NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI
- .set at
- .set noreorder
-
- /*
- * Get the pending interrupts
- */
- mfc0 t0, CP0_CAUSE
- mfc0 t1, CP0_STATUS
- andi t0, 0xff00
- and t0, t0, t1
-
- andi t1, t0, CAUSEF_IP7 # MIPS timer interrupt
- bnez t1, handle_irq
- li a0, 7
-
- andi t1, t0, 0x7800 # check for Int1-4
- beqz t1, 1f
-
- andi t1, t0, CAUSEF_IP3 # check for Int1
- bnez t1, handle_int
- li a0, 3
-
- andi t1, t0, CAUSEF_IP4 # check for Int2
- bnez t1, handle_int
- li a0, 4
-
- andi t1, t0, CAUSEF_IP5 # check for Int3
- bnez t1, handle_int
- li a0, 5
-
- andi t1, t0, CAUSEF_IP6 # check for Int4
- bnez t1, handle_int
- li a0, 6
-
-1:
- andi t1, t0, CAUSEF_IP2 # check for Int0
- bnez t1, handle_int
- li a0, 2
-
- andi t1, t0, CAUSEF_IP0 # check for IP0
- bnez t1, handle_irq
- li a0, 0
-
- andi t1, t0, CAUSEF_IP1 # check for IP1
- bnez t1, handle_irq
- li a0, 1
-
- j spurious_interrupt
- nop
-
-handle_int:
- jal irq_dispatch
- move a1, sp
- j ret_from_irq
- nop
-
-handle_irq:
- jal do_IRQ
- move a1, sp
- j ret_from_irq
- END(vr41xx_handle_interrupt)
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 61aa264275ff..86796bb63c3c 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -59,7 +59,7 @@ int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *)
EXPORT_SYMBOL_GPL(cascade_irq);
-asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+static void irq_dispatch(unsigned int irq, struct pt_regs *regs)
{
irq_cascade_t *cascade;
irq_desc_t *desc;
@@ -84,11 +84,32 @@ asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
do_IRQ(irq, regs);
}
-extern asmlinkage void vr41xx_handle_interrupt(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ do_IRQ(7, regs);
+ else if (pending & 0x7800) {
+ if (pending & CAUSEF_IP3)
+ irq_dispatch(3, regs);
+ else if (pending & CAUSEF_IP4)
+ irq_dispatch(4, regs);
+ else if (pending & CAUSEF_IP5)
+ irq_dispatch(5, regs);
+ else if (pending & CAUSEF_IP6)
+ irq_dispatch(6, regs);
+ } else if (pending & CAUSEF_IP2)
+ irq_dispatch(2, regs);
+ else if (pending & CAUSEF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & CAUSEF_IP1)
+ do_IRQ(1, regs);
+ else
+ spurious_interrupt(regs);
+}
void __init arch_init_irq(void)
{
mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
-
- set_except_vector(0, vr41xx_handle_interrupt);
}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 2fdf21989dc2..910fb3afc0b5 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -138,6 +138,37 @@ config 64BIT
enable this option otherwise. The 64bit kernel is significantly bigger
and slower than the 32bit one.
+choice
+ prompt "Kernel page size"
+ default PARISC_PAGE_SIZE_4KB if !64BIT
+ default PARISC_PAGE_SIZE_4KB if 64BIT
+# default PARISC_PAGE_SIZE_16KB if 64BIT
+
+config PARISC_PAGE_SIZE_4KB
+ bool "4KB"
+ help
+ This lets you select the page size of the kernel. For best
+ performance, a page size of 16KB is recommended. For best
+ compatibility with 32bit applications, a page size of 4KB should be
+ selected (the vast majority of 32bit binaries work perfectly fine
+ with a larger page size).
+
+ 4KB For best 32bit compatibility
+ 16KB For best performance
+ 64KB For best performance, might give more overhead.
+
+ If you don't know what to do, choose 4KB.
+
+config PARISC_PAGE_SIZE_16KB
+ bool "16KB (EXPERIMENTAL)"
+ depends on PA8X00 && EXPERIMENTAL
+
+config PARISC_PAGE_SIZE_64KB
+ bool "64KB (EXPERIMENTAL)"
+ depends on PA8X00 && EXPERIMENTAL
+
+endchoice
+
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -177,6 +208,11 @@ config ARCH_DISCONTIGMEM_DEFAULT
def_bool y
depends on ARCH_DISCONTIGMEM_ENABLE
+config NODES_SHIFT
+ int
+ default "3"
+ depends on NEED_MULTIPLE_NODES
+
source "kernel/Kconfig.preempt"
source "kernel/Kconfig.hz"
source "mm/Kconfig"
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
index 59f7bc38e72e..b38b58eb9dc2 100644
--- a/arch/parisc/defconfig
+++ b/arch/parisc/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-pa6
-# Sun Mar 26 19:50:07 2006
+# Linux kernel version: 2.6.16-pa10
+# Sun Apr 2 15:26:38 2006
#
CONFIG_PARISC=y
CONFIG_MMU=y
@@ -25,7 +25,7 @@ CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
@@ -35,7 +35,7 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -57,7 +57,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# Block layer
@@ -79,16 +85,19 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Processor type and features
#
-CONFIG_PA7000=y
-# CONFIG_PA7100LC is not set
+# CONFIG_PA7000 is not set
+CONFIG_PA7100LC=y
# CONFIG_PA7200 is not set
# CONFIG_PA7300LC is not set
# CONFIG_PA8X00 is not set
CONFIG_PA11=y
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
# CONFIG_SMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
@@ -108,7 +117,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096
# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
#
CONFIG_GSC=y
-CONFIG_HPPB=y
+# CONFIG_HPPB is not set
CONFIG_IOMMU_CCIO=y
CONFIG_GSC_LASI=y
CONFIG_GSC_WAX=y
@@ -126,7 +135,25 @@ CONFIG_IOMMU_SBA=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_PCCARD_NONSTATIC=y
#
# PCI Hotplug Support
@@ -145,7 +172,7 @@ CONFIG_PDC_STABLE=y
# Executable file formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
#
# Networking
@@ -159,13 +186,15 @@ CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
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_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
@@ -173,19 +202,20 @@ CONFIG_IP_PNP_BOOTP=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_AH=m
+CONFIG_INET_ESP=m
# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET6_TUNNEL=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -207,7 +237,8 @@ CONFIG_IPV6=y
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
@@ -237,9 +268,9 @@ CONFIG_IPV6=y
#
# Generic Driver Options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
#
@@ -256,13 +287,14 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Parallel port support
#
CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
CONFIG_PARPORT_NOT_PC=y
CONFIG_PARPORT_GSC=y
-# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_1284=y
#
# Plug and Play support
@@ -284,7 +316,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
# 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_SIZE=6144
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -292,7 +324,60 @@ CONFIG_BLK_DEV_INITRD=y
#
# ATA/ATAPI/MFM/RLL support
#
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+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_IDECS=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 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=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_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_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+CONFIG_BLK_DEV_NS87415=y
+# 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_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
#
# SCSI device support
@@ -375,6 +460,15 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_DEBUG is not set
#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
# Multi-device support (RAID and LVM)
#
CONFIG_MD=y
@@ -382,12 +476,17 @@ CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=y
CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
+CONFIG_MD_RAID6=y
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
-# CONFIG_BLK_DEV_DM is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
#
# Fusion MPT device support
@@ -411,10 +510,10 @@ CONFIG_MD_RAID5=y
# Network device support
#
CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
#
# ARCnet devices
@@ -430,7 +529,7 @@ CONFIG_NETDEVICES=y
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
CONFIG_LASI_82596=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
@@ -451,6 +550,8 @@ CONFIG_TULIP=y
# CONFIG_WINBOND_840 is not set
# CONFIG_DM9102 is not set
# CONFIG_ULI526X is not set
+# CONFIG_PCMCIA_XIRCOM is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
@@ -518,14 +619,33 @@ CONFIG_NET_RADIO=y
# 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
+#
+# CONFIG_PCMCIA_RAYCS is not set
#
# Wireless 802.11b ISA/PCI cards support
#
-# CONFIG_HERMES is not set
+CONFIG_HERMES=y
+# 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_ATMEL is not set
#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=y
+CONFIG_PCMCIA_SPECTRUM=y
+# 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 is not set
@@ -533,13 +653,34 @@ CONFIG_NET_RADIO=y
CONFIG_NET_WIRELESS=y
#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
# Wan interfaces
#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+# 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_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
@@ -571,14 +712,16 @@ 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_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
+# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
@@ -586,52 +729,25 @@ CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_HIL_OLD is not set
CONFIG_KEYBOARD_HIL=y
CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_MOUSE_HIL=y
-CONFIG_INPUT_JOYSTICK=y
-# CONFIG_JOYSTICK_ANALOG is not set
-# CONFIG_JOYSTICK_A3D is not set
-# CONFIG_JOYSTICK_ADI is not set
-# CONFIG_JOYSTICK_COBRA is not set
-# CONFIG_JOYSTICK_GF2K is not set
-# CONFIG_JOYSTICK_GRIP is not set
-# CONFIG_JOYSTICK_GRIP_MP is not set
-# CONFIG_JOYSTICK_GUILLEMOT is not set
-# CONFIG_JOYSTICK_INTERACT is not set
-# CONFIG_JOYSTICK_SIDEWINDER is not set
-# CONFIG_JOYSTICK_TMDC is not set
-# CONFIG_JOYSTICK_IFORCE is not set
-# CONFIG_JOYSTICK_WARRIOR is not set
-# CONFIG_JOYSTICK_MAGELLAN is not set
-# CONFIG_JOYSTICK_SPACEORB is not set
-# CONFIG_JOYSTICK_SPACEBALL is not set
-# CONFIG_JOYSTICK_STINGER is not set
-# CONFIG_JOYSTICK_TWIDJOY is not set
-# CONFIG_JOYSTICK_DB9 is not set
-# CONFIG_JOYSTICK_GAMECON is not set
-# CONFIG_JOYSTICK_TURBOGRAFX is not set
-# CONFIG_JOYSTICK_JOYDUMP is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_GUNZE is not set
-# CONFIG_TOUCHSCREEN_ELO is not set
-# CONFIG_TOUCHSCREEN_MTOUCH is not set
-# CONFIG_TOUCHSCREEN_MK712 is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_UINPUT is not set
-CONFIG_HP_SDC_RTC=y
+# 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_SERPORT is not set
+CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_PARKBD is not set
CONFIG_SERIO_GSCPS2=y
CONFIG_HP_SDC=y
CONFIG_HIL_MLC=y
# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
@@ -648,7 +764,8 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=17
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
@@ -666,10 +783,10 @@ 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_PRINTER=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
+CONFIG_PPDEV=m
# CONFIG_TIPAR is not set
#
@@ -682,7 +799,7 @@ CONFIG_PRINTER=y
#
# CONFIG_WATCHDOG is not set
CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
+CONFIG_GEN_RTC_X=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -691,6 +808,13 @@ CONFIG_GEN_RTC=y
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -718,10 +842,8 @@ CONFIG_GEN_RTC=y
#
# Hardware Monitoring support
#
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -749,8 +871,8 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -778,8 +900,8 @@ CONFIG_FB_STI=y
# Console display driver support
#
CONFIG_DUMMY_CONSOLE=y
-CONFIG_DUMMY_CONSOLE_COLUMNS=160
-CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
@@ -816,13 +938,14 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
CONFIG_SND_SEQUENCER=y
# CONFIG_SND_SEQ_DUMMY is not set
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -830,6 +953,7 @@ CONFIG_SND_SUPPORT_OLD_API=y
#
# Generic devices
#
+CONFIG_SND_OPL3_LIB=y
CONFIG_SND_AC97_CODEC=y
CONFIG_SND_AC97_BUS=y
# CONFIG_SND_DUMMY is not set
@@ -842,7 +966,7 @@ CONFIG_SND_AC97_BUS=y
# PCI devices
#
CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
+CONFIG_SND_AD1889_OPL3=y
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -890,6 +1014,10 @@ CONFIG_SND_AD1889=y
# CONFIG_SND_USB_AUDIO is not set
#
+# PCMCIA devices
+#
+
+#
# GSC devices
#
CONFIG_SND_HARMONY=y
@@ -905,12 +1033,12 @@ CONFIG_SND_HARMONY=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
#
# Miscellaneous USB options
#
-# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -918,14 +1046,12 @@ CONFIG_USB_DEBUG=y
#
# USB Host Controller Drivers
#
-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_HCD 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_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
#
@@ -948,13 +1074,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# 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_HID=y
+CONFIG_USB_HIDINPUT=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
@@ -1020,8 +1144,8 @@ CONFIG_USB_MON=y
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
#
# USB DSL modem support
@@ -1058,7 +1182,7 @@ CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
@@ -1066,7 +1190,7 @@ CONFIG_JBD=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1081,8 +1205,11 @@ CONFIG_JOLIET=y
#
# DOS/FAT/NT Filesystems
#
+CONFIG_FAT_FS=y
# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -1125,7 +1252,7 @@ CONFIG_NFS_V3=y
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
@@ -1133,10 +1260,16 @@ 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 is not set
-# CONFIG_CIFS is not set
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1153,50 +1286,50 @@ CONFIG_MSDOS_PARTITION=y
#
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_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
#
# Profiling support
#
CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
#
# Kernel hacking
@@ -1204,7 +1337,7 @@ CONFIG_OPROFILE=y
# CONFIG_PRINTK_TIME is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=16
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
@@ -1217,42 +1350,43 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_VM is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
-CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA is not set
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# 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_DES 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 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# 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_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=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=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
#
# Hardware crypto devices
@@ -1261,7 +1395,9 @@ CONFIG_CRYPTO=y
#
# Library routines
#
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index e23c4e1e3a25..c11a5bc7c067 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -288,8 +288,11 @@ int main(void)
DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE);
DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
+ DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT);
DEFINE(ASM_PT_INITIAL, PT_INITIAL);
DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
+ DEFINE(ASM_PAGE_SIZE_DIV64, PAGE_SIZE/64);
+ DEFINE(ASM_PAGE_SIZE_DIV128, PAGE_SIZE/128);
BLANK();
DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 360b7391cb8c..c057ad7605ba 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -4,7 +4,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> (07-13-1999)
* Copyright (C) 1999 SuSE GmbH Nuernberg
* Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
*
@@ -358,5 +358,5 @@ void parisc_setup_cache_timing(void)
if (!parisc_cache_flush_threshold)
parisc_cache_flush_threshold = FLUSH_THRESHOLD;
- printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
+ printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
}
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 7c95d7663c29..d9e53cf0372b 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -502,18 +502,20 @@
* all ILP32 processes and all the kernel for machines with
* under 4GB of memory) */
.macro L3_ptep pgd,pte,index,va,fault
+#if PT_NLEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
copy %r0,\pte
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
ldw,s \index(\pgd),\pgd
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
shld \pgd,PxD_VALUE_SHIFT,\index
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
copy \index,\pgd
- extrd,u,*<> \va,31,32,%r0
+ extrd,u,*<> \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
+#endif
L2_ptep \pgd,\pte,\index,\va,\fault
.endm
@@ -563,10 +565,18 @@
extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0
depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */
- /* Get rid of prot bits and convert to page addr for iitlbt and idtlbt */
+ /* Enforce uncacheable pages.
+ * This should ONLY be use for MMIO on PA 2.0 machines.
+ * Memory/DMA is cache coherent on all PA2.0 machines we support
+ * (that means T-class is NOT supported) and the memory controllers
+ * on most of those machines only handles cache transactions.
+ */
+ extrd,u,*= \pte,_PAGE_NO_CACHE_BIT+32,1,%r0
+ depi 1,12,1,\prot
- depd %r0,63,PAGE_SHIFT,\pte
- extrd,s \pte,(63-PAGE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+ /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
+ extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+ depdi _PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte
.endm
/* Identical macro to make_insert_tlb above, except it
@@ -584,9 +594,8 @@
/* Get rid of prot bits and convert to page addr for iitlba */
- depi 0,31,PAGE_SHIFT,\pte
+ depi _PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte
extru \pte,24,25,\pte
-
.endm
/* This is for ILP32 PA2.0 only. The TLB insertion needs
@@ -1201,10 +1210,9 @@ intr_save:
*/
/* adjust isr/ior. */
-
- extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */
- depd %r1,31,7,%r17 /* deposit them into ior */
- depdi 0,63,7,%r16 /* clear them from isr */
+ extrd,u %r16,63,SPACEID_SHIFT,%r1 /* get high bits from isr for ior */
+ depd %r1,31,SPACEID_SHIFT,%r17 /* deposit them into ior */
+ depdi 0,63,SPACEID_SHIFT,%r16 /* clear them from isr */
#endif
STREG %r16, PT_ISR(%r29)
STREG %r17, PT_IOR(%r29)
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 0b47afc20690..3e79e62f7b0b 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -76,16 +76,16 @@ $bss_loop:
mtctl %r4,%cr24 /* Initialize kernel root pointer */
mtctl %r4,%cr25 /* Initialize user root pointer */
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
/* Set pmd in pgd */
load32 PA(pmd0),%r5
shrd %r5,PxD_VALUE_SHIFT,%r3
- ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
+ ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
#else
/* 2-level page table, so pmd == pgd */
- ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
+ ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
#endif
/* Fill in pmd with enough pte directories */
@@ -99,7 +99,7 @@ $bss_loop:
stw %r3,0(%r4)
ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
addib,> -1,%r1,1b
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
ldo ASM_PMD_ENTRY_SIZE(%r4),%r4
#else
ldo ASM_PGD_ENTRY_SIZE(%r4),%r4
@@ -107,13 +107,14 @@ $bss_loop:
/* Now initialize the PTEs themselves */
- ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+ ldo 0+_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+ ldi (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
load32 PA(pg0),%r1
$pgt_fill_loop:
STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1)
- ldo ASM_PAGE_SIZE(%r3),%r3
- bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
+ ldo (1<<PFN_PTE_SHIFT)(%r3),%r3 /* add one PFN */
+ addib,> -1,%r11,$pgt_fill_loop
nop
/* Load the return address...er...crash 'n burn */
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index 7e898fd64415..8384bf9cecd2 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -53,17 +53,17 @@ union thread_union init_thread_union
__attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
-#ifdef __LP64__
+#if PT_NLEVELS == 3
/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
* with the first pmd adjacent to the pgd and below it. gcc doesn't actually
* guarantee that global objects will be laid out in memory in the same order
* as the order of declaration, so put these in different sections and use
* the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
-
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data.vm0.pmd"), aligned(PAGE_SIZE)));
#endif
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte"))) = { {0}, };
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data.vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data.vm0.pte"), aligned(PAGE_SIZE)));
/*
* Initial task structure.
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 7a4f07e8d3c3..f600556414d1 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -65,7 +65,7 @@ flush_tlb_all_local:
*/
/* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
- rsm PSW_SM_I, %r19 /* save I-bit state */
+ rsm PSW_SM_I, %r19 /* save I-bit state */
load32 PA(1f), %r1
nop
nop
@@ -84,8 +84,7 @@ flush_tlb_all_local:
rfi
nop
-1: ldil L%PA(cache_info), %r1
- ldo R%PA(cache_info)(%r1), %r1
+1: load32 PA(cache_info), %r1
/* Flush Instruction Tlb */
@@ -212,8 +211,7 @@ flush_instruction_cache_local:
.entry
mtsp %r0, %sr1
- ldil L%cache_info, %r1
- ldo R%cache_info(%r1), %r1
+ load32 cache_info, %r1
/* Flush Instruction Cache */
@@ -254,8 +252,7 @@ flush_data_cache_local:
.entry
mtsp %r0, %sr1
- ldil L%cache_info, %r1
- ldo R%cache_info(%r1), %r1
+ load32 cache_info, %r1
/* Flush Data Cache */
@@ -303,7 +300,8 @@ copy_user_page_asm:
*/
ldd 0(%r25), %r19
- ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+ ldi ASM_PAGE_SIZE_DIV128, %r1
+
ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */
ldw 128(%r25), %r0 /* prefetch 2 */
@@ -368,7 +366,7 @@ copy_user_page_asm:
* use ldd/std on a 32 bit kernel.
*/
ldw 0(%r25), %r19
- ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+ ldi ASM_PAGE_SIZE_DIV64, %r1
1:
ldw 4(%r25), %r20
@@ -461,6 +459,7 @@ copy_user_page_asm:
sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */
ldil L%(TMPALIAS_MAP_START), %r28
+ /* FIXME for different page sizes != 4k */
#ifdef CONFIG_64BIT
extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */
extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */
@@ -551,6 +550,7 @@ __clear_user_page_asm:
#ifdef CONFIG_64BIT
#if (TMPALIAS_MAP_START >= 0x80000000)
depdi 0, 31,32, %r28 /* clear any sign extension */
+ /* FIXME: page size dependend */
#endif
extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
@@ -566,10 +566,10 @@ __clear_user_page_asm:
pdtlb 0(%r28)
#ifdef CONFIG_64BIT
- ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+ ldi ASM_PAGE_SIZE_DIV128, %r1
/* PREFETCH (Write) has not (yet) been proven to help here */
-/* #define PREFETCHW_OP ldd 256(%0), %r0 */
+ /* #define PREFETCHW_OP ldd 256(%0), %r0 */
1: std %r0, 0(%r28)
std %r0, 8(%r28)
@@ -591,8 +591,7 @@ __clear_user_page_asm:
ldo 128(%r28), %r28
#else /* ! CONFIG_64BIT */
-
- ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+ ldi ASM_PAGE_SIZE_DIV64, %r1
1:
stw %r0, 0(%r28)
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 47ca5c0a323b..fc107add627c 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -31,7 +31,6 @@
#include <linux/string.h>
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strpbrk);
#include <asm/atomic.h>
EXPORT_SYMBOL(__xchg8);
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index d15a1d53e101..8b5df98e2b31 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -231,6 +231,14 @@ asmlinkage long parisc_fadvise64_64(int fd,
(loff_t)high_len << 32 | low_len, advice);
}
+asmlinkage long parisc_sync_file_range(int fd,
+ u32 hi_off, u32 lo_off, u32 hi_nbytes, u32 lo_nbytes,
+ unsigned int flags)
+{
+ return sys_sync_file_range(fd, (loff_t)hi_off << 32 | lo_off,
+ (loff_t)hi_nbytes << 32 | lo_nbytes, flags);
+}
+
asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
{
return -ENOMEM;
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index af88afef41bd..479d9a017cd1 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -55,7 +55,7 @@
* pointers.
*/
- .align 4096
+ .align ASM_PAGE_SIZE
linux_gateway_page:
/* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
@@ -632,7 +632,7 @@ cas_action:
end_compare_and_swap:
/* Make sure nothing else is placed on this page */
- .align 4096
+ .align ASM_PAGE_SIZE
.export end_linux_gateway_page
end_linux_gateway_page:
@@ -652,7 +652,7 @@ end_linux_gateway_page:
.section .rodata,"a"
- .align 4096
+ .align ASM_PAGE_SIZE
/* Light-weight-syscall table */
/* Start of lws table. */
.export lws_table
@@ -662,14 +662,14 @@ lws_table:
LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */
/* End of lws table */
- .align 4096
+ .align ASM_PAGE_SIZE
.export sys_call_table
.Lsys_call_table:
sys_call_table:
#include "syscall_table.S"
#ifdef CONFIG_64BIT
- .align 4096
+ .align ASM_PAGE_SIZE
.export sys_call_table64
.Lsys_call_table64:
sys_call_table64:
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index bbeeb614cfab..e27b432f90a8 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -13,7 +13,7 @@
* Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
* Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
- *
+ * Copyright (C) 2005-2006 Kyle McMartin <kyle at parisc-linux.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
@@ -393,5 +393,11 @@
ENTRY_SAME(readlinkat) /* 285 */
ENTRY_SAME(fchmodat)
ENTRY_SAME(faccessat)
+ ENTRY_SAME(unshare)
+ ENTRY_COMP(set_robust_list)
+ ENTRY_COMP(get_robust_list) /* 290 */
+ ENTRY_SAME(splice)
+ ENTRY_OURS(sync_file_range)
+ ENTRY_SAME(tee)
/* Nothing yet */
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 6d6436a6b624..94dcc03a28ed 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -6,6 +6,7 @@
* Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
* Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
+ * Copyright (C) 2006 Helge Deller <deller@gmx.de>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -27,6 +28,7 @@
/* needed for the processor specific cache alignment size */
#include <asm/cache.h>
#include <asm/page.h>
+#include <asm/asm-offsets.h>
/* ld script to make hppa Linux kernel */
#ifndef CONFIG_64BIT
@@ -68,7 +70,7 @@ SECTIONS
RODATA
/* writeable */
- . = ALIGN(4096); /* Make sure this is page aligned so
+ . = ALIGN(ASM_PAGE_SIZE); /* Make sure this is page aligned so
that we can properly leave these
as writable */
data_start = .;
@@ -81,23 +83,17 @@ SECTIONS
__start___unwind = .; /* unwind info */
.PARISC.unwind : { *(.PARISC.unwind) }
__stop___unwind = .;
-
+
+ /* rarely changed data like cpu maps */
+ . = ALIGN(16);
+ .data.read_mostly : { *(.data.read_mostly) }
+
+ . = ALIGN(L1_CACHE_BYTES);
.data : { /* Data */
*(.data)
- *(.data.vm0.pmd)
- *(.data.vm0.pgd)
- *(.data.vm0.pte)
CONSTRUCTORS
}
- . = ALIGN(4096);
- /* nosave data is really only used for software suspend...it's here
- * just in case we ever implement it */
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(4096);
- __nosave_end = .;
-
. = ALIGN(L1_CACHE_BYTES);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
@@ -105,12 +101,29 @@ SECTIONS
. = ALIGN(16);
.data.lock_aligned : { *(.data.lock_aligned) }
- /* rarely changed data like cpu maps */
- . = ALIGN(16);
- .data.read_mostly : { *(.data.read_mostly) }
+ . = ALIGN(ASM_PAGE_SIZE);
+ /* nosave data is really only used for software suspend...it's here
+ * just in case we ever implement it */
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(ASM_PAGE_SIZE);
+ __nosave_end = .;
_edata = .; /* End of data section */
+ __bss_start = .; /* BSS */
+ /* page table entries need to be PAGE_SIZE aligned */
+ . = ALIGN(ASM_PAGE_SIZE);
+ .data.vmpages : {
+ *(.data.vm0.pmd)
+ *(.data.vm0.pgd)
+ *(.data.vm0.pte)
+ }
+ .bss : { *(.bss) *(COMMON) }
+ __bss_stop = .;
+
+
+ /* assembler code expects init_task to be 16k aligned */
. = ALIGN(16384); /* init_task */
.data.init_task : { *(.data.init_task) }
@@ -126,6 +139,7 @@ SECTIONS
.dlt : { *(.dlt) }
#endif
+ /* reserve space for interrupt stack by aligning __init* to 16k */
. = ALIGN(16384);
__init_begin = .;
.init.text : {
@@ -166,7 +180,7 @@ SECTIONS
from .altinstructions and .eh_frame */
.exit.text : { *(.exit.text) }
.exit.data : { *(.exit.data) }
- . = ALIGN(4096);
+ . = ALIGN(ASM_PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
@@ -174,14 +188,10 @@ SECTIONS
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
- . = ALIGN(4096);
+ . = ALIGN(ASM_PAGE_SIZE);
__init_end = .;
/* freed after init ends here */
- __bss_start = .; /* BSS */
- .bss : { *(.bss) *(COMMON) }
- __bss_stop = .;
-
_end = . ;
/* Sections to be discarded */
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 0ad945d4c0a4..64785e46f93b 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -186,7 +186,7 @@ good_area:
break;
case VM_FAULT_SIGBUS:
/*
- * We hit a hared mapping outside of the file, or some
+ * We hit a shared mapping outside of the file, or some
* other thing happened to us that made us unable to
* handle the page fault gracefully.
*/
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 3796be67cd53..631712562656 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -6,6 +6,7 @@
* changed by Philipp Rumpf
* Copyright 1999 Philipp Rumpf (prumpf@tux.org)
* Copyright 2004 Randolph Chung (tausq@debian.org)
+ * Copyright 2006 Helge Deller (deller@gmx.de)
*
*/
@@ -371,8 +372,8 @@ static void __init setup_bootmem(void)
void free_initmem(void)
{
- unsigned long addr;
-
+ unsigned long addr, init_begin, init_end;
+
printk(KERN_INFO "Freeing unused kernel memory: ");
#ifdef CONFIG_DEBUG_KERNEL
@@ -395,8 +396,11 @@ void free_initmem(void)
local_irq_enable();
#endif
- addr = (unsigned long)(&__init_begin);
- for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ /* align __init_begin and __init_end to page size,
+ ignoring linker script where we might have tried to save RAM */
+ init_begin = PAGE_ALIGN((unsigned long)(&__init_begin));
+ init_end = PAGE_ALIGN((unsigned long)(&__init_end));
+ for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
free_page(addr);
@@ -407,7 +411,7 @@ void free_initmem(void)
/* set up a new led state on systems shipped LED State panel */
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
- printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
+ printk("%luk freed\n", (init_end - init_begin) >> 10);
}
@@ -639,11 +643,13 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
* Map the fault vector writable so we can
* write the HPMC checksum.
*/
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
if (address >= ro_start && address < ro_end
&& address != fv_addr
&& address != gw_addr)
pte = __mk_pte(address, PAGE_KERNEL_RO);
else
+#endif
pte = __mk_pte(address, pgprot);
if (address >= end_paddr)
@@ -874,8 +880,7 @@ unsigned long alloc_sid(void)
flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
spin_lock(&sid_lock);
}
- if (free_space_ids == 0)
- BUG();
+ BUG_ON(free_space_ids == 0);
}
free_space_ids--;
@@ -899,8 +904,7 @@ void free_sid(unsigned long spaceid)
spin_lock(&sid_lock);
- if (*dirty_space_offset & (1L << index))
- BUG(); /* attempt to free space id twice */
+ BUG_ON(*dirty_space_offset & (1L << index)); /* attempt to free space id twice */
*dirty_space_offset |= (1L << index);
dirty_space_ids++;
@@ -975,7 +979,7 @@ static void recycle_sids(void)
static unsigned long recycle_ndirty;
static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
-static unsigned int recycle_inuse = 0;
+static unsigned int recycle_inuse;
void flush_tlb_all(void)
{
@@ -984,9 +988,7 @@ void flush_tlb_all(void)
do_recycle = 0;
spin_lock(&sid_lock);
if (dirty_space_ids > RECYCLE_THRESHOLD) {
- if (recycle_inuse) {
- BUG(); /* FIXME: Use a semaphore/wait queue here */
- }
+ BUG_ON(recycle_inuse); /* FIXME: Use a semaphore/wait queue here */
get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
recycle_inuse++;
do_recycle++;
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 0db12818d7bc..27384567a1d0 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -2,7 +2,7 @@
* arch/parisc/mm/ioremap.c
*
* (C) Copyright 1995 1996 Linus Torvalds
- * (C) Copyright 2001 Helge Deller <deller@gmx.de>
+ * (C) Copyright 2001-2006 Helge Deller <deller@gmx.de>
* (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
*/
@@ -138,6 +138,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
if ((phys_addr >= 0x00080000 && end < 0x000fffff) ||
(phys_addr >= 0x00500000 && end < 0x03bfffff)) {
phys_addr |= F_EXTEND(0xfc000000);
+ flags |= _PAGE_NO_CACHE;
}
#endif
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2cdc35ce8045..6729c98b66f9 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -366,6 +366,7 @@ config PPC_PMAC64
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
+ select PPC_970_NAP
default y
config PPC_PREP
@@ -383,6 +384,7 @@ config PPC_MAPLE
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
select PPC_UDBG_16550
+ select PPC_970_NAP
default n
help
This option enables support for the Maple 970FX Evaluation Board.
@@ -457,6 +459,10 @@ config PPC_MPC106
bool
default n
+config PPC_970_NAP
+ bool
+ default n
+
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_PMAC
@@ -649,6 +655,11 @@ config NUMA
depends on PPC64
default y if SMP && PPC_PSERIES
+config NODES_SHIFT
+ int
+ default "4"
+ depends on NEED_MULTIPLE_NODES
+
config ARCH_SELECT_MEMORY_MODEL
def_bool y
depends on PPC64
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6ec84d37a337..ed5b26aa8be3 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -104,6 +104,10 @@ ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif
+ifeq ($(CONFIG_6xx),y)
+CFLAGS += -mcpu=powerpc
+endif
+
cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge
cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 2c3fd2007676..a45627547d03 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.16-rc2
-# Fri Feb 10 17:33:08 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 13:24:37 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -29,6 +30,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -53,6 +55,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -67,10 +70,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -82,7 +81,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -91,6 +89,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -185,7 +184,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -227,6 +225,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -238,6 +237,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -261,6 +262,7 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
#
@@ -513,6 +515,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -761,7 +764,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -772,6 +774,7 @@ CONFIG_GEN_RTC=y
# Ftape, the floppy tape device driver
#
CONFIG_AGP=m
+# CONFIG_AGP_VIA is not set
CONFIG_AGP_UNINORTH=m
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
@@ -813,7 +816,6 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -832,9 +834,7 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -862,10 +862,6 @@ CONFIG_I2C_POWERMAC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -874,6 +870,7 @@ CONFIG_I2C_POWERMAC=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -883,6 +880,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -901,7 +899,6 @@ CONFIG_FB_NVIDIA=y
CONFIG_FB_NVIDIA_I2C=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_DEBUG is not set
@@ -958,9 +955,11 @@ CONFIG_SND_SEQUENCER=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_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
@@ -977,6 +976,7 @@ CONFIG_SND_SUPPORT_OLD_API=y
# PCI devices
#
# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALS4000 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
@@ -1009,6 +1009,7 @@ CONFIG_SND_SUPPORT_OLD_API=y
# 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
@@ -1041,6 +1042,7 @@ CONFIG_SND_USB_AUDIO=m
#
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
@@ -1068,7 +1070,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=y
@@ -1126,15 +1127,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
CONFIG_USB_CATC=m
@@ -1194,6 +1186,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_HP4X is not set
CONFIG_USB_SERIAL_SAFE=m
@@ -1237,17 +1230,23 @@ CONFIG_USB_EZUSB=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1319,7 +1318,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 1816a46742f6..a95e455a1944 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.16-rc6
-# Wed Mar 15 16:19:52 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:46:44 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
@@ -55,6 +57,7 @@ CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -93,6 +91,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -165,7 +164,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -207,6 +205,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -218,6 +217,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -236,11 +237,14 @@ CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
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 is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -262,20 +266,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+# CONFIG_IP_NF_MATCH_AH is not set
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -479,6 +482,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -702,7 +706,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -751,10 +754,6 @@ CONFIG_MAX_RAW_DEVS=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -779,6 +778,7 @@ CONFIG_MAX_RAW_DEVS=256
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -796,6 +796,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
@@ -805,6 +810,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -878,7 +888,6 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index daaf038a1faa..58e68ce09b0f 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.16-rc2
-# Fri Feb 10 17:33:32 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:48:00 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=128
@@ -55,6 +57,7 @@ CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -93,6 +91,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -188,7 +187,6 @@ CONFIG_PPC_I8259=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -235,6 +233,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -246,6 +245,8 @@ CONFIG_TCP_CONG_BIC=y
#
# 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_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -272,6 +273,7 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
#
@@ -519,6 +521,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -750,6 +753,7 @@ CONFIG_HW_CONSOLE=y
#
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
@@ -767,7 +771,9 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_PRINTER is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
+CONFIG_HVC_DRIVER=y
CONFIG_HVC_CONSOLE=y
+# CONFIG_HVC_RTAS is not set
CONFIG_HVCS=m
#
@@ -779,7 +785,6 @@ CONFIG_HVCS=m
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -830,7 +835,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -849,9 +853,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -879,10 +881,6 @@ CONFIG_I2C_ALGOBIT=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -891,6 +889,7 @@ CONFIG_I2C_ALGOBIT=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -900,6 +899,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -919,7 +919,6 @@ CONFIG_FB_MATROX_MYSTIQUE=y
CONFIG_FB_MATROX_G=y
# CONFIG_FB_MATROX_I2C is not set
CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_DEBUG is not set
@@ -968,6 +967,7 @@ CONFIG_LCD_DEVICE=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
@@ -1048,15 +1048,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1109,6 +1100,11 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=m
@@ -1121,12 +1117,13 @@ CONFIG_INFINIBAND_IPOIB=m
# CONFIG_INFINIBAND_SRP is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1202,7 +1199,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 0cc0995b81b0..803858e86160 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
firmware.o sysfs.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
-obj-$(CONFIG_POWER4) += idle_power4.o
+obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o
procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 54b48f330051..8f85c5e8a55a 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -91,6 +91,7 @@ int main(void)
#endif /* CONFIG_PPC64 */
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index b3a979467225..8866fd26c6b9 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -128,37 +128,36 @@ transfer_to_handler:
stw r12,4(r11)
#endif
b 3f
+
2: /* if from kernel, check interrupted DOZE/NAP mode and
* check for stack overflow
*/
+ lwz r9,THREAD_INFO-THREAD(r12)
+ cmplw r1,r9 /* if r1 <= current->thread_info */
+ ble- stack_ovf /* then the kernel stack overflowed */
+5:
#ifdef CONFIG_6xx
- mfspr r11,SPRN_HID0
- mtcr r11
-BEGIN_FTR_SECTION
- bt- 8,4f /* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
- bt- 9,4f /* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+ tophys(r9,r9) /* check local flags */
+ lwz r12,TI_LOCAL_FLAGS(r9)
+ mtcrf 0x01,r12
+ bt- 31-TLF_NAPPING,4f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
- lwz r11,THREAD_INFO-THREAD(r12)
- cmplw r1,r11 /* if r1 <= current->thread_info */
- ble- stack_ovf /* then the kernel stack overflowed */
3:
mflr r9
lwz r11,0(r9) /* virtual address of handler */
lwz r9,4(r9) /* where to go when done */
- FIX_SRR1(r10,r12)
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r10
mtlr r9
SYNC
RFI /* jump to handler, enable MMU */
-#ifdef CONFIG_6xx
-4: b power_save_6xx_restore
+#ifdef CONFIG_6xx
+4: rlwinm r12,r12,0,~_TLF_NAPPING
+ stw r12,TI_LOCAL_FLAGS(r9)
+ b power_save_6xx_restore
#endif
/*
@@ -167,10 +166,10 @@ transfer_to_handler_cont:
*/
stack_ovf:
/* sometimes we use a statically-allocated stack, which is OK. */
- lis r11,_end@h
- ori r11,r11,_end@l
- cmplw r1,r11
- ble 3b /* r1 <= &_end is OK */
+ lis r12,_end@h
+ ori r12,r12,_end@l
+ cmplw r1,r12
+ ble 5b /* r1 <= &_end is OK */
SAVE_NVGPRS(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
lis r1,init_thread_union@ha
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index a5ae04a57c78..b7d140430a41 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -376,11 +376,28 @@ label##_common: \
bl hdlr; \
b .ret_from_except
+/*
+ * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
+ * in the idle task and therefore need the special idle handling.
+ */
+#define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr) \
+ .align 7; \
+ .globl label##_common; \
+label##_common: \
+ EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
+ FINISH_NAP; \
+ DISABLE_INTS; \
+ bl .save_nvgprs; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ bl hdlr; \
+ b .ret_from_except
+
#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \
.align 7; \
.globl label##_common; \
label##_common: \
EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
+ FINISH_NAP; \
DISABLE_INTS; \
bl .ppc64_runlatch_on; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
@@ -388,6 +405,25 @@ label##_common: \
b .ret_from_except_lite
/*
+ * When the idle code in power4_idle puts the CPU into NAP mode,
+ * it has to do so in a loop, and relies on the external interrupt
+ * and decrementer interrupt entry code to get it out of the loop.
+ * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags
+ * to signal that it is in the loop and needs help to get out.
+ */
+#ifdef CONFIG_PPC_970_NAP
+#define FINISH_NAP \
+BEGIN_FTR_SECTION \
+ clrrdi r11,r1,THREAD_SHIFT; \
+ ld r9,TI_LOCAL_FLAGS(r11); \
+ andi. r10,r9,_TLF_NAPPING; \
+ bnel power4_fixup_nap; \
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+#else
+#define FINISH_NAP
+#endif
+
+/*
* Start of pSeries system interrupt routines
*/
. = 0x100
@@ -772,6 +808,7 @@ hardware_interrupt_iSeries_masked:
.globl machine_check_common
machine_check_common:
EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+ FINISH_NAP
DISABLE_INTS
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -783,7 +820,7 @@ machine_check_common:
STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
- STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception)
+ STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
#ifdef CONFIG_ALTIVEC
STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
@@ -1034,6 +1071,7 @@ unrecov_slb:
.globl hardware_interrupt_entry
hardware_interrupt_common:
EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
+ FINISH_NAP
hardware_interrupt_entry:
DISABLE_INTS
bl .ppc64_runlatch_on
@@ -1041,6 +1079,15 @@ hardware_interrupt_entry:
bl .do_IRQ
b .ret_from_except_lite
+#ifdef CONFIG_PPC_970_NAP
+power4_fixup_nap:
+ andc r9,r9,r10
+ std r9,TI_LOCAL_FLAGS(r11)
+ ld r10,_LINK(r1) /* make idle task do the */
+ std r10,_NIP(r1) /* equivalent of a blr */
+ blr
+#endif
+
.align 7
.globl alignment_common
alignment_common:
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index e9f321d74d85..d491052c8e0c 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -50,9 +50,9 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
- ppc64_runlatch_off();
-
while (!need_resched() && !cpu_should_die()) {
+ ppc64_runlatch_off();
+
if (ppc_md.power_save) {
clear_thread_flag(TIF_POLLING_NRFLAG);
/*
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 12a4efbaa08f..b45fa0e37212 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -22,8 +22,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
-#undef DEBUG
-
.text
/*
@@ -109,12 +107,6 @@ BEGIN_FTR_SECTION
dcbf 0,r4
dcbf 0,r4
END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
- lis r6,nap_enter_count@ha
- lwz r4,nap_enter_count@l(r6)
- addi r4,r4,1
- stw r4,nap_enter_count@l(r6)
-#endif
2:
BEGIN_FTR_SECTION
/* Go to low speed mode on some 750FX */
@@ -144,48 +136,42 @@ BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ rlwinm r9,r1,0,0,31-THREAD_SHIFT /* current thread_info */
+ lwz r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
+ ori r8,r8,_TLF_NAPPING /* so when we take an exception */
+ stw r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
mfmsr r7
ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
- sync
- isync
+1: sync
mtmsr r7
isync
- sync
- blr
-
+ b 1b
+
/*
* Return from NAP/DOZE mode, restore some CPU specific registers,
* we are called with DR/IR still off and r2 containing physical
- * address of current.
+ * address of current. R11 points to the exception frame (physical
+ * address). We have to preserve r10.
*/
_GLOBAL(power_save_6xx_restore)
- mfspr r11,SPRN_HID0
- rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
- cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
- rlwinm r11,r11,0,9,7 /* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
- mtspr SPRN_HID0, r11
+ lwz r9,_LINK(r11) /* interrupted in ppc6xx_idle: */
+ stw r9,_NIP(r11) /* make it do a blr */
-#ifdef DEBUG
- beq cr1,1f
- lis r11,(nap_return_count-KERNELBASE)@ha
- lwz r9,nap_return_count@l(r11)
- addi r9,r9,1
- stw r9,nap_return_count@l(r11)
-1:
-#endif
-
- rlwinm r9,r1,0,0,18
- tophys(r9,r9)
- lwz r11,TI_CPU(r9)
+#ifdef CONFIG_SMP
+ mfspr r12,SPRN_SPRG3
+ lwz r11,TI_CPU(r12) /* get cpu number * 4 */
slwi r11,r11,2
+#else
+ li r11,0
+#endif
/* Todo make sure all these are in the same page
- * and load r22 (@ha part + CPU offset) only once
+ * and load r11 (@ha part + CPU offset) only once
*/
BEGIN_FTR_SECTION
- beq cr1,1f
+ mfspr r9,SPRN_HID0
+ andis. r9,r9,HID0_NAP@h
+ beq 1f
addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
lwz r9,nap_save_msscr0@l(r9)
mtspr SPRN_MSSCR0, r9
@@ -210,10 +196,3 @@ _GLOBAL(nap_save_hid1)
_GLOBAL(powersave_lowspeed)
.long 0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
- .space 4
-_GLOBAL(nap_return_count)
- .space 4
-#endif
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 6dad1c02496e..d85c7c938eed 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -35,12 +35,16 @@ BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ clrrdi r9,r1,THREAD_SHIFT /* current thread_info */
+ ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
+ ori r8,r8,_TLF_NAPPING /* so when we take an exception */
+ std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
mfmsr r7
ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
- sync
+1: sync
isync
mtmsrd r7
isync
- sync
- blr
+ b 1b
+
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d9a7fdef59b9..4eba60a32890 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -61,6 +61,7 @@ __setup("iommu=", setup_iommu);
static unsigned long iommu_range_alloc(struct iommu_table *tbl,
unsigned long npages,
unsigned long *handle,
+ unsigned long mask,
unsigned int align_order)
{
unsigned long n, end, i, start;
@@ -97,9 +98,21 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
*/
if (start >= limit)
start = largealloc ? tbl->it_largehint : tbl->it_hint;
-
+
again:
+ if (limit + tbl->it_offset > mask) {
+ limit = mask - tbl->it_offset + 1;
+ /* If we're constrained on address range, first try
+ * at the masked hint to avoid O(n) search complexity,
+ * but on second pass, start at 0.
+ */
+ if ((start & mask) >= limit || pass > 0)
+ start = 0;
+ else
+ start &= mask;
+ }
+
n = find_next_zero_bit(tbl->it_map, limit, start);
/* Align allocation */
@@ -150,14 +163,14 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
unsigned int npages, enum dma_data_direction direction,
- unsigned int align_order)
+ unsigned long mask, unsigned int align_order)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
-
+
spin_lock_irqsave(&(tbl->it_lock), flags);
- entry = iommu_range_alloc(tbl, npages, NULL, align_order);
+ entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
if (unlikely(entry == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -236,7 +249,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
- enum dma_data_direction direction)
+ unsigned long mask, enum dma_data_direction direction)
{
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
@@ -274,7 +287,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
vaddr = (unsigned long)page_address(s->page) + s->offset;
npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
npages >>= PAGE_SHIFT;
- entry = iommu_range_alloc(tbl, npages, &handle, 0);
+ entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -479,7 +492,8 @@ void iommu_free_table(struct device_node *dn)
* byte within the page as vaddr.
*/
dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, enum dma_data_direction direction)
+ size_t size, unsigned long mask,
+ enum dma_data_direction direction)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
unsigned long uaddr;
@@ -492,7 +506,8 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
npages >>= PAGE_SHIFT;
if (tbl) {
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0);
+ dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+ mask >> PAGE_SHIFT, 0);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
printk(KERN_INFO "iommu_alloc failed, "
@@ -521,7 +536,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* to the dma address (mapping) of the first page.
*/
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -551,7 +566,8 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
memset(ret, 0, size);
/* Set up tces to cover the allocated range */
- mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order);
+ mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL,
+ mask >> PAGE_SHIFT, order);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
ret = NULL;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index bb5c9501234c..57d560c68897 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -272,18 +272,26 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
* Don't use virtual irqs 0, 1, 2 for devices.
* The pcnet32 driver considers interrupt numbers < 2 to be invalid,
* and 2 is the XICS IPI interrupt.
- * We limit virtual irqs to 17 less than NR_IRQS so that when we
- * offset them by 16 (to reserve the first 16 for ISA interrupts)
- * we don't end up with an interrupt number >= NR_IRQS.
+ * We limit virtual irqs to __irq_offet_value less than virt_irq_max so
+ * that when we offset them we don't end up with an interrupt
+ * number >= virt_irq_max.
*/
#define MIN_VIRT_IRQ 3
-#define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1)
-#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)
+
+unsigned int virt_irq_max;
+static unsigned int max_virt_irq;
+static unsigned int nr_virt_irqs;
void
virt_irq_init(void)
{
int i;
+
+ if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1)))
+ virt_irq_max = NR_IRQS - 1;
+ max_virt_irq = virt_irq_max - __irq_offset_value;
+ nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1;
+
for (i = 0; i < NR_IRQS; i++)
virt_irq_to_real_map[i] = UNDEFINED_IRQ;
}
@@ -308,17 +316,17 @@ int virt_irq_create_mapping(unsigned int real_irq)
return real_irq;
}
- /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */
+ /* map to a number between MIN_VIRT_IRQ and max_virt_irq */
virq = real_irq;
- if (virq > MAX_VIRT_IRQ)
- virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+ if (virq > max_virt_irq)
+ virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
/* search for this number or a free slot */
first_virq = virq;
while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
if (virt_irq_to_real_map[virq] == real_irq)
return virq;
- if (++virq > MAX_VIRT_IRQ)
+ if (++virq > max_virt_irq)
virq = MIN_VIRT_IRQ;
if (virq == first_virq)
goto nospace; /* oops, no free slots */
@@ -330,8 +338,8 @@ int virt_irq_create_mapping(unsigned int real_irq)
nospace:
if (!warned) {
printk(KERN_CRIT "Interrupt table is full\n");
- printk(KERN_CRIT "Increase NR_IRQS (currently %d) "
- "in your kernel sources and rebuild.\n", NR_IRQS);
+ printk(KERN_CRIT "Increase virt_irq_max (currently %d) "
+ "in your kernel sources and rebuild.\n", virt_irq_max);
warned = 1;
}
return NO_IRQ;
@@ -349,8 +357,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
virq = real_irq;
- if (virq > MAX_VIRT_IRQ)
- virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+ if (virq > max_virt_irq)
+ virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
first_virq = virq;
@@ -360,7 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
virq++;
- if (virq >= MAX_VIRT_IRQ)
+ if (virq >= max_virt_irq)
virq = 0;
} while (first_virq != virq);
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index ad7a90212204..856ef1a832b9 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -88,7 +88,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex);
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = *p->ainsn.insn;
@@ -101,21 +101,21 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->nip = (unsigned long)p->ainsn.insn;
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -141,7 +141,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
}
}
-static inline int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
@@ -334,7 +334,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
regs->nip = (unsigned long)p->addr + 4;
}
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -370,7 +370,7 @@ out:
return 1;
}
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 1b73508ecb2b..2cbde865d4f5 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -37,7 +37,7 @@
#include <asm/prom.h>
#include <asm/vdso_datapage.h>
-#define MODULE_VERS "1.6"
+#define MODULE_VERS "1.7"
#define MODULE_NAME "lparcfg"
/* #define LPARCFG_DEBUG */
@@ -149,17 +149,17 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag)
if (rc == 0) /* success, return */
return;
/* check for null tag ? */
- if (rc == H_Hardware)
+ if (rc == H_HARDWARE)
printk(KERN_INFO
"plpar-hcall (%s) failed with hardware fault\n", tag);
- else if (rc == H_Function)
+ else if (rc == H_FUNCTION)
printk(KERN_INFO
"plpar-hcall (%s) failed; function not allowed\n", tag);
- else if (rc == H_Authority)
+ else if (rc == H_AUTHORITY)
printk(KERN_INFO
- "plpar-hcall (%s) failed; not authorized to this function\n",
- tag);
- else if (rc == H_Parameter)
+ "plpar-hcall (%s) failed; not authorized to this"
+ " function\n", tag);
+ else if (rc == H_PARAMETER)
printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
tag);
else
@@ -209,7 +209,7 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
unsigned long dummy;
rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
- if (rc != H_Authority)
+ if (rc != H_AUTHORITY)
log_plpar_hcall_return(rc, "H_PIC");
}
@@ -242,7 +242,7 @@ static void parse_system_parameter_string(struct seq_file *m)
{
int call_status;
- char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+ unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
if (!local_buffer) {
printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
__FILE__, __FUNCTION__, __LINE__);
@@ -254,7 +254,8 @@ static void parse_system_parameter_string(struct seq_file *m)
call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
NULL,
SPLPAR_CHARACTERISTICS_TOKEN,
- __pa(rtas_data_buf));
+ __pa(rtas_data_buf),
+ RTAS_DATA_BUF_SIZE);
memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
spin_unlock(&rtas_data_buf_lock);
@@ -275,7 +276,7 @@ static void parse_system_parameter_string(struct seq_file *m)
#ifdef LPARCFG_DEBUG
printk(KERN_INFO "success calling get-system-parameter \n");
#endif
- splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
+ splpar_strlen = local_buffer[0] * 256 + local_buffer[1];
local_buffer += 2; /* step over strlen value */
memset(workbuffer, 0, SPLPAR_MAXLENGTH);
@@ -529,13 +530,13 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
*new_weight_ptr);
- if (retval == H_Success || retval == H_Constrained) {
+ if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
retval = count;
- } else if (retval == H_Busy) {
+ } else if (retval == H_BUSY) {
retval = -EBUSY;
- } else if (retval == H_Hardware) {
+ } else if (retval == H_HARDWARE) {
retval = -EIO;
- } else if (retval == H_Parameter) {
+ } else if (retval == H_PARAMETER) {
retval = -EINVAL;
} else {
printk(KERN_WARNING "%s: received unknown hv return code %ld",
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c336f3e31cff..c1d95e14bbed 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -59,6 +59,25 @@ static inline struct iommu_table *devnode_table(struct device *dev)
}
+static inline unsigned long device_to_mask(struct device *hwdev)
+{
+ struct pci_dev *pdev;
+
+ if (!hwdev) {
+ pdev = ppc64_isabridge_dev;
+ if (!pdev) /* This is the best guess we can do */
+ return 0xfffffffful;
+ } else
+ pdev = to_pci_dev(hwdev);
+
+ if (pdev->dma_mask)
+ return pdev->dma_mask;
+
+ /* Assume devices without mask can take 32 bit addresses */
+ return 0xfffffffful;
+}
+
+
/* Allocates a contiguous real buffer and creates mappings over it.
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
@@ -67,7 +86,7 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
- flag);
+ device_to_mask(hwdev), flag);
}
static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
@@ -85,7 +104,8 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
- return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
+ return iommu_map_single(devnode_table(hwdev), vaddr, size,
+ device_to_mask(hwdev), direction);
}
@@ -100,7 +120,7 @@ static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
return iommu_map_sg(pdev, devnode_table(pdev), sglist,
- nelems, direction);
+ nelems, device_to_mask(pdev), direction);
}
static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
@@ -112,7 +132,19 @@ static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
/* We support DMA to/from any memory page via the iommu */
static int pci_iommu_dma_supported(struct device *dev, u64 mask)
{
- return 1;
+ struct iommu_table *tbl = devnode_table(dev);
+
+ if (!tbl || tbl->it_offset > mask) {
+ printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
+ if (tbl)
+ printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
+ mask, tbl->it_offset);
+ else
+ printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
+ mask);
+ return 0;
+ } else
+ return 1;
}
void pci_iommu_init(void)
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index dfa5398ab3c8..4b052ae5dc34 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -81,6 +81,7 @@ EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4336390bcf34..1cb69e8fb0b1 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -62,7 +62,7 @@ static int __initdata dt_root_addr_cells;
static int __initdata dt_root_size_cells;
#ifdef CONFIG_PPC64
-static int __initdata iommu_is_off;
+int __initdata iommu_is_off;
int __initdata iommu_force_on;
unsigned long tce_alloc_start, tce_alloc_end;
#endif
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index d66c5e77fcff..7e4d54821a07 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1528,12 +1528,11 @@ static int __init prom_find_machine_type(void)
* non-IBM designs !
* - it has /rtas
*/
- len = prom_getprop(_prom->root, "model",
+ len = prom_getprop(_prom->root, "device_type",
compat, sizeof(compat)-1);
if (len <= 0)
return PLATFORM_GENERIC;
- compat[len] = 0;
- if (strcmp(compat, "chrp"))
+ if (strncmp(compat, RELOC("chrp"), 4))
return PLATFORM_GENERIC;
/* Default to pSeries. We need to know if we are running LPAR */
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 456286cf1d14..9c9ad1fa9cce 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -258,11 +258,11 @@ static int __init proc_rtas_init(void)
struct proc_dir_entry *entry;
if (!machine_is(pseries))
- return 1;
+ return -ENODEV;
rtas_node = of_find_node_by_name(NULL, "rtas");
if (rtas_node == NULL)
- return 1;
+ return -ENODEV;
entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
if (entry)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 06636c927a7e..0112318213ab 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -578,18 +578,18 @@ static void rtas_percpu_suspend_me(void *info)
* We use "waiting" to indicate our state. As long
* as it is >0, we are still trying to all join up.
* If it goes to 0, we have successfully joined up and
- * one thread got H_Continue. If any error happens,
+ * one thread got H_CONTINUE. If any error happens,
* we set it to <0.
*/
local_irq_save(flags);
do {
rc = plpar_hcall_norets(H_JOIN);
smp_rmb();
- } while (rc == H_Success && data->waiting > 0);
- if (rc == H_Success)
+ } while (rc == H_SUCCESS && data->waiting > 0);
+ if (rc == H_SUCCESS)
goto out;
- if (rc == H_Continue) {
+ if (rc == H_CONTINUE) {
data->waiting = 0;
data->args->args[data->args->nargs] =
rtas_call(ibm_suspend_me_token, 0, 1, NULL);
@@ -597,7 +597,7 @@ static void rtas_percpu_suspend_me(void *info)
plpar_hcall_norets(H_PROD,i);
} else {
data->waiting = -EBUSY;
- printk(KERN_ERR "Error on H_Join hypervisor call\n");
+ printk(KERN_ERR "Error on H_JOIN hypervisor call\n");
}
out:
@@ -624,7 +624,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
printk(KERN_ERR "Error doing global join\n");
/* Prod each CPU. This won't hurt, and will wake
- * anyone we successfully put to sleep with H_Join
+ * anyone we successfully put to sleep with H_JOIN.
*/
for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD, i);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index a72bf5dceeee..69ac25701344 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -50,7 +50,6 @@
#include <asm/kgdb.h>
#endif
-extern void platform_init(void);
extern void bootx_init(unsigned long r4, unsigned long phys);
boot_infos_t *boot_infos;
@@ -138,12 +137,7 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
#endif /* CONFIG_CMDLINE */
-#ifdef CONFIG_PPC_MULTIPLATFORM
probe_machine();
-#else
- /* Base init based on machine type. Obsoloete, please kill ! */
- platform_init();
-#endif
#ifdef CONFIG_6xx
if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 59aa92cd6fa4..13e91c4d70a8 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -215,12 +215,10 @@ void __init early_setup(unsigned long dt_ptr)
/*
* Initialize stab / SLB management except on iSeries
*/
- if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
- if (cpu_has_feature(CPU_FTR_SLB))
- slb_initialize();
- else
- stab_initialize(get_paca()->stab_real);
- }
+ if (cpu_has_feature(CPU_FTR_SLB))
+ slb_initialize();
+ else if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ stab_initialize(get_paca()->stab_real);
DBG(" <- early_setup()\n");
}
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 73560ef6f802..ed737cacf92d 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -279,7 +279,7 @@ static void unregister_cpu_online(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit sysfs_cpu_notify(struct notifier_block *self,
+static int sysfs_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
@@ -297,7 +297,7 @@ static int __devinit sysfs_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata sysfs_cpu_nb = {
+static struct notifier_block sysfs_cpu_nb = {
.notifier_call = sysfs_cpu_notify,
};
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 1ad55f0466fd..0b98eea73c5e 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -322,3 +322,11 @@ SYSCALL(spu_create)
COMPAT_SYS(pselect6)
COMPAT_SYS(ppoll)
SYSCALL(unshare)
+SYSCALL(splice)
+SYSCALL(tee)
+SYSCALL(vmsplice)
+
+/*
+ * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
+ * as well when appropriate.
+ */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 4cbde211eb69..064a52564692 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -228,7 +228,7 @@ void system_reset_exception(struct pt_regs *regs)
*/
static inline int check_io_access(struct pt_regs *regs)
{
-#ifdef CONFIG_PPC_PMAC
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
unsigned long msr = regs->msr;
const struct exception_table_entry *entry;
unsigned int *nip = (unsigned int *)regs->nip;
@@ -261,7 +261,7 @@ static inline int check_io_access(struct pt_regs *regs)
return 1;
}
}
-#endif /* CONFIG_PPC_PMAC */
+#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
return 0;
}
@@ -308,8 +308,8 @@ platform_machine_check(struct pt_regs *regs)
void machine_check_exception(struct pt_regs *regs)
{
-#ifdef CONFIG_PPC64
int recover = 0;
+ unsigned long reason = get_mc_reason(regs);
/* See if any machine dependent calls */
if (ppc_md.machine_check_exception)
@@ -317,8 +317,6 @@ void machine_check_exception(struct pt_regs *regs)
if (recover)
return;
-#else
- unsigned long reason = get_mc_reason(regs);
if (user_mode(regs)) {
regs->msr |= MSR_RI;
@@ -462,7 +460,6 @@ void machine_check_exception(struct pt_regs *regs)
* additional info, e.g. bus error registers.
*/
platform_machine_check(regs);
-#endif /* CONFIG_PPC64 */
if (debugger_fault_handler(regs))
return;
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 13c655ba2841..971020cf3f7d 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -202,7 +202,7 @@ static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
- direction);
+ ~0ul, direction);
}
static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
@@ -216,7 +216,7 @@ static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
- nelems, direction);
+ nelems, ~0ul, direction);
}
static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
@@ -229,7 +229,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
- dma_handle, flag);
+ dma_handle, ~0ul, flag);
}
static void vio_free_coherent(struct device *dev, size_t size,
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 5aea0909a5ec..fdbba4206d59 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -177,15 +177,15 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
/* When running in the kernel we expect faults to occur only to
* addresses in user space. All other faults represent errors in the
- * kernel and should generate an OOPS. Unfortunatly, in the case of an
- * erroneous fault occuring in a code path which already holds mmap_sem
+ * kernel and should generate an OOPS. Unfortunately, in the case of an
+ * erroneous fault occurring in a code path which already holds mmap_sem
* we will deadlock attempting to validate the fault against the
* address space. Luckily the kernel only validly references user
* space from well defined areas of code, which are listed in the
* exceptions table.
*
* As the vast majority of faults will be valid we will only perform
- * the source reference check when there is a possibilty of a deadlock.
+ * the source reference check when there is a possibility of a deadlock.
* Attempt to lock the address space, if we cannot we then validate the
* source. If this is invalid we can skip the address space check,
* thus avoiding the deadlock.
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 7c18b4cd5db4..7e789d2420ba 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -158,25 +158,25 @@ static int __init mpc834x_rtc_hookup(void)
late_initcall(mpc834x_rtc_hookup);
#endif
-void __init platform_init(void)
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc834x_sys_probe(void)
{
- /* setup the PowerPC module struct */
- ppc_md.setup_arch = mpc834x_sys_setup_arch;
-
- ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
- ppc_md.get_irq = ipic_get_irq;
-
- ppc_md.restart = mpc83xx_restart;
-
- ppc_md.time_init = mpc83xx_time_init;
- ppc_md.set_rtc_time = NULL;
- ppc_md.get_rtc_time = NULL;
- ppc_md.calibrate_decr = generic_calibrate_decr;
-
- ppc_md.progress = udbg_progress;
-
- if (ppc_md.progress)
- ppc_md.progress("mpc834x_sys_init(): exit", 0);
-
- return;
+ /* We always match for now, eventually we should look at the flat
+ dev tree to ensure this is the board we are suppose to run on
+ */
+ return 1;
}
+
+define_machine(mpc834x_sys) {
+ .name = "MPC834x SYS",
+ .probe = mpc834x_sys_probe,
+ .setup_arch = mpc834x_sys_setup_arch,
+ .init_IRQ = mpc834x_sys_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index b7821dbae00d..5eeff370f5fc 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -220,25 +220,25 @@ void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
}
-void __init platform_init(void)
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_ads_probe(void)
{
- ppc_md.setup_arch = mpc85xx_ads_setup_arch;
- ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
-
- ppc_md.init_IRQ = mpc85xx_ads_pic_init;
- ppc_md.get_irq = mpic_get_irq;
-
- ppc_md.restart = mpc85xx_restart;
- ppc_md.power_off = NULL;
- ppc_md.halt = NULL;
-
- ppc_md.time_init = NULL;
- ppc_md.set_rtc_time = NULL;
- ppc_md.get_rtc_time = NULL;
- ppc_md.calibrate_decr = generic_calibrate_decr;
-
- ppc_md.progress = udbg_progress;
-
- if (ppc_md.progress)
- ppc_md.progress("mpc85xx_ads platform_init(): exit", 0);
+ /* We always match for now, eventually we should look at the flat
+ dev tree to ensure this is the board we are suppose to run on
+ */
+ return 1;
}
+
+define_machine(mpc85xx_ads) {
+ .name = "MPC85xx ADS",
+ .probe = mpc85xx_ads_probe,
+ .setup_arch = mpc85xx_ads_setup_arch,
+ .init_IRQ = mpc85xx_ads_pic_init,
+ .show_cpuinfo = mpc85xx_ads_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = mpc85xx_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index 3a4245c926ad..b283380a2a18 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -316,17 +316,18 @@ void *spu_syscall_table[] = {
[__NR_pselect6] sys_ni_syscall, /* sys_pselect */
[__NR_ppoll] sys_ni_syscall, /* sys_ppoll */
[__NR_unshare] sys_unshare,
+ [__NR_splice] sys_splice,
+ [__NR_tee] sys_tee,
+ [__NR_vmsplice] sys_vmsplice,
};
long spu_sys_callback(struct spu_syscall_block *s)
{
long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
- BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls);
-
syscall = spu_syscall_table[s->nr_ret];
- if (s->nr_ret >= __NR_syscalls) {
+ if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
return -ENOSYS;
}
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index c04e078c0fe5..483c8b76232c 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -2,6 +2,7 @@
#include <linux/ptrace.h>
#include <asm/spu.h>
+#include <asm/unistd.h>
#include "spufs.h"
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 97898d5d34e5..1726bfe38ee0 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -1297,7 +1297,7 @@ static inline void setup_decr(struct spu_state *csa, struct spu *spu)
cycles_t resume_time = get_cycles();
cycles_t delta_time = resume_time - csa->suspend_time;
- csa->lscsa->decr.slot[0] = delta_time;
+ csa->lscsa->decr.slot[0] -= delta_time;
}
}
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 63f0aee4c158..996c28744e96 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -9,3 +9,4 @@ extern long chrp_time_init(void);
extern void chrp_find_bridges(void);
extern void chrp_event_scan(unsigned long);
+extern void chrp_pcibios_fixup(void);
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 8ef279ad36ad..ac224876ce59 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -23,6 +23,8 @@
#include <asm/grackle.h>
#include <asm/rtas.h>
+#include "chrp.h"
+
/* LongTrail */
void __iomem *gg2_pci_config_base;
@@ -314,6 +316,6 @@ chrp_find_bridges(void)
}
/* Do not fixup interrupts from OF tree on pegasos */
- if (is_pegasos == 0)
- ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+ if (is_pegasos)
+ ppc_md.pcibios_fixup = NULL;
}
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 23a201718704..18d89f38796b 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -440,8 +440,6 @@ void __init chrp_init_IRQ(void)
if (_chrp_type == _CHRP_Pegasos)
ppc_md.get_irq = i8259_irq;
- else
- ppc_md.get_irq = mpic_get_irq;
#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
/* see if there is a keyboard in the device tree
@@ -528,26 +526,24 @@ static int __init chrp_probe(void)
/* Assume we have an 8259... */
__irq_offset_value = NUM_ISA_INTERRUPTS;
- ppc_md.setup_arch = chrp_setup_arch;
- ppc_md.show_cpuinfo = chrp_show_cpuinfo;
-
- ppc_md.init_IRQ = chrp_init_IRQ;
- ppc_md.init = chrp_init2;
-
- ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
- ppc_md.restart = rtas_restart;
- ppc_md.power_off = rtas_power_off;
- ppc_md.halt = rtas_halt;
-
- ppc_md.time_init = chrp_time_init;
- ppc_md.calibrate_decr = generic_calibrate_decr;
-
- /* this may get overridden with rtas routines later... */
- ppc_md.set_rtc_time = chrp_set_rtc_time;
- ppc_md.get_rtc_time = chrp_get_rtc_time;
-
-#ifdef CONFIG_SMP
- smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
+ return 1;
}
+
+define_machine(chrp) {
+ .name = "CHRP",
+ .probe = chrp_probe,
+ .setup_arch = chrp_setup_arch,
+ .init = chrp_init2,
+ .show_cpuinfo = chrp_show_cpuinfo,
+ .init_IRQ = chrp_init_IRQ,
+ .get_irq = mpic_get_irq,
+ .pcibios_fixup = chrp_pcibios_fixup,
+ .restart = rtas_restart,
+ .power_off = rtas_power_off,
+ .halt = rtas_halt,
+ .time_init = chrp_time_init,
+ .set_rtc_time = chrp_set_rtc_time,
+ .get_rtc_time = chrp_get_rtc_time,
+ .calibrate_decr = generic_calibrate_decr,
+ .phys_mem_access_prot = pci_phys_mem_access_prot,
+};
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 6ce8a404ba6b..a6fd9bedb074 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -54,6 +54,7 @@
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
+#include <asm/irq.h>
#include "naca.h"
#include "setup.h"
@@ -684,6 +685,12 @@ static int __init iseries_probe(void)
powerpc_firmware_features |= FW_FEATURE_ISERIES;
powerpc_firmware_features |= FW_FEATURE_LPAR;
+ /*
+ * The Hypervisor only allows us up to 256 interrupt
+ * sources (the irq number is passed in a u8).
+ */
+ virt_irq_max = 255;
+
return 1;
}
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index e14f9ac55cf4..df2343e1956b 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -231,6 +231,14 @@ static u8 kw_i2c_wait_interrupt(struct pmac_i2c_host_kw *host)
return isr;
}
+static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result)
+{
+ kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+ host->state = state_stop;
+ host->result = result;
+}
+
+
static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
{
u8 ack;
@@ -246,42 +254,36 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
}
if (isr == 0) {
+ printk(KERN_WARNING "low_i2c: Timeout in i2c transfer"
+ " on keywest !\n");
if (host->state != state_stop) {
- DBG_LOW("KW: Timeout !\n");
- host->result = -EIO;
- goto stop;
- }
- if (host->state == state_stop) {
- ack = kw_read_reg(reg_status);
- if (ack & KW_I2C_STAT_BUSY)
- kw_write_reg(reg_status, 0);
- host->state = state_idle;
- kw_write_reg(reg_ier, 0x00);
- if (!host->polled)
- complete(&host->complete);
+ kw_i2c_do_stop(host, -EIO);
+ return;
}
+ ack = kw_read_reg(reg_status);
+ if (ack & KW_I2C_STAT_BUSY)
+ kw_write_reg(reg_status, 0);
+ host->state = state_idle;
+ kw_write_reg(reg_ier, 0x00);
+ if (!host->polled)
+ complete(&host->complete);
return;
}
if (isr & KW_I2C_IRQ_ADDR) {
ack = kw_read_reg(reg_status);
if (host->state != state_addr) {
- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
WRONG_STATE("KW_I2C_IRQ_ADDR");
- host->result = -EIO;
- goto stop;
+ kw_i2c_do_stop(host, -EIO);
}
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- host->result = -ENODEV;
- DBG_LOW("KW: NAK on address\n");
+ host->result = -ENXIO;
host->state = state_stop;
- return;
+ DBG_LOW("KW: NAK on address\n");
} else {
- if (host->len == 0) {
- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- goto stop;
- }
- if (host->rw) {
+ if (host->len == 0)
+ kw_i2c_do_stop(host, 0);
+ else if (host->rw) {
host->state = state_read;
if (host->len > 1)
kw_write_reg(reg_control,
@@ -308,25 +310,19 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
ack = kw_read_reg(reg_status);
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
DBG_LOW("KW: nack on data write\n");
- host->result = -EIO;
- goto stop;
+ host->result = -EFBIG;
+ host->state = state_stop;
} else if (host->len) {
kw_write_reg(reg_data, *(host->data++));
host->len--;
- } else {
- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- host->state = state_stop;
- host->result = 0;
- }
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+ } else
+ kw_i2c_do_stop(host, 0);
} else {
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
WRONG_STATE("KW_I2C_IRQ_DATA");
- if (host->state != state_stop) {
- host->result = -EIO;
- goto stop;
- }
+ if (host->state != state_stop)
+ kw_i2c_do_stop(host, -EIO);
}
+ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
}
if (isr & KW_I2C_IRQ_STOP) {
@@ -340,14 +336,10 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
complete(&host->complete);
}
+ /* Below should only happen in manual mode which we don't use ... */
if (isr & KW_I2C_IRQ_START)
kw_write_reg(reg_isr, KW_I2C_IRQ_START);
- return;
- stop:
- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- host->state = state_stop;
- return;
}
/* Interrupt handler */
@@ -544,11 +536,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
return NULL;
}
- /* Make sure IRA is disabled */
+ /* Make sure IRQ is disabled */
kw_write_reg(reg_ier, 0);
/* Request chip interrupt */
- if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host))
+ if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host))
host->irq = NO_IRQ;
printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f5d8d15d74fa..ea179afea632 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1097,7 +1097,7 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
* (iBook second controller)
*/
if (dev->vendor == PCI_VENDOR_ID_APPLE
- && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
+ && dev->class == PCI_CLASS_SERIAL_USB_OHCI
&& !node) {
printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
pci_name(dev));
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 9b2b1cb117b3..32eaddfa5470 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -865,7 +865,7 @@ void __init eeh_init(void)
* on the CEC architecture, type of the device, on earlier boot
* command-line arguments & etc.
*/
-void eeh_add_device_early(struct device_node *dn)
+static void eeh_add_device_early(struct device_node *dn)
{
struct pci_controller *phb;
struct eeh_early_enable_info info;
@@ -882,7 +882,6 @@ void eeh_add_device_early(struct device_node *dn)
info.buid_lo = BUID_LO(phb->buid);
early_enable_eeh(dn, &info);
}
-EXPORT_SYMBOL_GPL(eeh_add_device_early);
void eeh_add_device_tree_early(struct device_node *dn)
{
@@ -893,20 +892,6 @@ void eeh_add_device_tree_early(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
-void eeh_add_device_tree_late(struct pci_bus *bus)
-{
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- eeh_add_device_late(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *subbus = dev->subordinate;
- if (subbus)
- eeh_add_device_tree_late(subbus);
- }
- }
-}
-
/**
* eeh_add_device_late - perform EEH initialization for the indicated pci device
* @dev: pci device for which to set up EEH
@@ -914,7 +899,7 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
* This routine must be used to complete EEH initialization for PCI
* devices that were added after system boot (e.g. hotplug, dlpar).
*/
-void eeh_add_device_late(struct pci_dev *dev)
+static void eeh_add_device_late(struct pci_dev *dev)
{
struct device_node *dn;
struct pci_dn *pdn;
@@ -933,16 +918,33 @@ void eeh_add_device_late(struct pci_dev *dev)
pci_addr_cache_insert_device (dev);
}
-EXPORT_SYMBOL_GPL(eeh_add_device_late);
+
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_add_device_late(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ eeh_add_device_tree_late(subbus);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
/**
* eeh_remove_device - undo EEH setup for the indicated pci device
* @dev: pci device to be removed
*
- * This routine should be when a device is removed from a running
- * system (e.g. by hotplug or dlpar).
+ * This routine should be called when a device is removed from
+ * a running system (e.g. by hotplug or dlpar). It unregisters
+ * the PCI device from the EEH subsystem. I/O errors affecting
+ * this device will no longer be detected after this call; thus,
+ * i/o errors affecting this slot may leave this device unusable.
*/
-void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev)
{
struct device_node *dn;
if (!dev || !eeh_subsystem_enabled)
@@ -955,24 +957,22 @@ void eeh_remove_device(struct pci_dev *dev)
pci_addr_cache_remove_device(dev);
dn = pci_device_to_OF_node(dev);
- PCI_DN(dn)->pcidev = NULL;
- pci_dev_put (dev);
+ if (PCI_DN(dn)->pcidev) {
+ PCI_DN(dn)->pcidev = NULL;
+ pci_dev_put (dev);
+ }
}
-EXPORT_SYMBOL_GPL(eeh_remove_device);
void eeh_remove_bus_device(struct pci_dev *dev)
{
+ struct pci_bus *bus = dev->subordinate;
+ struct pci_dev *child, *tmp;
+
eeh_remove_device(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *bus = dev->subordinate;
- struct list_head *ln;
- if (!bus)
- return;
- for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *pdev = pci_dev_b(ln);
- if (pdev)
- eeh_remove_bus_device(pdev);
- }
+
+ if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+ eeh_remove_bus_device(child);
}
}
EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index cc2495a0cdd5..1fba695e32e8 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -293,15 +293,16 @@ void handle_eeh_events (struct eeh_event *event)
frozen_pdn = PCI_DN(frozen_dn);
frozen_pdn->eeh_freeze_count++;
- pci_str = pci_name (frozen_pdn->pcidev);
- drv_str = pcid_name (frozen_pdn->pcidev);
- if (!pci_str) {
+ if (frozen_pdn->pcidev) {
+ pci_str = pci_name (frozen_pdn->pcidev);
+ drv_str = pcid_name (frozen_pdn->pcidev);
+ } else {
pci_str = pci_name (event->dev);
drv_str = pcid_name (event->dev);
}
if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
- goto hard_fail;
+ goto excess_failures;
/* If the reset state is a '5' and the time to reset is 0 (infinity)
* or is more then 15 seconds, then mark this as a permanent failure.
@@ -356,7 +357,7 @@ void handle_eeh_events (struct eeh_event *event)
return;
-hard_fail:
+excess_failures:
/*
* About 90% of all real-life EEH failures in the field
* are due to poorly seated PCI cards. Only 10% or so are
@@ -367,7 +368,15 @@ hard_fail:
"and has been permanently disabled. Please try reseating\n"
"this device or replacing it.\n",
drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+ goto perm_error;
+
+hard_fail:
+ printk(KERN_ERR
+ "EEH: Unable to recover from failure of PCI device %s - %s\n"
+ "Please try reseating this device or replacing it.\n",
+ drv_str, pci_str);
+perm_error:
eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
/* Notify all devices that they're about to go down. */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 9a9961f27480..a1bda6f96fd1 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -19,7 +19,9 @@
*/
#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/pci.h>
+#include <linux/workqueue.h>
#include <asm/eeh_event.h>
#include <asm/ppc-pci.h>
@@ -37,14 +39,18 @@ LIST_HEAD(eeh_eventlist);
static void eeh_thread_launcher(void *);
DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
+/* Serialize reset sequences for a given pci device */
+DEFINE_MUTEX(eeh_event_mutex);
+
/**
- * eeh_event_handler - dispatch EEH events. The detection of a frozen
- * slot can occur inside an interrupt, where it can be hard to do
- * anything about it. The goal of this routine is to pull these
- * detection events out of the context of the interrupt handler, and
- * re-dispatch them for processing at a later time in a normal context.
- *
+ * eeh_event_handler - dispatch EEH events.
* @dummy - unused
+ *
+ * The detection of a frozen slot can occur inside an interrupt,
+ * where it can be hard to do anything about it. The goal of this
+ * routine is to pull these detection events out of the context
+ * of the interrupt handler, and re-dispatch them for processing
+ * at a later time in a normal context.
*/
static int eeh_event_handler(void * dummy)
{
@@ -64,23 +70,24 @@ static int eeh_event_handler(void * dummy)
event = list_entry(eeh_eventlist.next, struct eeh_event, list);
list_del(&event->list);
}
-
- if (event)
- eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
-
spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+
if (event == NULL)
break;
+ /* Serialize processing of EEH events */
+ mutex_lock(&eeh_event_mutex);
+ eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+
printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
pci_name(event->dev));
handle_eeh_events(event);
eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-
pci_dev_put(event->dev);
kfree(event);
+ mutex_unlock(&eeh_event_mutex);
}
return 0;
@@ -88,7 +95,6 @@ static int eeh_event_handler(void * dummy)
/**
* eeh_thread_launcher
- *
* @dummy - unused
*/
static void eeh_thread_launcher(void *dummy)
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index db7c19fe9297..c9ff547f9d25 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -127,3 +127,103 @@ _GLOBAL(plpar_hcall_4out)
mtcrf 0xff,r0
blr /* return r3 = status */
+
+/* plpar_hcall_7arg_7ret(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long arg5, R8
+ unsigned long arg6, R9
+ unsigned long arg7, R10
+ unsigned long *out1, 112(R1)
+ unsigned long *out2, 110(R1)
+ unsigned long *out3, 108(R1)
+ unsigned long *out4, 106(R1)
+ unsigned long *out5, 104(R1)
+ unsigned long *out6, 102(R1)
+ unsigned long *out7); 100(R1)
+*/
+_GLOBAL(plpar_hcall_7arg_7ret)
+ HMT_MEDIUM
+
+ mfcr r0
+ stw r0,8(r1)
+
+ HVSC /* invoke the hypervisor */
+
+ lwz r0,8(r1)
+
+ ld r11,STK_PARM(r11)(r1) /* Fetch r4 ret arg */
+ std r4,0(r11)
+ ld r11,STK_PARM(r12)(r1) /* Fetch r5 ret arg */
+ std r5,0(r11)
+ ld r11,STK_PARM(r13)(r1) /* Fetch r6 ret arg */
+ std r6,0(r11)
+ ld r11,STK_PARM(r14)(r1) /* Fetch r7 ret arg */
+ std r7,0(r11)
+ ld r11,STK_PARM(r15)(r1) /* Fetch r8 ret arg */
+ std r8,0(r11)
+ ld r11,STK_PARM(r16)(r1) /* Fetch r9 ret arg */
+ std r9,0(r11)
+ ld r11,STK_PARM(r17)(r1) /* Fetch r10 ret arg */
+ std r10,0(r11)
+
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
+
+/* plpar_hcall_9arg_9ret(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long arg5, R8
+ unsigned long arg6, R9
+ unsigned long arg7, R10
+ unsigned long arg8, 112(R1)
+ unsigned long arg9, 110(R1)
+ unsigned long *out1, 108(R1)
+ unsigned long *out2, 106(R1)
+ unsigned long *out3, 104(R1)
+ unsigned long *out4, 102(R1)
+ unsigned long *out5, 100(R1)
+ unsigned long *out6, 98(R1)
+ unsigned long *out7); 96(R1)
+ unsigned long *out8, 94(R1)
+ unsigned long *out9, 92(R1)
+*/
+_GLOBAL(plpar_hcall_9arg_9ret)
+ HMT_MEDIUM
+
+ mfcr r0
+ stw r0,8(r1)
+
+ ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
+ ld r12,STK_PARM(r12)(r1) /* put arg9 in R12 */
+
+ HVSC /* invoke the hypervisor */
+
+ ld r0,STK_PARM(r13)(r1) /* Fetch r4 ret arg */
+ stdx r4,r0,r0
+ ld r0,STK_PARM(r14)(r1) /* Fetch r5 ret arg */
+ stdx r5,r0,r0
+ ld r0,STK_PARM(r15)(r1) /* Fetch r6 ret arg */
+ stdx r6,r0,r0
+ ld r0,STK_PARM(r16)(r1) /* Fetch r7 ret arg */
+ stdx r7,r0,r0
+ ld r0,STK_PARM(r17)(r1) /* Fetch r8 ret arg */
+ stdx r8,r0,r0
+ ld r0,STK_PARM(r18)(r1) /* Fetch r9 ret arg */
+ stdx r9,r0,r0
+ ld r0,STK_PARM(r19)(r1) /* Fetch r10 ret arg */
+ stdx r10,r0,r0
+ ld r0,STK_PARM(r20)(r1) /* Fetch r11 ret arg */
+ stdx r11,r0,r0
+ ld r0,STK_PARM(r21)(r1) /* Fetch r12 ret arg */
+ stdx r12,r0,r0
+
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index ba6befd96636..a72a987f1d4d 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -41,7 +41,7 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
unsigned long got;
if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
- (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
+ (unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS)
return got;
return 0;
}
@@ -69,9 +69,9 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
lbuf[1]);
- if (ret == H_Success)
+ if (ret == H_SUCCESS)
return count;
- if (ret == H_Busy)
+ if (ret == H_BUSY)
return 0;
return -EIO;
}
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c
index 22bfb5c89db9..fcf4b4cbeaf3 100644
--- a/arch/powerpc/platforms/pseries/hvcserver.c
+++ b/arch/powerpc/platforms/pseries/hvcserver.c
@@ -43,21 +43,21 @@ MODULE_VERSION(HVCS_ARCH_VERSION);
static int hvcs_convert(long to_convert)
{
switch (to_convert) {
- case H_Success:
+ case H_SUCCESS:
return 0;
- case H_Parameter:
+ case H_PARAMETER:
return -EINVAL;
- case H_Hardware:
+ case H_HARDWARE:
return -EIO;
- case H_Busy:
- case H_LongBusyOrder1msec:
- case H_LongBusyOrder10msec:
- case H_LongBusyOrder100msec:
- case H_LongBusyOrder1sec:
- case H_LongBusyOrder10sec:
- case H_LongBusyOrder100sec:
+ case H_BUSY:
+ case H_LONG_BUSY_ORDER_1_MSEC:
+ case H_LONG_BUSY_ORDER_10_MSEC:
+ case H_LONG_BUSY_ORDER_100_MSEC:
+ case H_LONG_BUSY_ORDER_1_SEC:
+ case H_LONG_BUSY_ORDER_10_SEC:
+ case H_LONG_BUSY_ORDER_100_SEC:
return -EBUSY;
- case H_Function: /* fall through */
+ case H_FUNCTION: /* fall through */
default:
return -EPERM;
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 8952528d31ac..634b7d06d3cc 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(plpar_hcall);
EXPORT_SYMBOL(plpar_hcall_4out);
EXPORT_SYMBOL(plpar_hcall_norets);
EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-
+EXPORT_SYMBOL(plpar_hcall_7arg_7ret);
+EXPORT_SYMBOL(plpar_hcall_9arg_9ret);
extern void pSeries_find_serial_port(void);
@@ -72,7 +73,7 @@ static void udbg_hvsi_putc(char c)
do {
rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
- } while (rc == H_Busy);
+ } while (rc == H_BUSY);
}
static long hvsi_udbg_buf_len;
@@ -85,7 +86,7 @@ static int udbg_hvsi_getc_poll(void)
if (hvsi_udbg_buf_len == 0) {
rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
- if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+ if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
/* bad read or non-data packet */
hvsi_udbg_buf_len = 0;
} else {
@@ -139,7 +140,7 @@ static void udbg_putcLP(char c)
buf[0] = c;
do {
rc = plpar_put_term_char(vtermno, 1, buf);
- } while(rc == H_Busy);
+ } while(rc == H_BUSY);
}
/* Buffered chars getc */
@@ -158,7 +159,7 @@ static int udbg_getc_pollLP(void)
/* get some more chars. */
inbuflen = 0;
rc = plpar_get_term_char(vtermno, &inbuflen, buf);
- if (rc != H_Success)
+ if (rc != H_SUCCESS)
inbuflen = 0; /* otherwise inbuflen is garbage */
}
if (inbuflen <= 0 || inbuflen > 16) {
@@ -304,7 +305,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
hpte_r, &slot, &dummy0, &dummy1);
- if (unlikely(lpar_rc == H_PTEG_Full)) {
+ if (unlikely(lpar_rc == H_PTEG_FULL)) {
if (!(vflags & HPTE_V_BOLTED))
DBG_LOW(" full\n");
return -1;
@@ -315,7 +316,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
* will fail. However we must catch the failure in hash_page
* or we will loop forever, so return -2 in this case.
*/
- if (unlikely(lpar_rc != H_Success)) {
+ if (unlikely(lpar_rc != H_SUCCESS)) {
if (!(vflags & HPTE_V_BOLTED))
DBG_LOW(" lpar err %d\n", lpar_rc);
return -2;
@@ -346,9 +347,9 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
/* don't remove a bolted entry */
lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
(0x1UL << 4), &dummy1, &dummy2);
- if (lpar_rc == H_Success)
+ if (lpar_rc == H_SUCCESS)
return i;
- BUG_ON(lpar_rc != H_Not_Found);
+ BUG_ON(lpar_rc != H_NOT_FOUND);
slot_offset++;
slot_offset &= 0x7;
@@ -391,14 +392,14 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN);
- if (lpar_rc == H_Not_Found) {
+ if (lpar_rc == H_NOT_FOUND) {
DBG_LOW("not found !\n");
return -1;
}
DBG_LOW("ok\n");
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
return 0;
}
@@ -417,7 +418,7 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
return dword0;
}
@@ -468,7 +469,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
flags = newpp & 7;
lpar_rc = plpar_pte_protect(flags, slot, 0);
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
}
static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -484,10 +485,10 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
want_v = hpte_encode_v(va, psize);
lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN,
&dummy1, &dummy2);
- if (lpar_rc == H_Not_Found)
+ if (lpar_rc == H_NOT_FOUND)
return;
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
}
/*
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index fcc4d561a236..e0000ce769e5 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -488,7 +488,7 @@ static int __init rtas_init(void)
/* No RTAS */
if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
printk(KERN_INFO "rtasd: no event-scan on system\n");
- return 1;
+ return -ENODEV;
}
entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index b2fbf8ba8fbb..5eb55ef1c91c 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -463,7 +463,7 @@ static void pseries_dedicated_idle_sleep(void)
* very low priority. The cede enables interrupts, which
* doesn't matter here.
*/
- if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending)
+ if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
cede_processor();
out:
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index 866379b80c09..8e53e04ada8b 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(vio_find_node);
int vio_enable_interrupts(struct vio_dev *dev)
{
int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
- if (rc != H_Success)
+ if (rc != H_SUCCESS)
printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
return rc;
}
@@ -267,7 +267,7 @@ EXPORT_SYMBOL(vio_enable_interrupts);
int vio_disable_interrupts(struct vio_dev *dev)
{
int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
- if (rc != H_Success)
+ if (rc != H_SUCCESS)
printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
return rc;
}
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 4864cb32be25..2d60ea30fed6 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -168,7 +168,7 @@ static int pSeriesLP_xirr_info_get(int n_cpu)
unsigned long return_value;
lpar_rc = plpar_xirr(&return_value);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic(" bad return code xirr - rc = %lx \n", lpar_rc);
return (int)return_value;
}
@@ -179,7 +179,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value)
unsigned long val64 = value & 0xffffffff;
lpar_rc = plpar_eoi(val64);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
val64);
}
@@ -189,7 +189,7 @@ void pSeriesLP_cppr_info(int n_cpu, u8 value)
unsigned long lpar_rc;
lpar_rc = plpar_cppr(value);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic("bad return code cppr - rc = %lx\n", lpar_rc);
}
@@ -198,7 +198,7 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value)
unsigned long lpar_rc;
lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic("bad return code qirr - rc = %lx\n", lpar_rc);
}
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 61d317428610..38087bd6e3cf 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -49,6 +49,7 @@
#include "dart.h"
+extern int iommu_is_off;
extern int iommu_force_on;
/* Physical base address and size of the DART table */
@@ -329,10 +330,17 @@ void iommu_init_early_dart(void)
void __init alloc_dart_table(void)
{
- /* Only reserve DART space if machine has more than 2GB of RAM
+ /* Only reserve DART space if machine has more than 1GB of RAM
* or if requested with iommu=on on cmdline.
+ *
+ * 1GB of RAM is picked as limit because some default devices
+ * (i.e. Airport Extreme) have 30 bit address range limits.
*/
- if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+
+ if (iommu_is_off)
+ return;
+
+ if (!iommu_force_on && lmb_end_of_DRAM() <= 0x40000000ull)
return;
/* 512 pages (2MB) is max DART tablesize. */
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index d4077e69086f..80c84d562fa4 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -3,7 +3,7 @@
#
CFLAGS_kbd.o := -Idrivers/char
-CFLAGS_vreset.o := -I$(srctree)/arch/ppc/boot/include
+CFLAGS_vreset.o := -Iarch/ppc/boot/include
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 77e4dc780f8c..cc7c4aea9397 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -134,6 +134,7 @@ main(void)
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5891ecbdc703..1adc9145516f 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -128,29 +128,26 @@ transfer_to_handler:
stw r12,4(r11)
#endif
b 3f
+
2: /* if from kernel, check interrupted DOZE/NAP mode and
* check for stack overflow
*/
+ lwz r9,THREAD_INFO-THREAD(r12)
+ cmplw r1,r9 /* if r1 <= current->thread_info */
+ ble- stack_ovf /* then the kernel stack overflowed */
+5:
#ifdef CONFIG_6xx
- mfspr r11,SPRN_HID0
- mtcr r11
-BEGIN_FTR_SECTION
- bt- 8,4f /* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
- bt- 9,4f /* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+ tophys(r9,r9) /* check local flags */
+ lwz r12,TI_LOCAL_FLAGS(r9)
+ mtcrf 0x01,r12
+ bt- 31-TLF_NAPPING,4f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
- lwz r11,THREAD_INFO-THREAD(r12)
- cmplw r1,r11 /* if r1 <= current->thread_info */
- ble- stack_ovf /* then the kernel stack overflowed */
3:
mflr r9
lwz r11,0(r9) /* virtual address of handler */
lwz r9,4(r9) /* where to go when done */
- FIX_SRR1(r10,r12)
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r10
mtlr r9
@@ -158,7 +155,9 @@ transfer_to_handler_cont:
RFI /* jump to handler, enable MMU */
#ifdef CONFIG_6xx
-4: b power_save_6xx_restore
+4: rlwinm r12,r12,0,~_TLF_NAPPING
+ stw r12,TI_LOCAL_FLAGS(r9)
+ b power_save_6xx_restore
#endif
/*
@@ -167,10 +166,10 @@ transfer_to_handler_cont:
*/
stack_ovf:
/* sometimes we use a statically-allocated stack, which is OK. */
- lis r11,_end@h
- ori r11,r11,_end@l
- cmplw r1,r11
- ble 3b /* r1 <= &_end is OK */
+ lis r12,_end@h
+ ori r12,r12,_end@l
+ cmplw r1,r12
+ ble 5b /* r1 <= &_end is OK */
SAVE_NVGPRS(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
lis r1,init_thread_union@ha
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 865ba74991a9..b250b1b539b6 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -94,6 +94,7 @@ EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(__div64_32);
EXPORT_SYMBOL(csum_partial);
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 60c724e11584..7662c4e6e7d6 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -156,12 +156,13 @@ void platform_notify_map(const struct platform_notify_dev_map *map,
while (map->bus_id != NULL) {
idx = -1;
s = strrchr(dev->bus_id, '.');
- if (s != NULL)
+ if (s != NULL) {
idx = (int)simple_strtol(s + 1, NULL, 10);
- else
+ len = s - dev->bus_id;
+ } else {
s = dev->bus_id;
-
- len = s - dev->bus_id;
+ len = strlen(dev->bus_id);
+ }
if (!strncmp(dev->bus_id, map->bus_id, len)) {
pdev = container_of(dev, struct platform_device, dev);
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 6c6b197898d0..7bb16fb97d4f 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -67,7 +67,6 @@ cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
endif
CFLAGS += -mbackchain -msoft-float $(cflags-y)
-CFLAGS += $(call cc-option,-finline-limit=10000)
CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
AFLAGS += $(aflags-y)
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 54d35c130907..9a22434a580c 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -652,7 +652,7 @@ appldata_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata appldata_nb = {
+static struct notifier_block appldata_nb = {
.notifier_call = appldata_cpu_notify,
};
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f8d0cd540a06..f4dfc10026d2 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb 8 10:44:39 2006
+# Linux kernel version: 2.6.17-rc1
+# Mon Apr 3 14:34:15 2006
#
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_S390=y
@@ -30,8 +31,8 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
@@ -45,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -60,7 +57,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -69,7 +65,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
-# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -91,17 +87,20 @@ CONFIG_DEFAULT_IOSCHED="deadline"
#
# Processor type and features
#
-# CONFIG_64BIT is not set
+CONFIG_64BIT=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
-CONFIG_MATHEMU=y
+CONFIG_DEFAULT_MIGRATION_COST=1000000
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_BINFMT_ELF32=y
#
# Code generation options
#
-CONFIG_MARCH_G5=y
-# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_G5 is not set
+CONFIG_MARCH_Z900=y
# CONFIG_MARCH_Z990 is not set
CONFIG_PACK_STACK=y
# CONFIG_SMALL_STACK is not set
@@ -143,7 +142,7 @@ CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_APPLDATA_BASE is not set
CONFIG_NO_IDLE_HZ=y
CONFIG_NO_IDLE_HZ_INIT=y
-# CONFIG_KEXEC is not set
+CONFIG_KEXEC=y
#
# Networking
@@ -173,6 +172,7 @@ CONFIG_IP_FIB_HASH=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -180,9 +180,11 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -276,6 +278,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
@@ -340,8 +347,7 @@ CONFIG_DASD_PROFILE=y
CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
CONFIG_DASD_DIAG=y
-CONFIG_DASD_EER=m
-# CONFIG_DASD_CMB is not set
+CONFIG_DASD_EER=y
# CONFIG_ATA_OVER_ETH is not set
#
@@ -354,6 +360,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
@@ -404,6 +411,7 @@ CONFIG_S390_TAPE_BLOCK=y
# S/390 tape hardware support
#
CONFIG_S390_TAPE_34XX=m
+# CONFIG_S390_TAPE_3590 is not set
# CONFIG_VMLOGRDR is not set
# CONFIG_VMCP is not set
# CONFIG_MONREADER is not set
@@ -529,7 +537,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -619,14 +626,15 @@ CONFIG_LOG_BUF_SHIFT=17
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_PREEMPT=y
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 5291b5f8788d..b4c815d8ef75 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -430,7 +430,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(sp))
+ if (! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 199da68bd7be..ef5b9c44b86b 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1608,3 +1608,45 @@ compat_sys_ppoll_wrapper:
sys_unshare_wrapper:
llgfr %r2,%r2 # unsigned long
jg sys_unshare
+
+ .globl compat_sys_set_robust_list_wrapper
+compat_sys_set_robust_list_wrapper:
+ llgtr %r2,%r2 # struct compat_robust_list_head *
+ llgfr %r3,%r3 # size_t
+ jg compat_sys_set_robust_list
+
+ .globl compat_sys_get_robust_list_wrapper
+compat_sys_get_robust_list_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # compat_uptr_t_t *
+ llgtr %r4,%r4 # compat_size_t *
+ jg compat_sys_get_robust_list
+
+ .globl sys_splice_wrapper
+sys_splice_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # loff_t *
+ lgfr %r4,%r4 # int
+ llgtr %r5,%r5 # loff_t *
+ llgfr %r6,%r6 # size_t
+ llgf %r0,164(%r15) # unsigned int
+ stg %r0,160(%r15)
+ jg sys_splice
+
+ .globl sys_sync_file_range_wrapper
+sys_sync_file_range_wrapper:
+ lgfr %r2,%r2 # int
+ sllg %r3,%r3,32 # get high word of 64bit loff_t
+ or %r3,%r4 # get low word of 64bit loff_t
+ sllg %r4,%r5,32 # get high word of 64bit loff_t
+ or %r4,%r6 # get low word of 64bit loff_t
+ llgf %r5,164(%r15) # unsigned int
+ jg sys_sync_file_range
+
+ .globl sys_tee_wrapper
+sys_tee_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ llgfr %r4,%r4 # size_t
+ llgfr %r5,%r5 # unsigned int
+ jg sys_tee
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 2f56654da821..fc2c0767202b 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -312,3 +312,8 @@ SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper) /* 300 */
SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper)
+SYSCALL(sys_set_robust_list,sys_set_robust_list,compat_sys_set_robust_list_wrapper)
+SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list_wrapper)
+SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
+SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
+SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 9289face3027..9f34bb54c051 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -58,9 +58,11 @@ SECTIONS
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }
- . = ALIGN(32);
+ . = ALIGN(256);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ . = ALIGN(256);
+ .data.read_mostly : { *(.data.read_mostly) }
_edata = .; /* End of data section */
. = ALIGN(8192); /* init_task */
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index a9566bcab682..9b11e3e20903 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -192,6 +192,7 @@ query_segment_type (struct dcss_segment *seg)
diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc);
if (diag_cc > 1) {
+ PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc);
rc = dcss_diag_translate_rc (vmrc);
goto out_free;
}
@@ -553,7 +554,7 @@ segment_save(char *name)
int endpfn = 0;
char cmd1[160];
char cmd2[80];
- int i;
+ int i, response;
if (!MACHINE_IS_VM)
return;
@@ -576,8 +577,20 @@ segment_save(char *name)
segtype_string[seg->range[i].start & 0xff]);
}
sprintf(cmd2, "SAVESEG %s", name);
- cpcmd(cmd1, NULL, 0, NULL);
- cpcmd(cmd2, NULL, 0, NULL);
+ response = 0;
+ cpcmd(cmd1, NULL, 0, &response);
+ if (response) {
+ PRINT_ERR("segment_save: DEFSEG failed with response code %i\n",
+ response);
+ goto out;
+ }
+ cpcmd(cmd2, NULL, 0, &response);
+ if (response) {
+ PRINT_ERR("segment_save: SAVESEG failed with response code %i\n",
+ response);
+ goto out;
+ }
+out:
spin_unlock(&dcss_lock);
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 58583f459471..2bcecf422573 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -527,6 +527,11 @@ config CPU_HAS_SR_RB
See <file:Documentation/sh/register-banks.txt> for further
information on SR.RB and register banking in the kernel in general.
+config NODES_SHIFT
+ int
+ default "1"
+ depends on NEED_MULTIPLE_NODES
+
endmenu
menu "Boot options"
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 1cf94a618be3..d5d032533a8b 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -37,7 +37,6 @@ EXPORT_SYMBOL(disable_irq_nosync);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(no_irq_type);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strnlen);
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index de29c45f23a7..6f3a1c946339 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -41,7 +41,6 @@ EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
#ifdef CONFIG_VT
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 2be812115197..a93f5da6855d 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -244,7 +244,7 @@ int setup_profiling_timer(unsigned int multiplier)
return -EINVAL;
spin_lock_irqsave(&prof_setup_lock, flags);
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
load_profile_irq(i, lvl14_resolution / multiplier);
prof_multiplier(i) = multiplier;
}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 2c21d7907635..ec1c9687d679 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -263,7 +263,6 @@ EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(page_kernel);
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 768de64b371f..db8faa75f94d 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -64,18 +64,18 @@ sys_call_table:
/*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex
/*220*/ .long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
/*225*/ .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
-/*230*/ .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/ .long sys_select, sys_time, sys_splice, sys_stime, sys_statfs64
/* "We are the Knights of the Forest of Ni!!" */
/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
/*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/ .long sys_nis_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*280*/ .long sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
diff --git a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile
index f84a9a6162be..8136987977f4 100644
--- a/arch/sparc/math-emu/Makefile
+++ b/arch/sparc/math-emu/Makefile
@@ -5,4 +5,4 @@
obj-y := math.o
EXTRA_AFLAGS := -ansi
-EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w
+EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index d1e2fc566486..43a66f5407f4 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -187,13 +187,16 @@ config HUGETLB_PAGE_SIZE_512K
bool "512K"
config HUGETLB_PAGE_SIZE_64K
- depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64K
+ depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64KB
bool "64K"
endchoice
endmenu
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
config ARCH_SPARSEMEM_ENABLE
def_bool y
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 900fb0b940d8..1317380fa937 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16
-# Sun Mar 26 14:58:11 2006
+# Sun Apr 2 19:31:04 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -180,6 +180,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -203,6 +204,7 @@ CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
# CONFIG_NETFILTER is not set
@@ -308,7 +310,6 @@ CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_UB=m
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -449,6 +450,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
@@ -741,9 +743,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -826,6 +826,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -837,7 +838,6 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_DEBUG is not set
@@ -923,6 +923,7 @@ CONFIG_SND_MTPAV=m
# PCI devices
#
# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
CONFIG_SND_ALI5451=m
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -954,6 +955,7 @@ CONFIG_SND_ALI5451=m
# 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
@@ -1108,6 +1110,11 @@ CONFIG_USB_HIDDEV=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
@@ -1117,6 +1124,11 @@ CONFIG_USB_HIDDEV=y
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# Misc Linux/SPARC drivers
#
CONFIG_SUN_OPENPROMIO=m
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index ffc7309e9f22..2e1c824c1cc9 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -63,7 +63,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
flushi(p->addr);
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -71,7 +71,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -79,7 +79,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -87,7 +87,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
regs->tstate |= TSTATE_PIL;
@@ -273,7 +273,7 @@ static void __kprobes resume_execution(struct kprobe *p,
kcb->kprobe_orig_tstate_pil);
}
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -300,7 +300,7 @@ out:
return 1;
}
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index dfccff29e182..f97ddeb105ac 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -419,6 +419,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
region->start = res->start - zero_res.start;
region->end = res->end - zero_res.start;
}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
struct pci_bus_region *region)
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 9372d4f376d5..9e94db2573a2 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -1092,7 +1092,7 @@ void sun4v_pci_init(int node, char *model_name)
}
}
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
unsigned long page = get_zeroed_page(GFP_ATOMIC);
if (!page)
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index eb93e9c52846..49e6dedd027d 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -244,6 +244,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
}
switch(request) {
+ case PTRACE_PEEKUSR:
+ if (addr != 0)
+ pt_error_return(regs, EIO);
+ else
+ pt_succ_return(regs, 0);
+ goto out_tsk;
+
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp64;
@@ -602,6 +609,22 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* PTRACE_DUMPCORE unsupported... */
+ case PTRACE_GETEVENTMSG: {
+ int err;
+
+ if (test_thread_flag(TIF_32BIT))
+ err = put_user(child->ptrace_message,
+ (unsigned int __user *) data);
+ else
+ err = put_user(child->ptrace_message,
+ (unsigned long __user *) data);
+ if (err)
+ pt_error_return(regs, -err);
+ else
+ pt_succ_return(regs, 0);
+ break;
+ }
+
default: {
int err = ptrace_request(child, request, addr, data);
if (err)
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 7d0e67c1ce50..005167f82419 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -535,7 +535,7 @@ static int __init topology_init(void)
while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
ncpus_probed++;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p) {
register_cpu(p, i, NULL);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 7dc28a484268..90eaca3ec9a6 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -745,12 +745,21 @@ struct call_data_struct {
int wait;
};
-static DEFINE_SPINLOCK(call_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
static struct call_data_struct *call_data;
extern unsigned long xcall_call_function;
-/*
+/**
+ * smp_call_function(): Run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: currently unused.
+ * @wait: If true, wait (atomically) until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
@@ -759,7 +768,6 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
{
struct call_data_struct data;
int cpus;
- long timeout;
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
@@ -777,31 +785,18 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
goto out_unlock;
call_data = &data;
+ mb();
smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
- /*
- * Wait for other cpus to complete function or at
- * least snap the call data.
- */
- timeout = 1000000;
- while (atomic_read(&data.finished) != cpus) {
- if (--timeout <= 0)
- goto out_timeout;
- barrier();
- udelay(1);
- }
+ /* Wait for response */
+ while (atomic_read(&data.finished) != cpus)
+ cpu_relax();
out_unlock:
spin_unlock(&call_lock);
return 0;
-
-out_timeout:
- spin_unlock(&call_lock);
- printk("XCALL: Remote cpus not responding, ncpus=%d finished=%d\n",
- cpus, atomic_read(&data.finished));
- return 0;
}
int smp_call_function(void (*func)(void *info), void *info,
@@ -830,9 +825,16 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
static void tsb_sync(void *info)
{
+ struct trap_per_cpu *tp = &trap_block[raw_smp_processor_id()];
struct mm_struct *mm = info;
- if (current->active_mm == mm)
+ /* It is not valid to test "currrent->active_mm == mm" here.
+ *
+ * The value of "current" is not changed atomically with
+ * switch_mm(). But that's OK, we just need to check the
+ * current cpu's trap block PGD physical address.
+ */
+ if (tp->pgd_paddr == __pa(mm->pgd))
tsb_context_switch(mm);
}
@@ -1278,7 +1280,7 @@ int setup_profiling_timer(unsigned int multiplier)
return -EINVAL;
spin_lock_irqsave(&prof_setup_lock, flags);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
prof_multiplier(i) = multiplier;
current_tick_offset = (timer_tick_offset / multiplier);
spin_unlock_irqrestore(&prof_setup_lock, flags);
@@ -1306,12 +1308,12 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (tlb_type == hypervisor) {
int j;
/* XXX get this mapping from machine description */
- for_each_cpu(j) {
+ for_each_possible_cpu(j) {
if ((j >> 2) == (i >> 2))
cpu_set(j, cpu_sibling_map[i]);
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index f5e8db1de76b..62d8a99271ea 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -276,7 +276,6 @@ EXPORT_SYMBOL(__prom_getsibling);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(__strlen_user);
EXPORT_SYMBOL(__strnlen_user);
-EXPORT_SYMBOL(strpbrk);
#ifdef CONFIG_SOLARIS_EMUL_MODULE
EXPORT_SYMBOL(linux_sparc_syscall);
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index c4a1cef4b1e5..f9b75760163c 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -136,6 +136,9 @@ SIGN1(sys32_getpeername, sys_getpeername, %o0)
SIGN1(sys32_getsockname, sys_getsockname, %o0)
SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
+SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
+SIGN2(sys32_tee, sys_tee, %o0, %o1)
.globl sys32_mmap2
sys32_mmap2:
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 2e906bad56fa..31030bf00f1a 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1069,3 +1069,11 @@ long sys32_lookup_dcookie(unsigned long cookie_high,
return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
buf, len);
}
+
+long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
+{
+ return sys_sync_file_range(fd,
+ (off_high << 32) | off_low,
+ (nb_high << 32) | nb_low,
+ flags);
+}
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 3b250f2318fd..62672cd92eca 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -66,17 +66,17 @@ sys_call_table32:
.word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex
/*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
-/*230*/ .word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64
+/*230*/ .word sys32_select, compat_sys_time, sys32_splice, compat_sys_stime, compat_sys_statfs64
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
- .word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+ .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
@@ -135,17 +135,17 @@ sys_call_table:
.word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex
/*220*/ .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
-/*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/ .word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64
.word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
/*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
- .word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+ .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index ff090bb9734b..2793a5d82380 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1130,9 +1130,9 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
afsr, afar,
(afsr & CHAFSR_TL1) ? 1 : 0);
- printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
+ printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
- regs->tpc, regs->tnpc, regs->tstate);
+ regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate);
printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
(afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 0db2f7d9fab5..6e002aacb961 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -327,8 +327,12 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
insn = get_fault_insn(regs, 0);
if (!insn)
goto continue_fault;
+ /* All loads, stores and atomics have bits 30 and 31 both set
+ * in the instruction. Bit 21 is set in all stores, but we
+ * have to avoid prefetches which also have bit 21 set.
+ */
if ((insn & 0xc0200000) == 0xc0200000 &&
- (insn & 0x1780000) != 0x1680000) {
+ (insn & 0x01780000) != 0x01680000) {
/* Don't bother updating thread struct value,
* because update_mmu_cache only cares which tlb
* the access came from.
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 074620d413d4..fbbbebbad8a4 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -198,6 +198,13 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
pmd_t *pmd;
pte_t *pte = NULL;
+ /* We must align the address, because our caller will run
+ * set_huge_pte_at() on whatever we return, which writes out
+ * all of the sub-ptes for the hugepage range. So we have
+ * to give it the first such sub-pte.
+ */
+ addr &= HPAGE_MASK;
+
pgd = pgd_offset(mm, addr);
pud = pud_alloc(mm, pgd, addr);
if (pud) {
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 24790bed2054..a508e7a02891 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -159,6 +159,7 @@ archclean:
$(SYMLINK_HEADERS):
@echo ' SYMLINK $@'
ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
else
$(Q)cd $(TOPDIR)/$(dir $@) ; \
@@ -168,7 +169,7 @@ endif
include/asm-um/arch:
@echo ' SYMLINK $@'
ifneq ($(KBUILD_SRC),)
- $(Q)mkdir -p include/asm-um
+ $(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(SUBARCH) include/asm-um/arch
else
$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index 04e3958266e0..dc36b222100b 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -46,7 +46,7 @@ extern int file_reader(__u64 offset, char *buf, int len, void *arg);
extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
void *arg, __u32 *version_out,
char **backing_file_out, time_t *mtime_out,
- __u64 *size_out, int *sectorsize_out,
+ unsigned long long *size_out, int *sectorsize_out,
__u32 *align_out, int *bitmap_offset_out);
extern int write_cow_header(char *cow_file, int fd, char *backing_file,
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 94de4ead4f7a..7a5b4afde692 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -28,7 +28,7 @@ static inline int cow_seek_file(int fd, __u64 offset)
return(os_seek_file(fd, offset));
}
-static inline int cow_file_size(char *file, __u64 *size_out)
+static inline int cow_file_size(char *file, unsigned long long *size_out)
{
return(os_file_size(file, size_out));
}
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 61951b721268..6ab852bfcd3a 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -17,30 +17,34 @@
#define PATH_LEN_V1 256
+typedef __u32 time32_t;
+
struct cow_header_v1 {
- int magic;
- int version;
+ __s32 magic;
+ __s32 version;
char backing_file[PATH_LEN_V1];
- time_t mtime;
+ time32_t mtime;
__u64 size;
- int sectorsize;
-};
+ __s32 sectorsize;
+} __attribute__((packed));
-#define PATH_LEN_V2 MAXPATHLEN
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+ * case other systems have different values for MAXPATHLEN.
+ *
+ * The same must hold for V2 - we want file format compatibility, not anything
+ * else.
+ */
+#define PATH_LEN_V3 4096
+#define PATH_LEN_V2 PATH_LEN_V3
struct cow_header_v2 {
__u32 magic;
__u32 version;
char backing_file[PATH_LEN_V2];
- time_t mtime;
+ time32_t mtime;
__u64 size;
- int sectorsize;
-};
-
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
- * case other systems have different values for MAXPATHLEN
- */
-#define PATH_LEN_V3 4096
+ __s32 sectorsize;
+} __attribute__((packed));
/* Changes from V2 -
* PATH_LEN_V3 as described above
@@ -66,6 +70,15 @@ struct cow_header_v2 {
* Fixed (finally!) the rounding bug
*/
+/* Until Dec2005, __attribute__((packed)) was left out from the below
+ * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to
+ * align size to 8-byte alignment. This shifted all fields above (no padding
+ * was present on 32-bit, no other padding was added).
+ *
+ * However, this _can be detected_: it means that cow_format (always 0 until
+ * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise
+ * impossible to find 4 zeros. -bb */
+
struct cow_header_v3 {
__u32 magic;
__u32 version;
@@ -75,7 +88,19 @@ struct cow_header_v3 {
__u32 alignment;
__u32 cow_format;
char backing_file[PATH_LEN_V3];
-};
+} __attribute__((packed));
+
+/* This is the broken layout used by some 64-bit binaries. */
+struct cow_header_v3_broken {
+ __u32 magic;
+ __u32 version;
+ __s64 mtime;
+ __u64 size;
+ __u32 sectorsize;
+ __u32 alignment;
+ __u32 cow_format;
+ char backing_file[PATH_LEN_V3];
+} __attribute__((packed));
/* COW format definitions - for now, we have only the usual COW bitmap */
#define COW_BITMAP 0
@@ -84,6 +109,7 @@ union cow_header {
struct cow_header_v1 v1;
struct cow_header_v2 v2;
struct cow_header_v3 v3;
+ struct cow_header_v3_broken v3_b;
};
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
@@ -184,8 +210,9 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
err = -EINVAL;
if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+ /* Below, %zd is for a size_t value */
cow_printf("Backing file name \"%s\" is too long - names are "
- "limited to %d characters\n", backing_file,
+ "limited to %zd characters\n", backing_file,
sizeof(header->backing_file) - 1);
goto out_free;
}
@@ -300,7 +327,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
*align_out = *sectorsize_out;
file = header->v2.backing_file;
}
- else if(version == 3){
+ /* This is very subtle - see above at union cow_header definition */
+ else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){
if(n < sizeof(header->v3)){
cow_printf("read_cow_header - failed to read V3 "
"header\n");
@@ -310,9 +338,43 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
*size_out = ntohll(header->v3.size);
*sectorsize_out = ntohl(header->v3.sectorsize);
*align_out = ntohl(header->v3.alignment);
+ if (*align_out == 0) {
+ cow_printf("read_cow_header - invalid COW header, "
+ "align == 0\n");
+ }
*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
file = header->v3.backing_file;
}
+ else if(version == 3){
+ cow_printf("read_cow_header - broken V3 file with"
+ " 64-bit layout - recovering content.\n");
+
+ if(n < sizeof(header->v3_b)){
+ cow_printf("read_cow_header - failed to read V3 "
+ "header\n");
+ goto out;
+ }
+
+ /* this was used until Dec2005 - 64bits are needed to represent
+ * 2038+. I.e. we can safely do this truncating cast.
+ *
+ * Additionally, we must use ntohl() instead of ntohll(), since
+ * the program used to use the former (tested - I got mtime
+ * mismatch "0 vs whatever").
+ *
+ * Ever heard about bug-to-bug-compatibility ? ;-) */
+ *mtime_out = (time32_t) ntohl(header->v3_b.mtime);
+
+ *size_out = ntohll(header->v3_b.size);
+ *sectorsize_out = ntohl(header->v3_b.sectorsize);
+ *align_out = ntohl(header->v3_b.alignment);
+ if (*align_out == 0) {
+ cow_printf("read_cow_header - invalid COW header, "
+ "align == 0\n");
+ }
+ *bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out);
+ file = header->v3_b.backing_file;
+ }
else {
cow_printf("read_cow_header - invalid COW version\n");
goto out;
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 28e3760e8b98..6d7173fc55a3 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -62,7 +62,7 @@ static void mc_work_proc(void *unused)
unsigned long flags;
while(!list_empty(&mc_requests)){
- local_save_flags(flags);
+ local_irq_save(flags);
req = list_entry(mc_requests.next, struct mconsole_entry,
list);
list_del(&req->list);
@@ -87,7 +87,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
if(req.cmd->context == MCONSOLE_INTR)
(*req.cmd->handler)(&req);
else {
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_NOWAIT);
if(new == NULL)
mconsole_reply(&req, "Out of memory", 1, 0);
else {
@@ -415,7 +415,6 @@ static int mem_config(char *str)
unplugged = page_address(page);
if(unplug_index == UNPLUGGED_PER_PAGE){
- INIT_LIST_HEAD(&unplugged->list);
list_add(&unplugged->list, &unplugged_pages);
unplug_index = 0;
}
@@ -616,7 +615,7 @@ static void console_write(struct console *console, const char *string,
return;
while(1){
- n = min((size_t)len, ARRAY_SIZE(console_buf) - console_index);
+ n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index);
strncpy(&console_buf[console_index], string, n);
console_index += n;
string += n;
@@ -655,7 +654,6 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
struct mconsole_entry entry;
unsigned long flags;
- INIT_LIST_HEAD(&entry.list);
entry.request = *req;
list_add(&entry.list, &clients);
spin_lock_irqsave(&console_lock, flags);
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 0e2f06187ea7..0a7786e00cfb 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -182,7 +182,9 @@ static int change_tramp(char **argv, char *output, int output_len)
pe_data.stdout = fds[1];
pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
- read_output(fds[0], output, output_len);
+ if (pid > 0) /* Avoid hang as we won't get data in failure case. */
+ read_output(fds[0], output, output_len);
+
os_close_file(fds[0]);
os_close_file(fds[1]);
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index b94c66114bc8..33c5f6e625e8 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -104,7 +104,7 @@ static void slirp_close(int fd, void *data)
}
if(err == 0) {
- printk("slirp_close: process %d has not exited\n");
+ printk("slirp_close: process %d has not exited\n", pri->pid);
return;
}
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 42557130a408..efa3d33c0be6 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -117,10 +117,6 @@ extern struct task_struct *get_task(int pid, int require);
extern void machine_halt(void);
extern int is_syscall(unsigned long addr);
-extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
-
-extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
-
extern void free_irq(unsigned int, void *);
extern int cpu(void);
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 018b3819ab0b..8e7053013f7b 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -4,11 +4,11 @@
#include <setjmp.h>
#include "os.h"
-#define UML_SIGLONGJMP(buf, val) do { \
+#define UML_LONGJMP(buf, val) do { \
longjmp(*buf, val); \
} while(0)
-#define UML_SIGSETJMP(buf, enable) ({ \
+#define UML_SETJMP(buf, enable) ({ \
int n; \
enable = get_signals(); \
n = setjmp(*buf); \
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h
index 82f96c574144..2c13de321f2f 100644
--- a/arch/um/include/sysdep-i386/kernel-offsets.h
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,6 +1,7 @@
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/elf.h>
+#include <asm/mman.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -16,6 +17,7 @@
void foo(void)
{
OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
#ifdef CONFIG_MODE_TT
OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
#endif
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index 5ce93abd0b54..939cc475757a 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -4,6 +4,7 @@
#include <linux/time.h>
#include <linux/elf.h>
#include <asm/page.h>
+#include <asm/mman.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -18,6 +19,7 @@
void foo(void)
{
+ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
#ifdef CONFIG_MODE_TT
OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
#endif
diff --git a/arch/um/include/tt/tt.h b/arch/um/include/tt/tt.h
index 808521980186..acb8356e1f98 100644
--- a/arch/um/include/tt/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -19,7 +19,8 @@ extern int fork_tramp(void *sig_stack);
extern int do_proc_op(void *t, int proc_id);
extern int tracer(int (*init_proc)(void *), void *sp);
extern void attach_process(int pid);
-extern void tracer_panic(char *format, ...);
+extern void tracer_panic(char *format, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern void set_init_pid(int pid);
extern int set_user_mode(void *task);
extern void set_tracing(void *t, int tracing);
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 91b0ac4ad88c..39f8c8801076 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -6,8 +6,10 @@
#ifndef __USER_H__
#define __USER_H__
-extern void panic(const char *fmt, ...);
-extern int printk(const char *fmt, ...);
+extern void panic(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+extern int printk(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern void schedule(void);
extern void *um_kmalloc(int size);
extern void *um_kmalloc_atomic(int size);
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index fe0c29b5144d..802d7842514d 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -55,7 +55,8 @@ extern int get_pty(void);
extern void *um_kmalloc(int size);
extern int switcheroo(int fd, int prot, void *from, void *to, int size);
extern void do_exec(int old_pid, int new_pid);
-extern void tracer_panic(char *msg, ...);
+extern void tracer_panic(char *msg, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern int detach(int pid, int sig);
extern int attach(int pid);
extern void kill_child_dead(int pid);
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7713e7a6f476..432cf0b97a13 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(um_virt_to_phys);
EXPORT_SYMBOL(mode_tt);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
-EXPORT_SYMBOL(end_iomem);
#ifdef CONFIG_MODE_TT
EXPORT_SYMBOL(strncpy_from_user_tt);
@@ -89,12 +88,10 @@ EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(do_gettimeofday);
EXPORT_SYMBOL(do_settimeofday);
-/* This is here because UML expands open to sys_open, not to a system
+/* This is here because UML expands lseek to sys_lseek, not to a system
* call instruction.
*/
-EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_wait4);
#ifdef CONFIG_SMP
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 901b85e8a1c6..8f49507e64ef 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -40,7 +40,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
int fd)
{
struct addr_change change;
- void *output;
+ char *output;
int n;
change.what = op;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6490a4ff40ac..6987d1d247a2 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -43,7 +43,7 @@ static int helper_child(void *arg)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
errval = errno;
- printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
+ printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
return(0);
@@ -92,15 +92,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
close(fds[1]);
fds[1] = -1;
- /*Read the errno value from the child.*/
+ /* Read the errno value from the child, if the exec failed, or get 0 if
+ * the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if(n < 0){
+ if (n < 0) {
printk("run_helper : read on pipe failed, ret = %d\n", -n);
ret = n;
kill(pid, SIGKILL);
CATCH_EINTR(waitpid(pid, NULL, 0));
- }
- else if(n != 0){
+ } else if(n != 0){
CATCH_EINTR(n = waitpid(pid, NULL, 0));
ret = -errno;
} else {
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 6ab372da9657..c6432e729241 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -8,6 +8,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <sys/statfs.h>
#include "kern_util.h"
#include "user.h"
#include "user_util.h"
@@ -19,6 +20,7 @@
#include <sys/param.h>
+static char *default_tmpdir = "/tmp";
static char *tempdir = NULL;
static void __init find_tempdir(void)
@@ -34,7 +36,7 @@ static void __init find_tempdir(void)
break;
}
if((dir == NULL) || (*dir == '\0'))
- dir = "/tmp";
+ dir = default_tmpdir;
tempdir = malloc(strlen(dir) + 2);
if(tempdir == NULL){
@@ -46,6 +48,96 @@ static void __init find_tempdir(void)
strcat(tempdir, "/");
}
+/* This will return 1, with the first character in buf being the
+ * character following the next instance of c in the file. This will
+ * read the file as needed. If there's an error, -errno is returned;
+ * if the end of the file is reached, 0 is returned.
+ */
+static int next(int fd, char *buf, int size, char c)
+{
+ int n;
+ char *ptr;
+
+ while((ptr = strchr(buf, c)) == NULL){
+ n = read(fd, buf, size - 1);
+ if(n == 0)
+ return 0;
+ else if(n < 0)
+ return -errno;
+
+ buf[n] = '\0';
+ }
+
+ ptr++;
+ memmove(buf, ptr, strlen(ptr) + 1);
+ return 1;
+}
+
+static int checked_tmpdir = 0;
+
+/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
+ * way to do this than to parse /proc/mounts. statfs will return the
+ * same filesystem magic number and fs id for both /dev and /dev/shm
+ * when they are both tmpfs, so you can't tell if they are different
+ * filesystems. Also, there seems to be no other way of finding the
+ * mount point of a filesystem from within it.
+ *
+ * If a /dev/shm tmpfs entry is found, then we switch to using it.
+ * Otherwise, we stay with the default /tmp.
+ */
+static void which_tmpdir(void)
+{
+ int fd, found;
+ char buf[128] = { '\0' };
+
+ if(checked_tmpdir)
+ return;
+
+ checked_tmpdir = 1;
+
+ printf("Checking for tmpfs mount on /dev/shm...");
+
+ fd = open("/proc/mounts", O_RDONLY);
+ if(fd < 0){
+ printf("failed to open /proc/mounts, errno = %d\n", errno);
+ return;
+ }
+
+ while(1){
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ if(found != 1)
+ break;
+
+ if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+ goto found;
+
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+ if(found != 1)
+ break;
+ }
+
+err:
+ if(found == 0)
+ printf("nothing mounted on /dev/shm\n");
+ else if(found < 0)
+ printf("read returned errno %d\n", -found);
+
+ return;
+
+found:
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ if(found != 1)
+ goto err;
+
+ if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+ printf("not tmpfs\n");
+ return;
+ }
+
+ printf("OK\n");
+ default_tmpdir = "/dev/shm";
+}
+
/*
* This proc still used in tt-mode
* (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -53,33 +145,37 @@ static void __init find_tempdir(void)
*/
int make_tempfile(const char *template, char **out_tempname, int do_unlink)
{
- char tempname[MAXPATHLEN];
+ char *tempname;
int fd;
+ which_tmpdir();
+ tempname = malloc(MAXPATHLEN);
+
find_tempdir();
- if (*template != '/')
+ if (template[0] != '/')
strcpy(tempname, tempdir);
else
- *tempname = 0;
+ tempname[0] = '\0';
strcat(tempname, template);
fd = mkstemp(tempname);
if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
- return -1;
+ goto out;
}
if(do_unlink && (unlink(tempname) < 0)){
perror("unlink");
- return -1;
+ goto out;
}
if(out_tempname){
- *out_tempname = strdup(tempname);
- if(*out_tempname == NULL){
- perror("strdup");
- return -1;
- }
+ *out_tempname = tempname;
+ } else {
+ free(tempname);
}
return(fd);
+out:
+ free(tempname);
+ return -1;
}
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -134,3 +230,26 @@ int create_mem_file(unsigned long long len)
}
return(fd);
}
+
+
+void check_tmpexec(void)
+{
+ void *addr;
+ int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+ addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+ printf("Checking PROT_EXEC mmap in %s...",tempdir);
+ fflush(stdout);
+ if(addr == MAP_FAILED){
+ err = errno;
+ perror("failed");
+ if(err == EPERM)
+ printf("%s must be not mounted noexec\n",tempdir);
+ exit(1);
+ }
+ printf("OK\n");
+ munmap(addr, UM_KERN_PAGE_SIZE);
+
+ close(fd);
+}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 8176b0b52047..3505f44f8a25 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -190,7 +190,7 @@ int os_unmap_memory(void *addr, int len)
}
#ifndef MADV_REMOVE
-#define MADV_REMOVE 0x5 /* remove these pages & resources */
+#define MADV_REMOVE KERNEL_MADV_REMOVE
#endif
int os_drop_memory(void *addr, int length)
@@ -216,7 +216,7 @@ int can_drop_memory(void)
}
addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_PRIVATE, fd, 0);
+ MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
printk("Mapping test memory file failed, err = %d\n", -errno);
return 0;
@@ -266,11 +266,11 @@ void init_new_thread_signals(int altstack)
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
- sigjmp_buf buf;
+ jmp_buf buf;
int n, enable;
*jmp_ptr = &buf;
- n = UML_SIGSETJMP(&buf, enable);
+ n = UML_SETJMP(&buf, enable);
if(n != 0)
return(n);
(*fn)(arg);
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 9ba942947146..00e9388e947a 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -304,8 +304,8 @@ out_clear_poll:
.size = 0,
.used = 0 });
out_free:
- kfree(p);
sigio_unlock();
+ kfree(p);
out_close2:
close(l_sigio_private[0]);
close(l_sigio_private[1]);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index fbb080c2fc26..b3c11cfa995a 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -82,8 +82,8 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
if (offset) {
data = (unsigned long *)(mm_idp->stack +
offset - UML_CONFIG_STUB_DATA);
- printk("do_syscall_stub : ret = %d, offset = %d, "
- "data = 0x%x\n", ret, offset, data);
+ printk("do_syscall_stub : ret = %ld, offset = %ld, "
+ "data = %p\n", ret, offset, data);
syscall = (unsigned long *)((unsigned long)data + data[0]);
printk("do_syscall_stub: syscall %ld failed, return value = "
"0x%lx, expected return value = 0x%lx\n",
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bbf34cb91ce1..0776bc18ca85 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -265,7 +265,7 @@ void userspace(union uml_pt_regs *regs)
if(err)
panic("userspace - could not resume userspace process, "
"pid=%d, ptrace operation = %d, errno = %d\n",
- op, errno);
+ pid, op, errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
if(err < 0)
@@ -369,7 +369,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
*/
wait_stub_done(pid, -1, "copy_context_skas0");
if (child_data->err != UML_CONFIG_STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %d\n",
+ panic("copy_context_skas0 - stub-child reports error %ld\n",
child_data->err);
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
@@ -434,7 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
{
unsigned long flags;
- sigjmp_buf switch_buf, fork_buf;
+ jmp_buf switch_buf, fork_buf;
int enable;
*switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
*/
flags = get_signals();
block_signals();
- if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+ if(UML_SETJMP(&fork_buf, enable) == 0)
new_thread_proc(stack, handler);
remove_sigstack();
@@ -466,35 +466,35 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void thread_wait(void *sw, void *fb)
{
- sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+ jmp_buf buf, **switch_buf = sw, *fork_buf;
int enable;
*switch_buf = &buf;
fork_buf = fb;
- if(UML_SIGSETJMP(&buf, enable) == 0)
+ if(UML_SETJMP(&buf, enable) == 0)
siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
}
void switch_threads(void *me, void *next)
{
- sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+ jmp_buf my_buf, **me_ptr = me, *next_buf = next;
int enable;
*me_ptr = &my_buf;
- if(UML_SIGSETJMP(&my_buf, enable) == 0)
- UML_SIGLONGJMP(next_buf, 1);
+ if(UML_SETJMP(&my_buf, enable) == 0)
+ UML_LONGJMP(next_buf, 1);
}
-static sigjmp_buf initial_jmpbuf;
+static jmp_buf initial_jmpbuf;
/* XXX Make these percpu */
static void (*cb_proc)(void *arg);
static void *cb_arg;
-static sigjmp_buf *cb_back;
+static jmp_buf *cb_back;
int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
{
- sigjmp_buf **switch_buf = switch_buf_ptr;
+ jmp_buf **switch_buf = switch_buf_ptr;
int n, enable;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
SIGVTALRM, -1);
*fork_buf_ptr = &initial_jmpbuf;
- n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+ n = UML_SETJMP(&initial_jmpbuf, enable);
switch(n){
case INIT_JMP_NEW_THREAD:
new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
- UML_SIGLONGJMP(cb_back, 1);
+ UML_LONGJMP(cb_back, 1);
break;
case INIT_JMP_HALT:
kmalloc_ok = 0;
@@ -523,12 +523,12 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_SIGLONGJMP(*switch_buf, 1);
+ UML_LONGJMP(*switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
- sigjmp_buf here;
+ jmp_buf here;
int enable;
cb_proc = proc;
@@ -536,8 +536,8 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
cb_back = &here;
block_signals();
- if(UML_SIGSETJMP(&here, enable) == 0)
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+ if(UML_SETJMP(&here, enable) == 0)
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
cb_proc = NULL;
@@ -548,13 +548,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
void halt_skas(void)
{
block_signals();
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
}
void reboot_skas(void)
{
block_signals();
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
}
void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 387e26af301a..503148504009 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -296,29 +296,7 @@ static void __init check_ptrace(void)
check_sysemu();
}
-extern int create_tmp_file(unsigned long long len);
-
-static void check_tmpexec(void)
-{
- void *addr;
- int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
- addr = mmap(NULL, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
- printf("Checking PROT_EXEC mmap in /tmp...");
- fflush(stdout);
- if(addr == MAP_FAILED){
- err = errno;
- perror("failed");
- if(err == EPERM)
- printf("/tmp must be not mounted noexec\n");
- exit(1);
- }
- printf("OK\n");
- munmap(addr, UM_KERN_PAGE_SIZE);
-
- close(fd);
-}
+extern void check_tmpexec(void);
void os_early_checks(void)
{
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
index ba21f0e04a2f..120abbe4e3ce 100644
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -1,3 +1,4 @@
+#include <errno.h>
#include <linux/unistd.h>
#include "sysdep/tls.h"
#include "user_util.h"
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index a9f6b26f9828..90b29ae9af46 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -35,7 +35,7 @@ void os_fill_handlinfo(struct kern_handlers h)
void do_longjmp(void *b, int val)
{
- sigjmp_buf *buf = b;
+ jmp_buf *buf = b;
- UML_SIGLONGJMP(buf, val);
+ UML_LONGJMP(buf, val);
}
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 166fb66995df..e523719330b2 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -16,9 +16,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
int enable;
- sigjmp_buf jbuf;
+ jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(UML_SIGSETJMP(&jbuf, enable) == 0){
+ if(UML_SETJMP(&jbuf, enable) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 198e59163288..34bfc1bb9e38 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -120,7 +120,8 @@ static int not_dead_yet(char *dir)
dead = 0;
fd = open(file, O_RDONLY);
- if(fd < 0){
+ if(fd < 0) {
+ fd = -errno;
if(fd != -ENOENT){
printk("not_dead_yet : couldn't open pid file '%s', "
"err = %d\n", file, -fd);
@@ -130,9 +131,13 @@ static int not_dead_yet(char *dir)
err = 0;
n = read(fd, pid, sizeof(pid));
- if(n <= 0){
+ if(n < 0){
+ printk("not_dead_yet : couldn't read pid file '%s', "
+ "err = %d\n", file, errno);
+ goto out_close;
+ } else if(n == 0){
printk("not_dead_yet : couldn't read pid file '%s', "
- "err = %d\n", file, -n);
+ "0-byte read\n", file);
goto out_close;
}
@@ -155,9 +160,9 @@ static int not_dead_yet(char *dir)
return err;
- out_close:
+out_close:
close(fd);
- out:
+out:
return 0;
}
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 8da6ab31152a..2598158e1f53 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -18,14 +18,19 @@ extern void *memmove(void *, const void *, size_t);
extern void *memset(void *, int, size_t);
extern int printf(const char *, ...);
+/* If they're not defined, the export is included in lib/string.c.*/
+#ifdef __HAVE_ARCH_STRLEN
EXPORT_SYMBOL(strlen);
+#endif
+#ifdef __HAVE_ARCH_STRSTR
+EXPORT_SYMBOL(strstr);
+#endif
+
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(printf);
-EXPORT_SYMBOL(strstr);
-
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
* However, the modules will use the CRC defined *here*, no matter if it is
* good; so the versions of these symbols will always match
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index e32065e2fdc8..c47a2a7ce70e 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -104,7 +104,7 @@ void setup_hostinfo(void)
int setjmp_wrapper(void (*proc)(void *, void *), ...)
{
va_list args;
- sigjmp_buf buf;
+ jmp_buf buf;
int n;
n = sigsetjmp(buf, 1);
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index b696b451774c..5e7a9c310aa5 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -9,10 +9,8 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) $(USER_OBJS:.o=.i) $(USER_OBJS:.o=.s) $(USER_OBJS:.o=.lst): \
c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
-$(USER_OBJS): cmd_checksrc =
-$(USER_OBJS): quiet_cmd_checksrc =
-$(USER_OBJS): cmd_force_checksrc =
-$(USER_OBJS): quiet_cmd_force_checksrc =
+$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
+ -Dunix -D__unix__ -D__$(SUBARCH)__
# The stubs and unmap.o can't try to call mcount or update basic block data
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
index db524ab3f743..2a1eac1859ce 100644
--- a/arch/um/sys-i386/ksyms.c
+++ b/arch/um/sys-i386/ksyms.c
@@ -15,7 +15,3 @@ EXPORT_SYMBOL(__up_wakeup);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial);
-
-/* delay core functions */
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__udelay);
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 9f3bd8ed78f5..40aa88531446 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -57,7 +57,7 @@ static void write_debugregs(int pid, unsigned long *regs)
if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
regs[i]) < 0)
printk("write_debugregs - ptrace failed on "
- "register %d, value = 0x%x, errno = %d\n", i,
+ "register %d, value = 0x%lx, errno = %d\n", i,
regs[i], errno);
}
}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index f5d0e1c37ea2..0709fc6670c2 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -57,7 +57,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
return(0);
}
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate __user *to_fp,
+int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
struct pt_regs *regs, unsigned long sp)
{
struct sigcontext sc;
@@ -132,7 +132,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
return(err);
}
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate __user *fp,
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
struct sigcontext *from, int fpsize, unsigned long sp)
{
struct _fpstate __user *to_fp;
@@ -147,7 +147,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate __user *fp,
* delivery. The sp passed in is the original, and this needs
* to be restored, so we stick it in separately.
*/
- err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
+ err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
if(from_fp != NULL){
err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
@@ -167,7 +167,7 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
return(ret);
}
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate __user *fp,
+static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
struct pt_regs *from, unsigned long sp)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index a37f672ec964..2355dc19c46c 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -27,6 +27,6 @@ stub_segv_handler(int sig)
* the stack in its original form when we do the sigreturn here, by
* hand.
*/
- __asm__("mov %0,%%esp ; movl %1, %%eax ; "
- "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+ __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
+ "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
}
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index a3188e861cc7..71b9796258ef 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -378,7 +378,7 @@ static int __init __setup_host_supports_tls(void) {
} else
printk(KERN_ERR " Host TLS support NOT detected! "
"TLS support inside UML will not work\n");
- return 1;
+ return 0;
}
__initcall(__setup_host_supports_tls);
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index e75c4e1838b0..a4c46a8af008 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -137,7 +137,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
* delivery. The sp passed in is the original, and this needs
* to be restored, so we stick it in separately.
*/
- err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
+ err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
if(from_fp != NULL){
err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index a27099533198..1c967026c957 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -33,7 +33,7 @@ stub_segv_handler(int sig)
struct ucontext *uc;
int pid;
- __asm__("movq %%rdx, %0" : "=g" (uc) :);
+ __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
&uc->uc_mcontext);
@@ -44,8 +44,8 @@ stub_segv_handler(int sig)
* the signal frame. So, we use the ucontext pointer, which we know
* already, to get the signal frame pointer, and add 8 to that.
*/
- __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
- "g" ((unsigned long) container_of(uc, struct rt_sigframe,
- uc) + 8),
- "g" (__NR_rt_sigreturn));
+ __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
+ "g" ((unsigned long)
+ container_of(uc, struct rt_sigframe, uc) + 8),
+ "g" (__NR_rt_sigreturn));
}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 8ffc29c1c89d..6bcfcfe88384 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -43,7 +43,6 @@ EXPORT_SYMBOL (strncmp);
EXPORT_SYMBOL (strchr);
EXPORT_SYMBOL (strlen);
EXPORT_SYMBOL (strnlen);
-EXPORT_SYMBOL (strpbrk);
EXPORT_SYMBOL (strrchr);
EXPORT_SYMBOL (strstr);
EXPORT_SYMBOL (memset);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 4310b4a311a5..408d44a59756 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -136,6 +136,11 @@ config X86_L1_CACHE_SHIFT
default "7" if GENERIC_CPU || MPSC
default "6" if MK8
+config X86_INTERNODE_CACHE_BYTES
+ int
+ default "4096" if X86_VSMP
+ default X86_L1_CACHE_BYTES if !X86_VSMP
+
config X86_TSC
bool
default y
@@ -283,6 +288,11 @@ config K8_NUMA
Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
instead, which also takes priority if both are compiled in.
+config NODES_SHIFT
+ int
+ default "6"
+ depends on NEED_MULTIPLE_NODES
+
# Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig.
config X86_64_ACPI_NUMA
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 585fd4a559c8..e573e2ab5510 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -24,37 +24,37 @@
LDFLAGS := -m elf_x86_64
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux :=
-
CHECKFLAGS += -D__x86_64__ -m64
+cflags-y :=
cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
-CFLAGS += $(cflags-y)
-CFLAGS += -m64
-CFLAGS += -mno-red-zone
-CFLAGS += -mcmodel=kernel
-CFLAGS += -pipe
+cflags-y += -m64
+cflags-y += -mno-red-zone
+cflags-y += -mcmodel=kernel
+cflags-y += -pipe
cflags-$(CONFIG_REORDER) += -ffunction-sections
# this makes reading assembly source easier, but produces worse code
# actually it makes the kernel smaller too.
-CFLAGS += -fno-reorder-blocks
-CFLAGS += -Wno-sign-compare
+cflags-y += -fno-reorder-blocks
+cflags-y += -Wno-sign-compare
ifneq ($(CONFIG_UNWIND_INFO),y)
-CFLAGS += -fno-asynchronous-unwind-tables
+cflags-y += -fno-asynchronous-unwind-tables
endif
ifneq ($(CONFIG_DEBUG_INFO),y)
# -fweb shrinks the kernel a bit, but the difference is very small
# it also messes up debugging, so don't use it for now.
-#CFLAGS += $(call cc-option,-fweb)
+#cflags-y += $(call cc-option,-fweb)
endif
# -funit-at-a-time shrinks the kernel .text considerably
# unfortunately it makes reading oopses harder.
-CFLAGS += $(call cc-option,-funit-at-a-time)
+cflags-y += $(call cc-option,-funit-at-a-time)
# prevent gcc from generating any FP code by mistake
-CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+CFLAGS += $(cflags-y)
AFLAGS += -m64
head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
index 0587477c99f2..32327bb37aff 100644
--- a/arch/x86_64/boot/video.S
+++ b/arch/x86_64/boot/video.S
@@ -97,6 +97,7 @@
#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
@@ -233,6 +234,10 @@ mopar_gr:
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
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 566ecc97ee5a..69db0c0721d1 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-git9
-# Sat Mar 25 15:18:40 2006
+# Linux kernel version: 2.6.17-rc1-git11
+# Sun Apr 16 07:22:36 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_X86=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_CMPXCHG=y
CONFIG_EARLY_PRINTK=y
@@ -55,11 +56,8 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
+CONFIG_DOUBLEFAULT=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -70,7 +68,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
@@ -81,6 +78,7 @@ CONFIG_STOP_MACHINE=y
#
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -105,6 +103,7 @@ CONFIG_X86_PC=y
CONFIG_GENERIC_CPU=y
CONFIG_X86_L1_CACHE_BYTES=128
CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
# CONFIG_MICROCODE is not set
@@ -116,12 +115,14 @@ CONFIG_X86_LOCAL_APIC=y
CONFIG_MTRR=y
CONFIG_SMP=y
CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_BKL=y
CONFIG_NUMA=y
CONFIG_K8_NUMA=y
+CONFIG_NODES_SHIFT=6
CONFIG_X86_64_ACPI_NUMA=y
CONFIG_NUMA_EMU=y
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
@@ -138,6 +139,7 @@ CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_OUT_OF_LINE_PFN_TO_PAGE=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
CONFIG_HPET_TIMER=y
@@ -289,6 +291,7 @@ CONFIG_IP_PNP_DHCP=y
# 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_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -300,6 +303,7 @@ CONFIG_IPV6=y
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -542,7 +546,6 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -704,7 +707,6 @@ CONFIG_S2IO=m
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Wan interfaces
@@ -791,7 +793,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -921,6 +923,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -932,6 +935,8 @@ CONFIG_VIDEO_SELECT=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256
CONFIG_DUMMY_CONSOLE=y
#
@@ -1041,9 +1046,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -1058,15 +1061,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1118,9 +1112,23 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
+# CONFIG_IPATH_CORE is not set
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1128,6 +1136,11 @@ CONFIG_USB_MON=y
# CONFIG_EDAC is not set
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# Firmware Drivers
#
# CONFIG_EDD is not set
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 929e6b0771f8..e9263b4975e0 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -27,5 +27,5 @@ $(obj)/vsyscall-sysenter.so $(obj)/vsyscall-syscall.so: \
$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
$(call if_changed,syscall)
-AFLAGS_vsyscall-sysenter.o = -m32
-AFLAGS_vsyscall-syscall.o = -m32
+AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
+AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 35b2faccdc6c..57fc37e0fb9c 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -15,6 +15,8 @@
#include <asm/vsyscall32.h>
#include <linux/linkage.h>
+#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
+
.macro IA32_ARG_FIXUP noebp=0
movl %edi,%r8d
.if \noebp
@@ -109,8 +111,8 @@ ENTRY(ia32_sysenter_target)
CFI_REMEMBER_STATE
jnz sysenter_tracesys
sysenter_do_call:
- cmpl $(IA32_NR_syscalls),%eax
- jae ia32_badsys
+ cmpl $(IA32_NR_syscalls-1),%eax
+ ja ia32_badsys
IA32_ARG_FIXUP 1
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -210,8 +212,8 @@ ENTRY(ia32_cstar_target)
CFI_REMEMBER_STATE
jnz cstar_tracesys
cstar_do_call:
- cmpl $IA32_NR_syscalls,%eax
- jae ia32_badsys
+ cmpl $IA32_NR_syscalls-1,%eax
+ ja ia32_badsys
IA32_ARG_FIXUP 1
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -296,8 +298,8 @@ ENTRY(ia32_syscall)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
jnz ia32_tracesys
ia32_do_syscall:
- cmpl $(IA32_NR_syscalls),%eax
- jae ia32_badsys
+ cmpl $(IA32_NR_syscalls-1),%eax
+ ja ia32_badsys
IA32_ARG_FIXUP
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
ia32_sysret:
@@ -685,12 +687,12 @@ ia32_sys_call_table:
.quad sys_readlinkat /* 305 */
.quad sys_fchmodat
.quad sys_faccessat
- .quad sys_ni_syscall /* pselect6 for now */
- .quad sys_ni_syscall /* ppoll for now */
+ .quad quiet_ni_syscall /* pselect6 for now */
+ .quad quiet_ni_syscall /* ppoll for now */
.quad sys_unshare /* 310 */
.quad compat_sys_set_robust_list
.quad compat_sys_get_robust_list
+ .quad sys_splice
+ .quad sys_sync_file_range
+ .quad sys_tee
ia32_syscall_end:
- .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
- .quad ni_syscall
- .endr
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index a098a11e7755..059c88313f4e 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
- dmi_scan.o pci-dma.o pci-nommu.o
+ pci-dma.o pci-nommu.o
obj-$(CONFIG_X86_MCE) += mce.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
@@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
-dmi_scan-y += ../../i386/kernel/dmi_scan.o
-
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index fffd6b0a2fab..70b9d21ed675 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -80,7 +80,7 @@ static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
return 0;
}
- if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
+ if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
return 0;
}
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 293cd71a266a..62776c07cff1 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -80,7 +80,12 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
return 0;
}
-int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int __meminit
+e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
{
int i;
for (i = 0; i < e820.nr_map; i++) {
@@ -94,6 +99,35 @@ int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
return 0;
}
+/*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+{
+ int i;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+ if (type && ei->type != type)
+ continue;
+ /* is the region (part) in overlap with the current region ?*/
+ if (ei->addr >= end || ei->addr + ei->size <= start)
+ continue;
+
+ /* if the region is at the beginning of <start,end> we move
+ * start to the end of the region since it's ok until there
+ */
+ if (ei->addr <= start)
+ start = ei->addr + ei->size;
+ /* if start is now at or beyond end, we're done, full coverage */
+ if (start >= end)
+ return 1; /* we're done */
+ }
+ return 0;
+}
+
/*
* Find a free area in a specific range.
*/
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 8538bfea30e6..c946e4fe67a7 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -180,6 +180,10 @@ rff_trace:
*
* XXX if we had a free scratch register we could save the RSP into the stack frame
* and report it properly in ps. Unfortunately we haven't.
+ *
+ * When user can change the frames always force IRET. That is because
+ * it deals with uncanonical addresses better. SYSRET has trouble
+ * with them due to bugs in both AMD and Intel CPUs.
*/
ENTRY(system_call)
@@ -254,7 +258,10 @@ sysret_signal:
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
1: movl $_TIF_NEED_RESCHED,%edi
- jmp sysret_check
+ /* Use IRET because user could have changed frame. This
+ works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+ cli
+ jmp int_with_check
badsys:
movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
@@ -280,7 +287,8 @@ tracesys:
call syscall_trace_leave
RESTORE_TOP_OF_STACK %rbx
RESTORE_REST
- jmp ret_from_sys_call
+ /* Use IRET because user could have changed frame */
+ jmp int_ret_from_sys_call
CFI_ENDPROC
/*
@@ -408,25 +416,9 @@ ENTRY(stub_execve)
CFI_ADJUST_CFA_OFFSET -8
CFI_REGISTER rip, r11
SAVE_REST
- movq %r11, %r15
- CFI_REGISTER rip, r15
FIXUP_TOP_OF_STACK %r11
call sys_execve
- GET_THREAD_INFO(%rcx)
- bt $TIF_IA32,threadinfo_flags(%rcx)
- CFI_REMEMBER_STATE
- jc exec_32bit
RESTORE_TOP_OF_STACK %r11
- movq %r15, %r11
- CFI_REGISTER rip, r11
- RESTORE_REST
- pushq %r11
- CFI_ADJUST_CFA_OFFSET 8
- CFI_REL_OFFSET rip, 0
- ret
-
-exec_32bit:
- CFI_RESTORE_STATE
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index accbff3fec49..1eaa5dae6174 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -53,7 +53,7 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
-static inline int is_IF_modifier(kprobe_opcode_t *insn)
+static __always_inline int is_IF_modifier(kprobe_opcode_t *insn)
{
switch (*insn) {
case 0xfa: /* cli */
@@ -84,7 +84,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
* If it does, return the address of the 32-bit displacement word.
* If not, return null.
*/
-static inline s32 *is_riprel(u8 *insn)
+static s32 __kprobes *is_riprel(u8 *insn)
{
#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \
(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
@@ -229,7 +229,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex);
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -237,7 +237,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -245,7 +245,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 10b3e348fc99..c69fc43cee7b 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -29,6 +29,8 @@
#define MISC_MCELOG_MINOR 227
#define NR_BANKS 6
+atomic_t mce_entry;
+
static int mce_dont_init;
/* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic,
@@ -172,10 +174,12 @@ void do_machine_check(struct pt_regs * regs, long error_code)
int i;
int panicm_found = 0;
+ atomic_inc(&mce_entry);
+
if (regs)
notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
if (!banks)
- return;
+ goto out2;
memset(&m, 0, sizeof(struct mce));
m.cpu = safe_smp_processor_id();
@@ -266,6 +270,8 @@ void do_machine_check(struct pt_regs * regs, long error_code)
out:
/* Last thing done in the machine check exception to clear state. */
wrmsrl(MSR_IA32_MCG_STATUS, 0);
+ out2:
+ atomic_dec(&mce_entry);
}
/*
@@ -623,7 +629,7 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
#endif
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int
+static int
mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index d3ad7d81266d..d13b241ad094 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -482,7 +482,7 @@ static void threshold_remove_device(unsigned int cpu)
#endif
/* get notified when a cpu comes on/off */
-static __cpuinit int threshold_cpu_callback(struct notifier_block *nfb,
+static int threshold_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
/* cpu was unsigned int to begin with */
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index d9e4067faf05..4e6357fe0ec3 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -34,6 +34,7 @@
#include <asm/proto.h>
#include <asm/kdebug.h>
#include <asm/local.h>
+#include <asm/mce.h>
/*
* lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -480,6 +481,12 @@ void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
__get_cpu_var(nmi_touch) = 0;
touched = 1;
}
+#ifdef CONFIG_X86_MCE
+ /* Could check oops_in_progress here too, but it's safer
+ not too */
+ if (atomic_read(&mce_entry) > 0)
+ touched = 1;
+#endif
if (!touched && __get_cpu_var(last_irq_sum) == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 03c9eeedb0f3..af035ede70cd 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -48,9 +48,11 @@ dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
{
struct page *page;
int node;
+#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
node = pcibus_to_node(to_pci_dev(dev)->bus);
else
+#endif
node = numa_node_id();
page = alloc_pages_node(node, gfp, order);
return page ? page_address(page) : NULL;
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index a6c01e121266..9d3d76c85ae7 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -112,10 +112,6 @@ static unsigned long alloc_iommu(int size)
static void free_iommu(unsigned long offset, int size)
{
unsigned long flags;
- if (size == 1) {
- clear_bit(offset, iommu_gart_bitmap);
- return;
- }
spin_lock_irqsave(&iommu_bitmap_lock, flags);
__clear_bit_string(iommu_gart_bitmap, offset, size);
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 70dd8e5c6889..fb903e65e079 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -575,8 +575,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
prev->userrsp = read_pda(oldrsp);
write_pda(oldrsp, next->userrsp);
write_pda(pcurrent, next_p);
+
/* This must be here to ensure both math_state_restore() and
- kernel_fpu_begin() work consistently. */
+ kernel_fpu_begin() work consistently.
+ And the AMD workaround requires it to be after DS reload. */
unlazy_fpu(prev_p);
write_pda(kernelstack,
task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
@@ -781,10 +783,16 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
}
case ARCH_GET_GS: {
unsigned long base;
+ unsigned gsindex;
if (task->thread.gsindex == GS_TLS_SEL)
base = read_32bit_tls(task, GS_TLS);
- else if (doit)
- rdmsrl(MSR_KERNEL_GS_BASE, base);
+ else if (doit) {
+ asm("movl %%gs,%0" : "=r" (gsindex));
+ if (gsindex)
+ rdmsrl(MSR_KERNEL_GS_BASE, base);
+ else
+ base = task->thread.gs;
+ }
else
base = task->thread.gs;
ret = put_user(base, (unsigned long __user *)addr);
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index d44b2c1e63a6..da8e7903d817 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -274,11 +274,6 @@ static int putreg(struct task_struct *child,
return -EIO;
value &= 0xffff;
break;
- case offsetof(struct user_regs_struct, rip):
- /* Check if the new RIP address is canonical */
- if (value >= TASK_SIZE_OF(child))
- return -EIO;
- break;
}
put_stack_long(child, regno - sizeof(struct pt_regs), value);
return 0;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 0856ad444f90..759070c82751 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -353,8 +353,10 @@ static __init void parse_cmdline_early (char ** cmdline_p)
if (fullarg(from, "enable_timer_pin_1"))
disable_timer_pin_1 = -1;
- if (fullarg(from, "nolapic") || fullarg(from, "disableapic"))
+ if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
disable_apic = 1;
+ }
if (fullarg(from, "noapic"))
skip_ioapic_setup = 1;
@@ -928,6 +930,10 @@ static int __init init_amd(struct cpuinfo_x86 *c)
if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+ /* Enable workaround for FXSAVE leak */
+ if (c->x86 >= 6)
+ set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
+
r = get_model_name(c);
if (!r) {
switch (c->x86) {
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index ef8bc46dc140..7392570f975d 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -726,7 +726,7 @@ static __init int late_hpet_init(void)
unsigned int ntimer;
if (!vxtime.hpet_address)
- return -1;
+ return 0;
memset(&hd, 0, sizeof (hd));
@@ -917,6 +917,8 @@ void __init time_init(void)
vxtime.hpet_address = 0;
if (hpet_use_timer) {
+ /* set tick_nsec to use the proper rate for HPET */
+ tick_nsec = TICK_NSEC_HPET;
cpu_khz = hpet_calibrate_tsc();
timename = "HPET";
#ifdef CONFIG_X86_PM_TIMER
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 6bda322d3caf..2700b1375c1f 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/moduleparam.h>
#include <linux/nmi.h>
#include <linux/kprobes.h>
+#include <linux/kexec.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -433,6 +434,8 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk(KERN_ALERT "RIP ");
printk_address(regs->rip);
printk(" RSP <%016lx>\n", regs->rsp);
+ if (kexec_should_crash(current))
+ crash_kexec(regs);
}
void die(const char * str, struct pt_regs * regs, long err)
@@ -455,6 +458,8 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs)
*/
printk(str, safe_smp_processor_id());
show_registers(regs);
+ if (kexec_should_crash(current))
+ crash_kexec(regs);
if (panic_on_timeout || panic_on_oops)
panic("nmi watchdog");
printk("console shuts up ...\n");
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 39ff0708f803..b81f473c4a19 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -65,7 +65,7 @@ SECTIONS
.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
*(.data.cacheline_aligned)
}
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
.data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
*(.data.read_mostly)
}
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index d78f46056bda..1def21c9f7cd 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -112,7 +112,6 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback);
#undef memcpy
#undef memset
#undef memmove
-#undef strlen
extern void * memset(void *,int,__kernel_size_t);
extern size_t strlen(const char *);
@@ -121,8 +120,6 @@ extern void * memcpy(void *,const void *,__kernel_size_t);
extern void * __memcpy(void *,const void *,__kernel_size_t);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(__memcpy);
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index e5f7f1c34462..4ba34e95d835 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -305,7 +305,7 @@ static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned
if (paddr >= end)
break;
- if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
+ if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) {
set_pud(pud, __pud(0));
continue;
}
@@ -507,9 +507,8 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
/*
* Memory hotplug specific functions
- * These are only for non-NUMA machines right now.
*/
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
void online_page(struct page *page)
{
@@ -520,6 +519,38 @@ void online_page(struct page *page)
num_physpages++;
}
+#ifndef CONFIG_MEMORY_HOTPLUG
+/*
+ * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
+ * just online the pages.
+ */
+int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
+{
+ int err = -EIO;
+ unsigned long pfn;
+ unsigned long total = 0, mem = 0;
+ for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
+ if (pfn_valid(pfn)) {
+ online_page(pfn_to_page(pfn));
+ err = 0;
+ mem++;
+ }
+ total++;
+ }
+ if (!err) {
+ z->spanned_pages += total;
+ z->present_pages += mem;
+ z->zone_pgdat->node_spanned_pages += total;
+ z->zone_pgdat->node_present_pages += mem;
+ }
+ return err;
+}
+#endif
+
+/*
+ * Memory is added always to NORMAL zone. This means you will never get
+ * additional DMA/DMA32 memory.
+ */
int add_memory(u64 start, u64 size)
{
struct pglist_data *pgdat = NODE_DATA(0);
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 4be82d6e2b48..b2fac14baac0 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -100,11 +100,30 @@ int early_pfn_to_nid(unsigned long pfn)
}
#endif
+static void * __init
+early_node_mem(int nodeid, unsigned long start, unsigned long end,
+ unsigned long size)
+{
+ unsigned long mem = find_e820_area(start, end, size);
+ void *ptr;
+ if (mem != -1L)
+ return __va(mem);
+ ptr = __alloc_bootmem_nopanic(size,
+ SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS));
+ if (ptr == 0) {
+ printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
+ size, nodeid);
+ return NULL;
+ }
+ return ptr;
+}
+
/* Initialize bootmem allocator for a node */
void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
{
unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start;
unsigned long nodedata_phys;
+ void *bootmap;
const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE);
start = round_up(start, ZONE_ALIGN);
@@ -114,13 +133,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
- nodedata_phys = find_e820_area(start, end, pgdat_size);
- if (nodedata_phys == -1L)
- panic("Cannot find memory pgdat in node %d\n", nodeid);
-
- Dprintk("nodedata_phys %lx\n", nodedata_phys);
+ node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size);
+ if (node_data[nodeid] == NULL)
+ return;
+ nodedata_phys = __pa(node_data[nodeid]);
- node_data[nodeid] = phys_to_virt(nodedata_phys);
memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
NODE_DATA(nodeid)->node_start_pfn = start_pfn;
@@ -129,9 +146,15 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
/* Find a place for the bootmem map */
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
- bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<<PAGE_SHIFT);
- if (bootmap_start == -1L)
- panic("Not enough continuous space for bootmap on node %d", nodeid);
+ bootmap = early_node_mem(nodeid, bootmap_start, end,
+ bootmap_pages<<PAGE_SHIFT);
+ if (bootmap == NULL) {
+ if (nodedata_phys < start || nodedata_phys >= end)
+ free_bootmem((unsigned long)node_data[nodeid],pgdat_size);
+ node_data[nodeid] = NULL;
+ return;
+ }
+ bootmap_start = __pa(bootmap);
Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages);
bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
@@ -142,6 +165,9 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size);
reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
+#ifdef CONFIG_ACPI_NUMA
+ srat_reserve_add_area(nodeid);
+#endif
node_set_online(nodeid);
}
@@ -162,11 +188,13 @@ void __init setup_node_zones(int nodeid)
memory. */
memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
limit = end_pfn << PAGE_SHIFT;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
NODE_DATA(nodeid)->node_mem_map =
__alloc_bootmem_core(NODE_DATA(nodeid)->bdata,
memmapsize, SMP_CACHE_BYTES,
round_down(limit - memmapsize, PAGE_SIZE),
limit);
+#endif
size_zones(zones, holes, start_pfn, end_pfn);
free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
@@ -335,6 +363,8 @@ __init int numa_setup(char *opt)
#ifdef CONFIG_ACPI_NUMA
if (!strncmp(opt,"noacpi",6))
acpi_numa = -1;
+ if (!strncmp(opt,"hotadd=", 7))
+ hotadd_percent = simple_strtoul(opt+7, NULL, 10);
#endif
return 1;
}
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 2eb879590dc4..15ae9fcd65a7 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -15,15 +15,26 @@
#include <linux/bitmap.h>
#include <linux/module.h>
#include <linux/topology.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
#include <asm/proto.h>
#include <asm/numa.h>
#include <asm/e820.h>
+#if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
+ defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \
+ && !defined(CONFIG_MEMORY_HOTPLUG)
+#define RESERVE_HOTADD 1
+#endif
+
static struct acpi_table_slit *acpi_slit;
static nodemask_t nodes_parsed __initdata;
static nodemask_t nodes_found __initdata;
static struct bootnode nodes[MAX_NUMNODES] __initdata;
+static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
+static int found_add_area __initdata;
+int hotadd_percent __initdata = 10;
static u8 pxm2node[256] = { [0 ... 255] = 0xff };
/* Too small nodes confuse the VM badly. Usually they result
@@ -71,6 +82,10 @@ static __init int conflicting_nodes(unsigned long start, unsigned long end)
static __init void cutoff_node(int i, unsigned long start, unsigned long end)
{
struct bootnode *nd = &nodes[i];
+
+ if (found_add_area)
+ return;
+
if (nd->start < start) {
nd->start = start;
if (nd->end < nd->start)
@@ -90,6 +105,8 @@ static __init void bad_srat(void)
acpi_numa = -1;
for (i = 0; i < MAX_LOCAL_APIC; i++)
apicid_to_node[i] = NUMA_NO_NODE;
+ for (i = 0; i < MAX_NUMNODES; i++)
+ nodes_add[i].start = nodes[i].end = 0;
}
static __init inline int srat_disabled(void)
@@ -155,11 +172,114 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
pxm, pa->apic_id, node);
}
+#ifdef RESERVE_HOTADD
+/*
+ * Protect against too large hotadd areas that would fill up memory.
+ */
+static int hotadd_enough_memory(struct bootnode *nd)
+{
+ static unsigned long allocated;
+ static unsigned long last_area_end;
+ unsigned long pages = (nd->end - nd->start) >> PAGE_SHIFT;
+ long mem = pages * sizeof(struct page);
+ unsigned long addr;
+ unsigned long allowed;
+ unsigned long oldpages = pages;
+
+ if (mem < 0)
+ return 0;
+ allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
+ allowed = (allowed / 100) * hotadd_percent;
+ if (allocated + mem > allowed) {
+ /* Give them at least part of their hotadd memory upto hotadd_percent
+ It would be better to spread the limit out
+ over multiple hotplug areas, but that is too complicated
+ right now */
+ if (allocated >= allowed)
+ return 0;
+ pages = (allowed - allocated + mem) / sizeof(struct page);
+ mem = pages * sizeof(struct page);
+ nd->end = nd->start + pages*PAGE_SIZE;
+ }
+ /* Not completely fool proof, but a good sanity check */
+ addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem);
+ if (addr == -1UL)
+ return 0;
+ if (pages != oldpages)
+ printk(KERN_NOTICE "SRAT: Hotadd area limited to %lu bytes\n",
+ pages << PAGE_SHIFT);
+ last_area_end = addr + mem;
+ allocated += mem;
+ return 1;
+}
+
+/*
+ * It is fine to add this area to the nodes data it will be used later
+ * This code supports one contigious hot add area per node.
+ */
+static int reserve_hotadd(int node, unsigned long start, unsigned long end)
+{
+ unsigned long s_pfn = start >> PAGE_SHIFT;
+ unsigned long e_pfn = end >> PAGE_SHIFT;
+ int changed = 0;
+ struct bootnode *nd = &nodes_add[node];
+
+ /* I had some trouble with strange memory hotadd regions breaking
+ the boot. Be very strict here and reject anything unexpected.
+ If you want working memory hotadd write correct SRATs.
+
+ The node size check is a basic sanity check to guard against
+ mistakes */
+ if ((signed long)(end - start) < NODE_MIN_SIZE) {
+ printk(KERN_ERR "SRAT: Hotplug area too small\n");
+ return -1;
+ }
+
+ /* This check might be a bit too strict, but I'm keeping it for now. */
+ if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) {
+ printk(KERN_ERR "SRAT: Hotplug area has existing memory\n");
+ return -1;
+ }
+
+ if (!hotadd_enough_memory(&nodes_add[node])) {
+ printk(KERN_ERR "SRAT: Hotplug area too large\n");
+ return -1;
+ }
+
+ /* Looks good */
+
+ found_add_area = 1;
+ if (nd->start == nd->end) {
+ nd->start = start;
+ nd->end = end;
+ changed = 1;
+ } else {
+ if (nd->start == end) {
+ nd->start = start;
+ changed = 1;
+ }
+ if (nd->end == start) {
+ nd->end = end;
+ changed = 1;
+ }
+ if (!changed)
+ printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
+ }
+
+ if ((nd->end >> PAGE_SHIFT) > end_pfn)
+ end_pfn = nd->end >> PAGE_SHIFT;
+
+ if (changed)
+ printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end);
+ return 0;
+}
+#endif
+
/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
void __init
acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
{
- struct bootnode *nd;
+ struct bootnode *nd, oldnode;
unsigned long start, end;
int node, pxm;
int i;
@@ -172,6 +292,8 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
}
if (ma->flags.enabled == 0)
return;
+ if (ma->flags.hot_pluggable && hotadd_percent == 0)
+ return;
start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32);
end = start + (ma->length_lo | ((u64)ma->length_hi << 32));
pxm = ma->proximity_domain;
@@ -181,10 +303,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
bad_srat();
return;
}
- /* It is fine to add this area to the nodes data it will be used later*/
- if (ma->flags.hot_pluggable == 1)
- printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
- start, end);
i = conflicting_nodes(start, end);
if (i == node) {
printk(KERN_WARNING
@@ -199,6 +317,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
return;
}
nd = &nodes[node];
+ oldnode = *nd;
if (!node_test_and_set(node, nodes_parsed)) {
nd->start = start;
nd->end = end;
@@ -208,8 +327,19 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
if (nd->end < end)
nd->end = end;
}
+
printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
nd->start, nd->end);
+
+#ifdef RESERVE_HOTADD
+ if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
+ /* Ignore hotadd region. Undo damage */
+ printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
+ *nd = oldnode;
+ if ((nd->start | nd->end) == 0)
+ node_clear(node, nodes_parsed);
+ }
+#endif
}
/* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -225,6 +355,9 @@ static int nodes_cover_memory(void)
unsigned long e = nodes[i].end >> PAGE_SHIFT;
pxmram += e - s;
pxmram -= e820_hole_size(s, e);
+ pxmram -= nodes_add[i].end - nodes_add[i].start;
+ if ((long)pxmram < 0)
+ pxmram = 0;
}
e820ram = end_pfn - e820_hole_size(0, end_pfn);
@@ -258,7 +391,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
/* First clean up the node list */
for (i = 0; i < MAX_NUMNODES; i++) {
- cutoff_node(i, start, end);
+ cutoff_node(i, start, end);
if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE)
unparse_node(i);
}
@@ -282,6 +415,12 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
/* Finally register nodes */
for_each_node_mask(i, nodes_parsed)
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ /* Try again in case setup_node_bootmem missed one due
+ to missing bootmem */
+ for_each_node_mask(i, nodes_parsed)
+ if (!node_online(i))
+ setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+
for (i = 0; i < NR_CPUS; i++) {
if (cpu_to_node[i] == NUMA_NO_NODE)
continue;
@@ -303,6 +442,25 @@ static int node_to_pxm(int n)
return 0;
}
+void __init srat_reserve_add_area(int nodeid)
+{
+ if (found_add_area && nodes_add[nodeid].end) {
+ u64 total_mb;
+
+ printk(KERN_INFO "SRAT: Reserving hot-add memory space "
+ "for node %d at %Lx-%Lx\n",
+ nodeid, nodes_add[nodeid].start, nodes_add[nodeid].end);
+ total_mb = (nodes_add[nodeid].end - nodes_add[nodeid].start)
+ >> PAGE_SHIFT;
+ total_mb *= sizeof(struct page);
+ total_mb >>= 20;
+ printk(KERN_INFO "SRAT: This will cost you %Lu MB of "
+ "pre-allocated memory.\n", (unsigned long long)total_mb);
+ reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start,
+ nodes_add[nodeid].end - nodes_add[nodeid].start);
+ }
+}
+
int __node_distance(int a, int b)
{
int index;
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index e616500207e4..a2060e4d5de6 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,11 +9,16 @@
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/bitmap.h>
+#include <asm/e820.h>
+
#include "pci.h"
#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* Verify the first 16 busses. We assume that systems with more busses
+ get MCFG right. */
+#define MAX_CHECK_BUS 16
-static DECLARE_BITMAP(fallback_slots, 32);
+static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
/* Static virtual mapping of the MMCONFIG aperture */
struct mmcfg_virt {
@@ -55,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{
char __iomem *addr;
- if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots))
+ if (seg == 0 && bus < MAX_CHECK_BUS &&
+ test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
return NULL;
addr = get_virt(seg, bus);
if (!addr)
@@ -69,8 +75,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
char __iomem *addr;
/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
- if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
+ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
+ *value = -1;
return -EINVAL;
+ }
addr = pci_dev_base(seg, bus, devfn);
if (!addr)
@@ -129,21 +137,26 @@ static struct pci_raw_ops pci_mmcfg = {
Normally this can be expressed in the MCFG by not listing them
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
- and fallback for them.
- We only do this for bus 0/seg 0 */
+ and fallback for them. */
static __init void unreachable_devices(void)
{
- int i;
- for (i = 0; i < 32; i++) {
- u32 val1;
- char __iomem *addr;
-
- pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
- if (val1 == 0xffffffff)
- continue;
- addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
- if (addr == NULL|| readl(addr) != val1) {
- set_bit(i, fallback_slots);
+ int i, k;
+ /* Use the max bus number from ACPI here? */
+ for (k = 0; k < MAX_CHECK_BUS; k++) {
+ for (i = 0; i < 32; i++) {
+ u32 val1;
+ char __iomem *addr;
+
+ pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
+ if (val1 == 0xffffffff)
+ continue;
+ addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
+ if (addr == NULL|| readl(addr) != val1) {
+ set_bit(i + 32*k, fallback_slots);
+ printk(KERN_NOTICE
+ "PCI: No mmconfig possible on device %x:%x\n",
+ k, i);
+ }
}
}
}
@@ -161,6 +174,14 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
+ if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+ pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+ E820_RESERVED)) {
+ printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+ return;
+ }
+
/* RED-PEN i386 doesn't do _nocache right now */
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) {
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 152b9370789b..a15b6e3e72c8 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -48,7 +48,6 @@ EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 296708ceceb2..e25a5d79ab27 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1844,9 +1844,10 @@ static void __exit as_exit(void)
DECLARE_COMPLETION(all_gone);
elv_unregister(&iosched_as);
ioc_gone = &all_gone;
- barrier();
+ /* ioc_gone's update must be visible before reading ioc_count */
+ smp_wmb();
if (atomic_read(&ioc_count))
- complete(ioc_gone);
+ wait_for_completion(ioc_gone);
synchronize_rcu();
kmem_cache_destroy(arq_pool);
}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 67d446de0227..2540dfaa3e38 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1472,19 +1472,37 @@ out:
return cfqq;
}
+static void
+cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
+{
+ read_lock(&cfq_exit_lock);
+ rb_erase(&cic->rb_node, &ioc->cic_root);
+ read_unlock(&cfq_exit_lock);
+ kmem_cache_free(cfq_ioc_pool, cic);
+ atomic_dec(&ioc_count);
+}
+
static struct cfq_io_context *
cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
{
- struct rb_node *n = ioc->cic_root.rb_node;
+ struct rb_node *n;
struct cfq_io_context *cic;
- void *key = cfqd;
+ void *k, *key = cfqd;
+restart:
+ n = ioc->cic_root.rb_node;
while (n) {
cic = rb_entry(n, struct cfq_io_context, rb_node);
+ /* ->key must be copied to avoid race with cfq_exit_queue() */
+ k = cic->key;
+ if (unlikely(!k)) {
+ cfq_drop_dead_cic(ioc, cic);
+ goto restart;
+ }
- if (key < cic->key)
+ if (key < k)
n = n->rb_left;
- else if (key > cic->key)
+ else if (key > k)
n = n->rb_right;
else
return cic;
@@ -1497,29 +1515,37 @@ static inline void
cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
struct cfq_io_context *cic)
{
- struct rb_node **p = &ioc->cic_root.rb_node;
- struct rb_node *parent = NULL;
+ struct rb_node **p;
+ struct rb_node *parent;
struct cfq_io_context *__cic;
-
- read_lock(&cfq_exit_lock);
+ void *k;
cic->ioc = ioc;
cic->key = cfqd;
ioc->set_ioprio = cfq_ioc_set_ioprio;
-
+restart:
+ parent = NULL;
+ p = &ioc->cic_root.rb_node;
while (*p) {
parent = *p;
__cic = rb_entry(parent, struct cfq_io_context, rb_node);
+ /* ->key must be copied to avoid race with cfq_exit_queue() */
+ k = __cic->key;
+ if (unlikely(!k)) {
+ cfq_drop_dead_cic(ioc, cic);
+ goto restart;
+ }
- if (cic->key < __cic->key)
+ if (cic->key < k)
p = &(*p)->rb_left;
- else if (cic->key > __cic->key)
+ else if (cic->key > k)
p = &(*p)->rb_right;
else
BUG();
}
+ read_lock(&cfq_exit_lock);
rb_link_node(&cic->rb_node, parent, p);
rb_insert_color(&cic->rb_node, &ioc->cic_root);
list_add(&cic->queue_list, &cfqd->cic_list);
@@ -2439,9 +2465,10 @@ static void __exit cfq_exit(void)
DECLARE_COMPLETION(all_gone);
elv_unregister(&iosched_cfq);
ioc_gone = &all_gone;
- barrier();
+ /* ioc_gone's update must be visible before reading ioc_count */
+ smp_wmb();
if (atomic_read(&ioc_count))
- complete(ioc_gone);
+ wait_for_completion(ioc_gone);
synchronize_rcu();
cfq_slab_kill();
}
diff --git a/block/elevator.c b/block/elevator.c
index 0d6be03d929e..29825792cbd5 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -895,10 +895,8 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
EXPORT_SYMBOL(elv_dispatch_sort);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
-EXPORT_SYMBOL(elv_requeue_request);
EXPORT_SYMBOL(elv_next_request);
EXPORT_SYMBOL(elv_dequeue_request);
EXPORT_SYMBOL(elv_queue_empty);
-EXPORT_SYMBOL(elv_completed_request);
EXPORT_SYMBOL(elevator_exit);
EXPORT_SYMBOL(elevator_init);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 5b26af8597f3..e5041a02e21f 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1554,7 +1554,7 @@ void blk_plug_device(request_queue_t *q)
* don't plug a stopped queue, it must be paired with blk_start_queue()
* which will restart the queueing
*/
- if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+ if (blk_queue_stopped(q))
return;
if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
@@ -1587,7 +1587,7 @@ EXPORT_SYMBOL(blk_remove_plug);
*/
void __generic_unplug_device(request_queue_t *q)
{
- if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
+ if (unlikely(blk_queue_stopped(q)))
return;
if (!blk_remove_plug(q))
@@ -1740,7 +1740,7 @@ EXPORT_SYMBOL(blk_run_queue);
/**
* blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
- * @q: the request queue to be released
+ * @kobj: the kobj belonging of the request queue to be released
*
* Description:
* blk_cleanup_queue is the pair to blk_init_queue() or
@@ -3385,7 +3385,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
}
-static struct notifier_block __devinitdata blk_cpu_notifier = {
+static struct notifier_block blk_cpu_notifier = {
.notifier_call = blk_cpu_notify,
};
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 24f7af9d0abc..b33eda26e205 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -350,16 +350,51 @@ out:
return ret;
}
+/**
+ * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
+ * @file: file this ioctl operates on (optional)
+ * @q: request queue to send scsi commands down
+ * @disk: gendisk to operate on (option)
+ * @sic: userspace structure describing the command to perform
+ *
+ * Send down the scsi command described by @sic to the device below
+ * the request queue @q. If @file is non-NULL it's used to perform
+ * fine-grained permission checks that allow users to send down
+ * non-destructive SCSI commands. If the caller has a struct gendisk
+ * available it should be passed in as @disk to allow the low level
+ * driver to use the information contained in it. A non-NULL @disk
+ * is only allowed if the caller knows that the low level driver doesn't
+ * need it (e.g. in the scsi subsystem).
+ *
+ * Notes:
+ * - This interface is deprecated - users should use the SG_IO
+ * interface instead, as this is a more flexible approach to
+ * performing SCSI commands on a device.
+ * - The SCSI command length is determined by examining the 1st byte
+ * of the given command. There is no way to override this.
+ * - Data transfers are limited to PAGE_SIZE
+ * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
+ * accommodate the sense buffer when an error occurs.
+ * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
+ * old code will not be surprised.
+ * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
+ * a negative return and the Unix error code in 'errno'.
+ * If the SCSI command succeeds then 0 is returned.
+ * Positive numbers returned are the compacted SCSI error codes (4
+ * bytes in one int) where the lowest byte is the SCSI status.
+ */
#define OMAX_SB_LEN 16 /* For backward compatibility */
-
-static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
- struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
+int sg_scsi_ioctl(struct file *file, struct request_queue *q,
+ struct gendisk *disk, struct scsi_ioctl_command __user *sic)
{
struct request *rq;
int err;
unsigned int in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
+ if (!sic)
+ return -EINVAL;
+
/*
* get in an out lengths, verify they don't exceed a page worth of data
*/
@@ -393,45 +428,53 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
if (copy_from_user(rq->cmd, sic->data, cmdlen))
goto error;
- if (copy_from_user(buffer, sic->data + cmdlen, in_len))
+ if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
goto error;
err = verify_command(file, rq->cmd);
if (err)
goto error;
+ /* default. possible overriden later */
+ rq->retries = 5;
+
switch (opcode) {
- case SEND_DIAGNOSTIC:
- case FORMAT_UNIT:
- rq->timeout = FORMAT_UNIT_TIMEOUT;
- break;
- case START_STOP:
- rq->timeout = START_STOP_TIMEOUT;
- break;
- case MOVE_MEDIUM:
- rq->timeout = MOVE_MEDIUM_TIMEOUT;
- break;
- case READ_ELEMENT_STATUS:
- rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
- break;
- case READ_DEFECT_DATA:
- rq->timeout = READ_DEFECT_DATA_TIMEOUT;
- break;
- default:
- rq->timeout = BLK_DEFAULT_TIMEOUT;
- break;
+ case SEND_DIAGNOSTIC:
+ case FORMAT_UNIT:
+ rq->timeout = FORMAT_UNIT_TIMEOUT;
+ rq->retries = 1;
+ break;
+ case START_STOP:
+ rq->timeout = START_STOP_TIMEOUT;
+ break;
+ case MOVE_MEDIUM:
+ rq->timeout = MOVE_MEDIUM_TIMEOUT;
+ break;
+ case READ_ELEMENT_STATUS:
+ rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
+ break;
+ case READ_DEFECT_DATA:
+ rq->timeout = READ_DEFECT_DATA_TIMEOUT;
+ rq->retries = 1;
+ break;
+ default:
+ rq->timeout = BLK_DEFAULT_TIMEOUT;
+ break;
+ }
+
+ if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) {
+ err = DRIVER_ERROR << 24;
+ goto out;
}
memset(sense, 0, sizeof(sense));
rq->sense = sense;
rq->sense_len = 0;
-
- rq->data = buffer;
- rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC;
- rq->retries = 0;
- blk_execute_rq(q, bd_disk, rq, 0);
+ blk_execute_rq(q, disk, rq, 0);
+
+out:
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) {
if (rq->sense_len && rq->sense) {
@@ -450,7 +493,7 @@ error:
blk_put_request(rq);
return err;
}
-
+EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
/* Send basic block requests */
static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 5c91d6afb117..aeb5ab2391e4 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -68,8 +68,6 @@ source "drivers/leds/Kconfig"
source "drivers/infiniband/Kconfig"
-source "drivers/sn/Kconfig"
-
source "drivers/edac/Kconfig"
source "drivers/rtc/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 55205c8d2318..447d8e68887a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
+obj-$(CONFIG_IPATH_CORE) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5cb96300eb0f..c24652d31bf9 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -329,7 +329,7 @@ config ACPI_CONTAINER
config ACPI_HOTPLUG_MEMORY
tristate "Memory Hotplug"
depends on ACPI
- depends on MEMORY_HOTPLUG
+ depends on MEMORY_HOTPLUG || X86_64
default n
help
This driver adds supports for ACPI Memory Hotplug. This driver
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 48718b7f4fa0..76656acd00d4 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device_driver *drv,
up(&dev->sem);
if (dev->parent)
up(&dev->parent->sem);
+
+ if (err > 0) /* success */
+ err = count;
+ else if (err == 0) /* driver didn't accept device */
+ err = -ENODEV;
}
put_device(dev);
put_bus(bus);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index df7fdabd0730..0e71dff327cd 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -562,14 +562,13 @@ int class_device_add(struct class_device *class_dev)
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */
- if (parent_class) {
- down(&parent_class->sem);
- list_add_tail(&class_dev->node, &parent_class->children);
- list_for_each_entry(class_intf, &parent_class->interfaces, node)
- if (class_intf->add)
- class_intf->add(class_dev, class_intf);
- up(&parent_class->sem);
+ down(&parent_class->sem);
+ list_add_tail(&class_dev->node, &parent_class->children);
+ list_for_each_entry(class_intf, &parent_class->interfaces, node) {
+ if (class_intf->add)
+ class_intf->add(class_dev, class_intf);
}
+ up(&parent_class->sem);
register_done:
if (error) {
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 730a9ce0a14a..889c71111239 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev)
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
- if (dev->bus->remove)
+ if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
else if (drv->remove)
drv->remove(dev);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 16c513aa4d48..c80c3aeed004 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -106,7 +106,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
other_node = 0;
for (i = 0; i < MAX_NR_ZONES; i++) {
struct zone *z = &pg->node_zones[i];
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for_each_online_cpu(cpu) {
struct per_cpu_pageset *ps = zone_pcp(z,cpu);
numa_hit += ps->numa_hit;
numa_miss += ps->numa_miss;
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index bdb60663f2ef..662209d3f42d 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -10,6 +10,8 @@
#include <linux/vt_kern.h>
#include <linux/device.h>
+#include <linux/kallsyms.h>
+#include <linux/pm.h>
#include "../base.h"
#include "power.h"
@@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state)
if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
+ suspend_report_result(dev->bus->suspend, error);
}
up(&dev->sem);
return error;
@@ -169,3 +172,12 @@ int device_power_down(pm_message_t state)
EXPORT_SYMBOL_GPL(device_power_down);
+void __suspend_report_result(const char *function, void *fn, int ret)
+{
+ if (ret) {
+ printk(KERN_ERR "%s(): ", function);
+ print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
+ printk("%d\n", ret);
+ }
+}
+EXPORT_SYMBOL_GPL(__suspend_report_result);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 915810f6237e..8c52421cbc54 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -107,7 +107,7 @@ static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
return 0;
}
-static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
+static int topology_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1b0fd31c57c3..1319d8f20640 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1180,6 +1180,53 @@ static int revalidate_allvol(ctlr_info_t *host)
return 0;
}
+static inline void complete_buffers(struct bio *bio, int status)
+{
+ while (bio) {
+ struct bio *xbh = bio->bi_next;
+ int nr_sectors = bio_sectors(bio);
+
+ bio->bi_next = NULL;
+ blk_finished_io(len);
+ bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+ bio = xbh;
+ }
+
+}
+
+static void cciss_softirq_done(struct request *rq)
+{
+ CommandList_struct *cmd = rq->completion_data;
+ ctlr_info_t *h = hba[cmd->ctlr];
+ unsigned long flags;
+ u64bit temp64;
+ int i, ddir;
+
+ if (cmd->Request.Type.Direction == XFER_READ)
+ ddir = PCI_DMA_FROMDEVICE;
+ else
+ ddir = PCI_DMA_TODEVICE;
+
+ /* command did not need to be retried */
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->Header.SGList; i++) {
+ temp64.val32.lower = cmd->SG[i].Addr.lower;
+ temp64.val32.upper = cmd->SG[i].Addr.upper;
+ pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+ }
+
+ complete_buffers(rq->bio, rq->errors);
+
+#ifdef CCISS_DEBUG
+ printk("Done with %p\n", rq);
+#endif /* CCISS_DEBUG */
+
+ spin_lock_irqsave(&h->lock, flags);
+ end_that_request_last(rq, rq->errors);
+ cmd_free(h, cmd,1);
+ spin_unlock_irqrestore(&h->lock, flags);
+}
+
/* This function will check the usage_count of the drive to be updated/added.
* If the usage_count is zero then the drive information will be updated and
* the disk will be re-registered with the kernel. If not then it will be
@@ -1248,6 +1295,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
blk_queue_max_sectors(disk->queue, 512);
+ blk_queue_softirq_done(disk->queue, cciss_softirq_done);
+
disk->queue->queuedata = hba[ctlr];
blk_queue_hardsect_size(disk->queue,
@@ -2147,20 +2196,6 @@ static void start_io( ctlr_info_t *h)
addQ (&(h->cmpQ), c);
}
}
-
-static inline void complete_buffers(struct bio *bio, int status)
-{
- while (bio) {
- struct bio *xbh = bio->bi_next;
- int nr_sectors = bio_sectors(bio);
-
- bio->bi_next = NULL;
- blk_finished_io(len);
- bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
- bio = xbh;
- }
-
-}
/* Assumes that CCISS_LOCK(h->ctlr) is held. */
/* Zeros out the error record and then resends the command back */
/* to the controller */
@@ -2178,39 +2213,6 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
start_io(h);
}
-static void cciss_softirq_done(struct request *rq)
-{
- CommandList_struct *cmd = rq->completion_data;
- ctlr_info_t *h = hba[cmd->ctlr];
- unsigned long flags;
- u64bit temp64;
- int i, ddir;
-
- if (cmd->Request.Type.Direction == XFER_READ)
- ddir = PCI_DMA_FROMDEVICE;
- else
- ddir = PCI_DMA_TODEVICE;
-
- /* command did not need to be retried */
- /* unmap the DMA mapping for all the scatter gather elements */
- for(i=0; i<cmd->Header.SGList; i++) {
- temp64.val32.lower = cmd->SG[i].Addr.lower;
- temp64.val32.upper = cmd->SG[i].Addr.upper;
- pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
- }
-
- complete_buffers(rq->bio, rq->errors);
-
-#ifdef CCISS_DEBUG
- printk("Done with %p\n", rq);
-#endif /* CCISS_DEBUG */
-
- spin_lock_irqsave(&h->lock, flags);
- end_that_request_last(rq, rq->errors);
- cmd_free(h, cmd,1);
- spin_unlock_irqrestore(&h->lock, flags);
-}
-
/* checks the status of the job and calls complete buffers to mark all
* buffers for the completed job. Note that this function does not need
* to hold the hba/queue lock.
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 9888bc151755..473a13b22b29 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");
typedef struct bluecard_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -85,8 +85,8 @@ typedef struct bluecard_info_t {
} bluecard_info_t;
-static void bluecard_config(dev_link_t *link);
-static void bluecard_release(dev_link_t *link);
+static int bluecard_config(struct pcmcia_device *link);
+static void bluecard_release(struct pcmcia_device *link);
static void bluecard_detach(struct pcmcia_device *p_dev);
@@ -162,7 +162,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
static void bluecard_activity_led_timeout(u_long arg)
{
bluecard_info_t *info = (bluecard_info_t *)arg;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
return;
@@ -179,7 +179,7 @@ static void bluecard_activity_led_timeout(u_long arg)
static void bluecard_enable_activity_led(bluecard_info_t *info)
{
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
return;
@@ -235,7 +235,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
}
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register unsigned int offset;
register unsigned char command;
register unsigned long ready_bit;
@@ -244,7 +244,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
clear_bit(XMIT_WAKEUP, &(info->tx_state));
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
return;
if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
@@ -382,7 +382,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
bluecard_enable_activity_led(info);
@@ -512,7 +512,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *r
if (!test_bit(CARD_READY, &(info->hw_state)))
return IRQ_HANDLED;
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -626,7 +626,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
static int bluecard_hci_open(struct hci_dev *hdev)
{
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -646,7 +646,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
static int bluecard_hci_close(struct hci_dev *hdev)
{
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
@@ -713,7 +713,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l
static int bluecard_open(bluecard_info_t *info)
{
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev;
unsigned char id;
@@ -831,7 +831,7 @@ static int bluecard_open(bluecard_info_t *info)
static int bluecard_close(bluecard_info_t *info)
{
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -856,17 +856,16 @@ static int bluecard_close(bluecard_info_t *info)
return 0;
}
-static int bluecard_attach(struct pcmcia_device *p_dev)
+static int bluecard_probe(struct pcmcia_device *link)
{
bluecard_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -878,32 +877,22 @@ static int bluecard_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- bluecard_config(link);
-
- return 0;
+ return bluecard_config(link);
}
-static void bluecard_detach(struct pcmcia_device *p_dev)
+static void bluecard_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
bluecard_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- bluecard_release(link);
-
+ bluecard_release(link);
kfree(info);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -918,14 +907,12 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static void bluecard_config(dev_link_t *link)
+static int bluecard_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
bluecard_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
- config_info_t config;
int i, n, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -935,7 +922,7 @@ static void bluecard_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -943,36 +930,31 @@ static void bluecard_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
link->conf.ConfigIndex = 0x20;
link->io.NumPorts1 = 64;
link->io.IOAddrLines = 6;
for (n = 0; n < 0x400; n += 0x40) {
link->io.BasePort1 = n ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -980,57 +962,28 @@ static void bluecard_config(dev_link_t *link)
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
bluecard_release(link);
+ return -ENODEV;
}
-static void bluecard_release(dev_link_t *link)
+static void bluecard_release(struct pcmcia_device *link)
{
bluecard_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- bluecard_close(info);
+ bluecard_close(info);
del_timer(&(info->timer));
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int bluecard_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int bluecard_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
static struct pcmcia_device_id bluecard_ids[] = {
@@ -1046,11 +999,9 @@ static struct pcmcia_driver bluecard_driver = {
.drv = {
.name = "bluecard_cs",
},
- .probe = bluecard_attach,
+ .probe = bluecard_probe,
.remove = bluecard_detach,
.id_table = bluecard_ids,
- .suspend = bluecard_suspend,
- .resume = bluecard_resume,
};
static int __init init_bluecard_cs(void)
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7e21b1ff27c4..b94ac2f9f7ba 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -72,7 +72,7 @@ MODULE_LICENSE("GPL");
typedef struct bt3c_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -88,8 +88,8 @@ typedef struct bt3c_info_t {
} bt3c_info_t;
-static void bt3c_config(dev_link_t *link);
-static void bt3c_release(dev_link_t *link);
+static int bt3c_config(struct pcmcia_device *link);
+static void bt3c_release(struct pcmcia_device *link);
static void bt3c_detach(struct pcmcia_device *p_dev);
@@ -191,11 +191,11 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
return;
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register struct sk_buff *skb;
register int len;
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
break;
@@ -229,7 +229,7 @@ static void bt3c_receive(bt3c_info_t *info)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
avail = bt3c_read(iobase, 0x7006);
//printk("bt3c_cs: receiving %d bytes\n", avail);
@@ -350,7 +350,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
return IRQ_NONE;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -481,7 +481,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int co
unsigned int iobase, size, addr, fcs, tmp;
int i, err = 0;
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
/* Reset */
bt3c_io_write(iobase, 0x8040, 0x0404);
@@ -562,7 +562,6 @@ static int bt3c_open(bt3c_info_t *info)
{
const struct firmware *firmware;
struct hci_dev *hdev;
- client_handle_t handle;
int err;
spin_lock_init(&(info->lock));
@@ -594,10 +593,8 @@ static int bt3c_open(bt3c_info_t *info)
hdev->owner = THIS_MODULE;
- handle = info->link.handle;
-
/* Load firmware */
- err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
+ err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
if (err < 0) {
BT_ERR("Firmware request failed");
goto error;
@@ -648,17 +645,16 @@ static int bt3c_close(bt3c_info_t *info)
return 0;
}
-static int bt3c_attach(struct pcmcia_device *p_dev)
+static int bt3c_probe(struct pcmcia_device *link)
{
bt3c_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -670,31 +666,21 @@ static int bt3c_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- bt3c_config(link);
-
- return 0;
+ return bt3c_config(link);
}
-static void bt3c_detach(struct pcmcia_device *p_dev)
+static void bt3c_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
bt3c_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- bt3c_release(link);
-
+ bt3c_release(link);
kfree(info);
}
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -705,30 +691,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static void bt3c_config(dev_link_t *link)
+static int bt3c_config(struct pcmcia_device *link)
{
static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- client_handle_t handle = link->handle;
bt3c_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
int i, j, try, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -738,7 +722,7 @@ static void bt3c_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -746,11 +730,6 @@ static void bt3c_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
/* First pass: look for a config entry that looks normal. */
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
@@ -759,59 +738,59 @@ static void bt3c_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
/* Two tries: without IO aliases, then with aliases */
for (try = 0; try < 2; try++) {
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
}
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
link->conf.ConfigIndex = cf->index;
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
BT_ERR("No usable port range found");
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -819,55 +798,26 @@ found_port:
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
bt3c_release(link);
+ return -ENODEV;
}
-static void bt3c_release(dev_link_t *link)
+static void bt3c_release(struct pcmcia_device *link)
{
bt3c_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- bt3c_close(info);
-
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int bt3c_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
+ bt3c_close(info);
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int bt3c_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
@@ -882,11 +832,9 @@ static struct pcmcia_driver bt3c_driver = {
.drv = {
.name = "bt3c_cs",
},
- .probe = bt3c_attach,
+ .probe = bt3c_probe,
.remove = bt3c_detach,
.id_table = bt3c_ids,
- .suspend = bt3c_suspend,
- .resume = bt3c_resume,
};
static int __init init_bt3c_cs(void)
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 7b4bff4cfa2d..9ce4c93467e5 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -68,7 +68,7 @@ MODULE_LICENSE("GPL");
typedef struct btuart_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -84,8 +84,8 @@ typedef struct btuart_info_t {
} btuart_info_t;
-static void btuart_config(dev_link_t *link);
-static void btuart_release(dev_link_t *link);
+static int btuart_config(struct pcmcia_device *link);
+static void btuart_release(struct pcmcia_device *link);
static void btuart_detach(struct pcmcia_device *p_dev);
@@ -146,13 +146,13 @@ static void btuart_write_wakeup(btuart_info_t *info)
}
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register struct sk_buff *skb;
register int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
return;
if (!(skb = skb_dequeue(&(info->txq))))
@@ -187,7 +187,7 @@ static void btuart_receive(btuart_info_t *info)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
do {
info->hdev->stat.byte_rx++;
@@ -301,7 +301,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst, struct pt_regs *reg
return IRQ_NONE;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -357,7 +357,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock_irqsave(&(info->lock), flags);
@@ -481,7 +481,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon
static int btuart_open(btuart_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev;
spin_lock_init(&(info->lock));
@@ -550,7 +550,7 @@ static int btuart_open(btuart_info_t *info)
static int btuart_close(btuart_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -576,17 +576,16 @@ static int btuart_close(btuart_info_t *info)
return 0;
}
-static int btuart_attach(struct pcmcia_device *p_dev)
+static int btuart_probe(struct pcmcia_device *link)
{
btuart_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -598,31 +597,21 @@ static int btuart_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- btuart_config(link);
-
- return 0;
+ return btuart_config(link);
}
-static void btuart_detach(struct pcmcia_device *p_dev)
+static void btuart_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
btuart_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- btuart_release(link);
-
+ btuart_release(link);
kfree(info);
}
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -633,30 +622,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static void btuart_config(dev_link_t *link)
+static int btuart_config(struct pcmcia_device *link)
{
static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- client_handle_t handle = link->handle;
btuart_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
int i, j, try, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -666,7 +653,7 @@ static void btuart_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -674,11 +661,6 @@ static void btuart_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
/* First pass: look for a config entry that looks normal. */
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleOffset = 0;
@@ -687,29 +669,29 @@ static void btuart_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
/* Two tries: without IO aliases, then with aliases */
for (try = 0; try < 2; try++) {
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
}
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
&& ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -717,30 +699,30 @@ next_entry:
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
BT_ERR("No usable port range found");
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -748,58 +730,28 @@ found_port:
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
btuart_release(link);
+ return -ENODEV;
}
-static void btuart_release(dev_link_t *link)
+static void btuart_release(struct pcmcia_device *link)
{
btuart_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- btuart_close(info);
-
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int btuart_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
+ btuart_close(info);
- return 0;
+ pcmcia_disable_device(link);
}
-static int btuart_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
-
static struct pcmcia_device_id btuart_ids[] = {
/* don't use this driver. Use serial_cs + hci_uart instead */
PCMCIA_DEVICE_NULL
@@ -811,11 +763,9 @@ static struct pcmcia_driver btuart_driver = {
.drv = {
.name = "btuart_cs",
},
- .probe = btuart_attach,
+ .probe = btuart_probe,
.remove = btuart_detach,
.id_table = btuart_ids,
- .suspend = btuart_suspend,
- .resume = btuart_resume,
};
static int __init init_btuart_cs(void)
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 0449bc45ae5e..a71a240611e0 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -68,7 +68,7 @@ MODULE_LICENSE("GPL");
typedef struct dtl1_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -87,8 +87,8 @@ typedef struct dtl1_info_t {
} dtl1_info_t;
-static void dtl1_config(dev_link_t *link);
-static void dtl1_release(dev_link_t *link);
+static int dtl1_config(struct pcmcia_device *link);
+static void dtl1_release(struct pcmcia_device *link);
static void dtl1_detach(struct pcmcia_device *p_dev);
@@ -153,13 +153,13 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
}
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register struct sk_buff *skb;
register int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
return;
if (!(skb = skb_dequeue(&(info->txq))))
@@ -218,7 +218,7 @@ static void dtl1_receive(dtl1_info_t *info)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
do {
info->hdev->stat.byte_rx++;
@@ -305,7 +305,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
return IRQ_NONE;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -458,7 +458,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
static int dtl1_open(dtl1_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev;
spin_lock_init(&(info->lock));
@@ -504,7 +504,7 @@ static int dtl1_open(dtl1_info_t *info)
outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */
outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
- info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
+ info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
/* Turn on interrupts */
outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
@@ -529,7 +529,7 @@ static int dtl1_open(dtl1_info_t *info)
static int dtl1_close(dtl1_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -555,17 +555,16 @@ static int dtl1_close(dtl1_info_t *info)
return 0;
}
-static int dtl1_attach(struct pcmcia_device *p_dev)
+static int dtl1_probe(struct pcmcia_device *link)
{
dtl1_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -577,31 +576,22 @@ static int dtl1_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- dtl1_config(link);
-
- return 0;
+ return dtl1_config(link);
}
-static void dtl1_detach(struct pcmcia_device *p_dev)
+static void dtl1_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
dtl1_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- dtl1_release(link);
+ dtl1_release(link);
kfree(info);
}
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -612,29 +602,27 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static void dtl1_config(dev_link_t *link)
+static int dtl1_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
dtl1_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
int i, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -644,7 +632,7 @@ static void dtl1_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -652,11 +640,6 @@ static void dtl1_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
@@ -665,34 +648,34 @@ static void dtl1_config(dev_link_t *link)
/* Look for a generic full-sized window */
link->io.NumPorts1 = 8;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.NumPorts1 = cf->io.win[0].len; /*yo */
link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -700,55 +683,26 @@ static void dtl1_config(dev_link_t *link)
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
dtl1_release(link);
+ return -ENODEV;
}
-static void dtl1_release(dev_link_t *link)
+static void dtl1_release(struct pcmcia_device *link)
{
dtl1_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- dtl1_close(info);
-
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int dtl1_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int dtl1_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
+ dtl1_close(info);
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
@@ -765,11 +719,9 @@ static struct pcmcia_driver dtl1_driver = {
.drv = {
.name = "dtl1_cs",
},
- .probe = dtl1_attach,
+ .probe = dtl1_probe,
.remove = dtl1_detach,
.id_table = dtl1_ids,
- .suspend = dtl1_suspend,
- .resume = dtl1_resume,
};
static int __init init_dtl1_cs(void)
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index ce4a1ce59d6a..ec004897b634 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -1763,7 +1763,7 @@ static int __init aztcd_init(void)
release_region(azt_port, 4);
}
}
- if ((azt_port_auto[i] == 0) || (i == 16)) {
+ if ((i == 16) || (azt_port_auto[i] == 0)) {
printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
return -EIO;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 889cad07774e..402296670d3a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -805,10 +805,6 @@ config S3C2410_RTC
Samsung S3C2410. This can provide periodic interrupt rates
from 1Hz to 64Hz for user programs, and wakeup from Alarm.
-config RTC_VR41XX
- tristate "NEC VR4100 series Real Time Clock Support"
- depends on CPU_VR41XX
-
config COBALT_LCD
bool "Support for Cobalt LCD"
depends on MIPS_COBALT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index a73cb4956928..f5b01c6d498e 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -67,7 +67,6 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o
obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
obj-$(CONFIG_DS1302) += ds1302.o
obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
-obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
ifeq ($(CONFIG_GENERIC_NVRAM),y)
obj-$(CONFIG_NVRAM) += generic_nvram.o
else
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index fed0a87448d8..86a966b65236 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -64,6 +64,12 @@ static struct gatt_mask efficeon_generic_masks[] =
{.mask = 0x00000001, .type = 0}
};
+/* This function does the same thing as mask_memory() for this chipset... */
+static inline unsigned long efficeon_mask_memory(unsigned long addr)
+{
+ return addr | 0x00000001;
+}
+
static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
{
{256, 65536, 0},
@@ -251,7 +257,7 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t
last_page = NULL;
for (i = 0; i < count; i++) {
int index = pg_start + i;
- unsigned long insert = mem->memory[i];
+ unsigned long insert = efficeon_mask_memory(mem->memory[i]);
page = (unsigned int *) efficeon_private.l1_table[index >> 10];
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 927a5bbe112c..a370e7a0bad5 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -142,7 +142,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc,
if (!boardno)
boardno = readb(loc + NUMCARD_OWNER_TO_PC);
- if (!boardno && boardno > MAX_BOARD) {
+ if (!boardno || boardno > MAX_BOARD) {
printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",
boardno, physloc, MAX_BOARD);
return 0;
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 5d72f50de1ac..46d66037b917 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -241,9 +241,10 @@ static int __init cs5535_gpio_init(void)
static void __exit cs5535_gpio_cleanup(void)
{
dev_t dev_id = MKDEV(major, 0);
+
+ cdev_del(&cs5535_gpio_cdev);
unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
- if (gpio_base != 0)
- release_region(gpio_base, CS5535_GPIO_SIZE);
+ release_region(gpio_base, CS5535_GPIO_SIZE);
}
module_init(cs5535_gpio_init);
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index edc72a6348a7..cb76e5ca9a23 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -815,8 +815,6 @@ extern int drm_mem_info(char *buf, char **start, off_t offset,
extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
extern void *drm_ioremap(unsigned long offset, unsigned long size,
drm_device_t * dev);
-extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
- drm_device_t * dev);
extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
@@ -891,7 +889,6 @@ extern int drm_lock_free(drm_device_t * dev,
/* Buffer management support (drm_bufs.h) */
extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request);
extern int drm_addmap(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_local_map_t ** map_ptr);
@@ -1022,11 +1019,13 @@ static __inline__ void drm_core_ioremap(struct drm_map *map,
map->handle = drm_ioremap(map->offset, map->size, dev);
}
+#if 0
static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
struct drm_device *dev)
{
map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
}
+#endif /* 0 */
static __inline__ void drm_core_ioremapfree(struct drm_map *map,
struct drm_device *dev)
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index fabc930c67a2..40bfd9b01e39 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -503,8 +503,6 @@ int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
return agp_bind_memory(handle, start);
}
-EXPORT_SYMBOL(drm_agp_bind_memory);
-
/** Calls agp_unbind_memory() */
int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
{
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 8a9cf12e6183..006b06d29727 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -386,7 +386,6 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
return 0;
}
-EXPORT_SYMBOL(drm_rmmap_locked);
int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{
@@ -398,7 +397,6 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
return ret;
}
-EXPORT_SYMBOL(drm_rmmap);
/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
* the last close of the device, and this is necessary for cleanup when things
@@ -1053,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
@@ -1212,7 +1210,6 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
-EXPORT_SYMBOL(drm_addbufs_fb);
/**
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index dc6bbe8a18dc..3c0b882a8e72 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -75,8 +75,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
- [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index dddf8de66143..7e3318e1d1c6 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -80,6 +80,71 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
}
#if __OS_HAS_AGP
+/*
+ * Find the drm_map that covers the range [offset, offset+size).
+ */
+static drm_map_t *drm_lookup_map(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
+{
+ struct list_head *list;
+ drm_map_list_t *r_list;
+ drm_map_t *map;
+
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *) list;
+ map = r_list->map;
+ if (!map)
+ continue;
+ if (map->offset <= offset
+ && (offset + size) <= (map->offset + map->size))
+ return map;
+ }
+ return NULL;
+}
+
+static void *agp_remap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
+{
+ unsigned long *phys_addr_map, i, num_pages =
+ PAGE_ALIGN(size) / PAGE_SIZE;
+ struct drm_agp_mem *agpmem;
+ struct page **page_map;
+ void *addr;
+
+ size = PAGE_ALIGN(size);
+
+#ifdef __alpha__
+ offset -= dev->hose->mem_space->start;
+#endif
+
+ for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+ if (agpmem->bound <= offset
+ && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
+ (offset + size))
+ break;
+ if (!agpmem)
+ return NULL;
+
+ /*
+ * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
+ * the CPU do not get remapped by the GART. We fix this by using the kernel's
+ * page-table instead (that's probably faster anyhow...).
+ */
+ /* note: use vmalloc() because num_pages could be large... */
+ page_map = vmalloc(num_pages * sizeof(struct page *));
+ if (!page_map)
+ return NULL;
+
+ phys_addr_map =
+ agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+ for (i = 0; i < num_pages; ++i)
+ page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+ addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+ vfree(page_map);
+
+ return addr;
+}
+
/** Wrapper around agp_allocate_memory() */
DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
{
@@ -103,5 +168,74 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
{
return drm_agp_unbind_memory(handle);
}
+
+#else /* __OS_HAS_AGP */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
+{
+ return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
+{
+ return NULL;
+}
+
#endif /* agp */
+
+void *drm_ioremap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
+{
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+ if (map && map->type == _DRM_AGP)
+ return agp_remap(offset, size, dev);
+ }
+ return ioremap(offset, size);
+}
+EXPORT_SYMBOL(drm_ioremap);
+
+#if 0
+void *drm_ioremap_nocache(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
+{
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+ if (map && map->type == _DRM_AGP)
+ return agp_remap(offset, size, dev);
+ }
+ return ioremap_nocache(offset, size);
+}
+#endif /* 0 */
+
+void drm_ioremapfree(void *pt, unsigned long size,
+ drm_device_t * dev)
+{
+ /*
+ * This is a bit ugly. It would be much cleaner if the DRM API would use separate
+ * routines for handling mappings in the AGP space. Hopefully this can be done in
+ * a future revision of the interface...
+ */
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
+ && ((unsigned long)pt >= VMALLOC_START
+ && (unsigned long)pt < VMALLOC_END)) {
+ unsigned long offset;
+ drm_map_t *map;
+
+ offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
+ map = drm_lookup_map(offset, size, dev);
+ if (map && map->type == _DRM_AGP) {
+ vunmap(pt);
+ return;
+ }
+ }
+
+ iounmap(pt);
+}
+EXPORT_SYMBOL(drm_ioremapfree);
+
#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
index 3732a61c3762..714d9aedcff5 100644
--- a/drivers/char/drm/drm_memory.h
+++ b/drivers/char/drm/drm_memory.h
@@ -57,71 +57,6 @@
# endif
#endif
-/*
- * Find the drm_map that covers the range [offset, offset+size).
- */
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
- unsigned long size, drm_device_t * dev)
-{
- struct list_head *list;
- drm_map_list_t *r_list;
- drm_map_t *map;
-
- list_for_each(list, &dev->maplist->head) {
- r_list = (drm_map_list_t *) list;
- map = r_list->map;
- if (!map)
- continue;
- if (map->offset <= offset
- && (offset + size) <= (map->offset + map->size))
- return map;
- }
- return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
-{
- unsigned long *phys_addr_map, i, num_pages =
- PAGE_ALIGN(size) / PAGE_SIZE;
- struct drm_agp_mem *agpmem;
- struct page **page_map;
- void *addr;
-
- size = PAGE_ALIGN(size);
-
-#ifdef __alpha__
- offset -= dev->hose->mem_space->start;
-#endif
-
- for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
- if (agpmem->bound <= offset
- && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
- (offset + size))
- break;
- if (!agpmem)
- return NULL;
-
- /*
- * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
- * the CPU do not get remapped by the GART. We fix this by using the kernel's
- * page-table instead (that's probably faster anyhow...).
- */
- /* note: use vmalloc() because num_pages could be large... */
- page_map = vmalloc(num_pages * sizeof(struct page *));
- if (!page_map)
- return NULL;
-
- phys_addr_map =
- agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
- for (i = 0; i < num_pages; ++i)
- page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
- addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
- vfree(page_map);
-
- return addr;
-}
-
static inline unsigned long drm_follow_page(void *vaddr)
{
pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
@@ -133,18 +68,6 @@ static inline unsigned long drm_follow_page(void *vaddr)
#else /* __OS_HAS_AGP */
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
- unsigned long size, drm_device_t * dev)
-{
- return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
-{
- return NULL;
-}
-
static inline unsigned long drm_follow_page(void *vaddr)
{
return 0;
@@ -152,51 +75,8 @@ static inline unsigned long drm_follow_page(void *vaddr)
#endif
-static inline void *drm_ioremap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
-{
- if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
- drm_map_t *map = drm_lookup_map(offset, size, dev);
-
- if (map && map->type == _DRM_AGP)
- return agp_remap(offset, size, dev);
- }
- return ioremap(offset, size);
-}
-
-static inline void *drm_ioremap_nocache(unsigned long offset,
- unsigned long size, drm_device_t * dev)
-{
- if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
- drm_map_t *map = drm_lookup_map(offset, size, dev);
-
- if (map && map->type == _DRM_AGP)
- return agp_remap(offset, size, dev);
- }
- return ioremap_nocache(offset, size);
-}
-
-static inline void drm_ioremapfree(void *pt, unsigned long size,
- drm_device_t * dev)
-{
- /*
- * This is a bit ugly. It would be much cleaner if the DRM API would use separate
- * routines for handling mappings in the AGP space. Hopefully this can be done in
- * a future revision of the interface...
- */
- if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
- && ((unsigned long)pt >= VMALLOC_START
- && (unsigned long)pt < VMALLOC_END)) {
- unsigned long offset;
- drm_map_t *map;
-
- offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
- map = drm_lookup_map(offset, size, dev);
- if (map && map->type == _DRM_AGP) {
- vunmap(pt);
- return;
- }
- }
+void *drm_ioremap(unsigned long offset, unsigned long size,
+ drm_device_t * dev);
- iounmap(pt);
-}
+void drm_ioremapfree(void *pt, unsigned long size,
+ drm_device_t * dev);
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 7868341817da..6543b9a14c42 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -229,6 +229,7 @@ void *drm_ioremap (unsigned long offset, unsigned long size,
return pt;
}
+#if 0
void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -251,6 +252,7 @@ void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
spin_unlock(&drm_mem_lock);
return pt;
}
+#endif /* 0 */
void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {
int alloc_count;
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index b28ca9cea8a2..86a0f1c22091 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -37,6 +37,7 @@
*/
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include "drmP.h"
/**********************************************************************/
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 68073e14fdec..9a842a36bb27 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -229,8 +229,6 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
return ret;
}
-EXPORT_SYMBOL(drm_get_dev);
-
/**
* Put a device minor number.
*
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index b108c7f913b2..26bdf2ca59d7 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -723,7 +723,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
dev_priv->scratch_ages[header.scratch.reg]++;
- ref_age_base = *(u32 **)cmdbuf->buf;
+ ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
cmdbuf->buf += sizeof(u64);
cmdbuf->bufsz -= sizeof(u64);
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 6152415644e9..c33d068cde19 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -196,9 +196,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
unsigned int cur_irq_sequence;
- drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ drm_via_irq_t *cur_irq;
int ret = 0;
- maskarray_t *masks = dev_priv->irq_masks;
+ maskarray_t *masks;
int real_irq;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -221,8 +221,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
__FUNCTION__, irq);
return DRM_ERR(EINVAL);
}
-
- cur_irq += real_irq;
+
+ masks = dev_priv->irq_masks;
+ cur_irq = dev_priv->via_irqs + real_irq;
if (masks[real_irq][2] && !force_sequence) {
DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
@@ -247,11 +248,12 @@ void via_driver_irq_preinstall(drm_device_t * dev)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
- drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ drm_via_irq_t *cur_irq;
int i;
DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
if (dev_priv) {
+ cur_irq = dev_priv->via_irqs;
dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index a229915ce1b2..87dcaa237f07 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -490,7 +490,7 @@ for (i = 0; i < 10; i++) \
release_region(dtlk_portlist[i], DTLK_IO_EXTENT);
}
- printk(KERN_INFO "\nDoubleTalk PC - not found\n");
+ printk(KERN_INFO "DoubleTalk PC - not found\n");
return -ENODEV;
}
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 327b00c3c45e..8d97b3911293 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -904,7 +904,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
* It is possible the vty-server was removed after the irq was
* requested but before we have time to enable interrupts.
*/
- if (vio_enable_interrupts(vdev) == H_Success)
+ if (vio_enable_interrupts(vdev) == H_SUCCESS)
return 0;
else {
printk(KERN_ERR "HVCS: int enable failed for"
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 58dcdee1cd71..0030cd8e2e95 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -165,7 +165,7 @@ static int bt_start_transaction(struct si_sm_data *bt,
{
unsigned int i;
- if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+ if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
return -1;
if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0ded046d5aa8..9f2f8fdec69a 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -941,6 +941,7 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
list_del(&msg->link);
list_add_tail(&msg->link, &msgs);
}
+ intf->waiting_events_count = 0;
}
/* Hold the events lock while doing this to preserve order. */
@@ -2916,6 +2917,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
copy_event_into_recv_msg(recv_msg, msg);
list_add_tail(&(recv_msg->link), &(intf->waiting_events));
+ intf->waiting_events_count++;
} else {
/* There's too many things in the queue, discard this
message. */
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a86c0f29953e..b36eef0e9d19 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2198,11 +2198,11 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
}
}
-static struct ipmi_default_vals
+static __devinitdata struct ipmi_default_vals
{
int type;
int port;
-} __devinit ipmi_defaults[] =
+} ipmi_defaults[] =
{
{ .type = SI_KCS, .port = 0xca2 },
{ .type = SI_SMIC, .port = 0xca9 },
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 66719f9d294c..1fa9fa157c12 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,6 +27,7 @@
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
+#include <linux/pipe_fs_i.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -578,6 +579,18 @@ static ssize_t write_null(struct file * file, const char __user * buf,
return count;
}
+static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf,
+ struct splice_desc *sd)
+{
+ return sd->len;
+}
+
+static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
+{
+ return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
+}
+
#ifdef CONFIG_MMU
/*
* For fun, we are using the MMU for this.
@@ -785,6 +798,7 @@ static struct file_operations null_fops = {
.llseek = null_lseek,
.read = read_null,
.write = write_null,
+ .splice_write = splice_write_null,
};
#if defined(CONFIG_ISA) || !defined(__mc68000__)
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 8666171e187b..d3ba2f860ef0 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -271,7 +271,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
- if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+ if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
PRINTK_ERROR(KERN_ERR_MWAVE
"mwavedd::mwave_ioctl:"
" IOCTL_MW_REGISTER_IPC:"
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 5fdf18515433..02114a0bd0d9 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -46,7 +46,7 @@
/* #define ATR_CSUM */
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
@@ -67,7 +67,7 @@ static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
#define T_100MSEC msecs_to_jiffies(100)
#define T_500MSEC msecs_to_jiffies(500)
-static void cm4000_release(dev_link_t *link);
+static void cm4000_release(struct pcmcia_device *link);
static int major; /* major number we get from the kernel */
@@ -106,7 +106,7 @@ static int major; /* major number we get from the kernel */
#define REG_STOPBITS(x) (x + 7)
struct cm4000_dev {
- dev_link_t link; /* pcmcia link */
+ struct pcmcia_device *p_dev;
dev_node_t node; /* OS node (major,minor) */
unsigned char atr[MAX_ATR];
@@ -149,14 +149,14 @@ struct cm4000_dev {
#define ZERO_DEV(dev) \
memset(&dev->atr_csum,0, \
sizeof(struct cm4000_dev) - \
- /*link*/ sizeof(dev_link_t) - \
+ /*link*/ sizeof(struct pcmcia_device) - \
/*node*/ sizeof(dev_node_t) - \
/*atr*/ MAX_ATR*sizeof(char) - \
/*rbuf*/ 512*sizeof(char) - \
/*sbuf*/ 512*sizeof(char) - \
/*queue*/ 4*sizeof(wait_queue_head_t))
-static dev_link_t *dev_table[CM4000_MAX_DEV];
+static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
static struct class *cmm_class;
/* This table doesn't use spaces after the comma between fields and thus
@@ -454,7 +454,7 @@ static struct card_fixup card_fixups[] = {
static void set_cardparameter(struct cm4000_dev *dev)
{
int i;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
u_int8_t stopbits = 0x02; /* ISO default */
DEBUGP(3, dev, "-> set_cardparameter\n");
@@ -487,7 +487,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
unsigned short num_bytes_read;
unsigned char pts_reply[4];
ssize_t rc;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
rc = 0;
@@ -699,7 +699,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
static void monitor_card(unsigned long p)
{
struct cm4000_dev *dev = (struct cm4000_dev *) p;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
unsigned short s;
struct ptsreq ptsreq;
int i, atrc;
@@ -962,7 +962,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
loff_t *ppos)
{
struct cm4000_dev *dev = filp->private_data;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
ssize_t rc;
int i, j, k;
@@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
if (count == 0) /* according to manpage */
return 0;
- if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */
+ if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
test_bit(IS_CMM_ABSENT, &dev->flags))
return -ENODEV;
@@ -1083,7 +1083,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
unsigned short s;
unsigned char tmp;
unsigned char infolen;
@@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;
- if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */
+ if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
test_bit(IS_CMM_ABSENT, &dev->flags))
return -ENODEV;
@@ -1440,8 +1440,8 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct cm4000_dev *dev = filp->private_data;
- ioaddr_t iobase = dev->link.io.BasePort1;
- dev_link_t *link;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ struct pcmcia_device *link;
int size;
int rc;
void __user *argp = (void __user *)arg;
@@ -1458,7 +1458,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
iminor(inode), ioctl_names[_IOC_NR(cmd)]);
link = dev_table[iminor(inode)];
- if (!(DEV_OK(link))) {
+ if (!pcmcia_dev_present(link)) {
DEBUGP(4, dev, "DEV_OK false\n");
return -ENODEV;
}
@@ -1660,14 +1660,14 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
static int cmm_open(struct inode *inode, struct file *filp)
{
struct cm4000_dev *dev;
- dev_link_t *link;
+ struct pcmcia_device *link;
int rc, minor = iminor(inode);
if (minor >= CM4000_MAX_DEV)
return -ENODEV;
link = dev_table[minor];
- if (link == NULL || !(DEV_OK(link)))
+ if (link == NULL || !pcmcia_dev_present(link))
return -ENODEV;
if (link->open)
@@ -1709,7 +1709,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
static int cmm_close(struct inode *inode, struct file *filp)
{
struct cm4000_dev *dev;
- dev_link_t *link;
+ struct pcmcia_device *link;
int minor = iminor(inode);
if (minor >= CM4000_MAX_DEV)
@@ -1735,7 +1735,7 @@ static int cmm_close(struct inode *inode, struct file *filp)
return 0;
}
-static void cmm_cm4000_release(dev_link_t * link)
+static void cmm_cm4000_release(struct pcmcia_device * link)
{
struct cm4000_dev *dev = link->priv;
@@ -1759,13 +1759,11 @@ static void cmm_cm4000_release(dev_link_t * link)
/*==== Interface to PCMCIA Layer =======================================*/
-static void cm4000_config(dev_link_t * link, int devno)
+static int cm4000_config(struct pcmcia_device * link, int devno)
{
- client_handle_t handle = link->handle;
struct cm4000_dev *dev;
tuple_t tuple;
cisparse_t parse;
- config_info_t conf;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
@@ -1777,41 +1775,34 @@ static void cm4000_config(dev_link_t * link, int devno)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
if ((fail_rc =
- pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) {
+ pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
- if ((fail_rc =
- pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) {
- fail_fn = GetConfigurationInfo;
- goto cs_failed;
- }
- link->state |= DEV_CONFIG;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- link->conf.Vcc = conf.Vcc;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(handle, &tuple);
- rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) {
+ for (rc = pcmcia_get_first_tuple(link, &tuple);
+ rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
- rc = pcmcia_get_tuple_data(handle, &tuple);
+ rc = pcmcia_get_tuple_data(link, &tuple);
if (rc != CS_SUCCESS)
continue;
- rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+ rc = pcmcia_parse_tuple(link, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
@@ -1831,7 +1822,7 @@ static void cm4000_config(dev_link_t * link, int devno)
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(handle, &link->io);
+ rc = pcmcia_request_io(link, &link->io);
if (rc == CS_SUCCESS)
break; /* we are done */
}
@@ -1841,7 +1832,7 @@ static void cm4000_config(dev_link_t * link, int devno)
link->conf.IntType = 00000002;
if ((fail_rc =
- pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) {
+ pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
fail_fn = RequestConfiguration;
goto cs_release;
}
@@ -1851,63 +1842,48 @@ static void cm4000_config(dev_link_t * link, int devno)
dev->node.major = major;
dev->node.minor = devno;
dev->node.next = NULL;
- link->dev = &dev->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &dev->node;
- return;
+ return 0;
cs_failed:
- cs_error(handle, fail_fn, fail_rc);
+ cs_error(link, fail_fn, fail_rc);
cs_release:
cm4000_release(link);
-
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
}
-static int cm4000_suspend(struct pcmcia_device *p_dev)
+static int cm4000_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
dev = link->priv;
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
stop_monitor(dev);
return 0;
}
-static int cm4000_resume(struct pcmcia_device *p_dev)
+static int cm4000_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
dev = link->priv;
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
if (link->open)
start_monitor(dev);
return 0;
}
-static void cm4000_release(dev_link_t *link)
+static void cm4000_release(struct pcmcia_device *link)
{
cmm_cm4000_release(link->priv); /* delay release until device closed */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
+ pcmcia_disable_device(link);
}
-static int cm4000_attach(struct pcmcia_device *p_dev)
+static int cm4000_probe(struct pcmcia_device *link)
{
struct cm4000_dev *dev;
- dev_link_t *link;
- int i;
+ int i, ret;
for (i = 0; i < CM4000_MAX_DEV; i++)
if (dev_table[i] == NULL)
@@ -1923,7 +1899,7 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
if (dev == NULL)
return -ENOMEM;
- link = &dev->link;
+ dev->p_dev = link;
link->priv = dev;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
@@ -1933,11 +1909,9 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
init_waitqueue_head(&dev->atrq);
init_waitqueue_head(&dev->readq);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- cm4000_config(link, i);
+ ret = cm4000_config(link, i);
+ if (ret)
+ return ret;
class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
"cmm%d", i);
@@ -1945,9 +1919,8 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
return 0;
}
-static void cm4000_detach(struct pcmcia_device *p_dev)
+static void cm4000_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev = link->priv;
int devno;
@@ -1958,11 +1931,9 @@ static void cm4000_detach(struct pcmcia_device *p_dev)
if (devno == CM4000_MAX_DEV)
return;
- link->state &= ~DEV_PRESENT;
stop_monitor(dev);
- if (link->state & DEV_CONFIG)
- cm4000_release(link);
+ cm4000_release(link);
dev_table[devno] = NULL;
kfree(dev);
@@ -1993,7 +1964,7 @@ static struct pcmcia_driver cm4000_driver = {
.drv = {
.name = "cm4000_cs",
},
- .probe = cm4000_attach,
+ .probe = cm4000_probe,
.remove = cm4000_detach,
.suspend = cm4000_suspend,
.resume = cm4000_resume,
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 466e33bab029..29efa64580a8 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -41,7 +41,7 @@
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
@@ -65,7 +65,7 @@ static char *version =
/* how often to poll for fifo status change */
#define POLL_PERIOD msecs_to_jiffies(10)
-static void reader_release(dev_link_t *link);
+static void reader_release(struct pcmcia_device *link);
static int major;
static struct class *cmx_class;
@@ -74,7 +74,7 @@ static struct class *cmx_class;
#define BS_WRITABLE 0x02
struct reader_dev {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
wait_queue_head_t devq;
wait_queue_head_t poll_wait;
@@ -87,7 +87,7 @@ struct reader_dev {
struct timer_list poll_timer;
};
-static dev_link_t *dev_table[CM_MAX_DEV];
+static struct pcmcia_device *dev_table[CM_MAX_DEV];
#ifndef PCMCIA_DEBUG
#define xoutb outb
@@ -116,7 +116,7 @@ static inline unsigned char xinb(unsigned short port)
static void cm4040_do_poll(unsigned long dummy)
{
struct reader_dev *dev = (struct reader_dev *) dummy;
- unsigned int obs = xinb(dev->link.io.BasePort1
+ unsigned int obs = xinb(dev->p_dev->io.BasePort1
+ REG_OFFSET_BUFFER_STATUS);
if ((obs & BSR_BULK_IN_FULL)) {
@@ -147,7 +147,7 @@ static void cm4040_stop_poll(struct reader_dev *dev)
static int wait_for_bulk_out_ready(struct reader_dev *dev)
{
int i, rc;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
for (i = 0; i < POLL_LOOP_COUNT; i++) {
if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -177,7 +177,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev)
/* Write to Sync Control Register */
static int write_sync_reg(unsigned char val, struct reader_dev *dev)
{
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
int rc;
rc = wait_for_bulk_out_ready(dev);
@@ -195,7 +195,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev)
static int wait_for_bulk_in_ready(struct reader_dev *dev)
{
int i, rc;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
for (i = 0; i < POLL_LOOP_COUNT; i++) {
if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -225,7 +225,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
struct reader_dev *dev = filp->private_data;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
size_t bytes_to_read;
unsigned long i;
size_t min_bytes_to_read;
@@ -246,7 +246,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
return -EAGAIN;
}
- if ((dev->link.state & DEV_PRESENT)==0)
+ if (!pcmcia_dev_present(dev->p_dev))
return -ENODEV;
for (i = 0; i < 5; i++) {
@@ -328,7 +328,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
struct reader_dev *dev = filp->private_data;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
ssize_t rc;
int i;
unsigned int bytes_to_write;
@@ -351,7 +351,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
return -EAGAIN;
}
- if ((dev->link.state & DEV_PRESENT) == 0)
+ if (!pcmcia_dev_present(dev->p_dev))
return -ENODEV;
bytes_to_write = count;
@@ -445,14 +445,14 @@ static unsigned int cm4040_poll(struct file *filp, poll_table *wait)
static int cm4040_open(struct inode *inode, struct file *filp)
{
struct reader_dev *dev;
- dev_link_t *link;
+ struct pcmcia_device *link;
int minor = iminor(inode);
if (minor >= CM_MAX_DEV)
return -ENODEV;
link = dev_table[minor];
- if (link == NULL || !(DEV_OK(link)))
+ if (link == NULL || !pcmcia_dev_present(link))
return -ENODEV;
if (link->open)
@@ -478,7 +478,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
static int cm4040_close(struct inode *inode, struct file *filp)
{
struct reader_dev *dev = filp->private_data;
- dev_link_t *link;
+ struct pcmcia_device *link;
int minor = iminor(inode);
DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode),
@@ -500,7 +500,7 @@ static int cm4040_close(struct inode *inode, struct file *filp)
return 0;
}
-static void cm4040_reader_release(dev_link_t *link)
+static void cm4040_reader_release(struct pcmcia_device *link)
{
struct reader_dev *dev = link->priv;
@@ -514,60 +514,49 @@ static void cm4040_reader_release(dev_link_t *link)
return;
}
-static void reader_config(dev_link_t *link, int devno)
+static int reader_config(struct pcmcia_device *link, int devno)
{
- client_handle_t handle;
struct reader_dev *dev;
tuple_t tuple;
cisparse_t parse;
- config_info_t conf;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
- handle = link->handle;
-
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
- if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse))
+ if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse))
!= CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_configuration_info(handle, &conf))
- != CS_SUCCESS) {
- fail_fn = GetConfigurationInfo;
- goto cs_failed;
- }
- link->state |= DEV_CONFIG;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- link->conf.Vcc = conf.Vcc;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(handle, &tuple);
+ for (rc = pcmcia_get_first_tuple(link, &tuple);
rc == CS_SUCCESS;
- rc = pcmcia_get_next_tuple(handle, &tuple)) {
- rc = pcmcia_get_tuple_data(handle, &tuple);
+ rc = pcmcia_get_next_tuple(link, &tuple)) {
+ rc = pcmcia_get_tuple_data(link, &tuple);
if (rc != CS_SUCCESS)
continue;
- rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+ rc = pcmcia_parse_tuple(link, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
@@ -585,13 +574,13 @@ static void reader_config(dev_link_t *link, int devno)
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(handle, &link->io);
+ rc = pcmcia_request_io(link, &link->io);
- dev_printk(KERN_INFO, &handle_to_dev(handle), "foo");
+ dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
if (rc == CS_SUCCESS)
break;
else
- dev_printk(KERN_INFO, &handle_to_dev(handle),
+ dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_io failed 0x%x\n", rc);
}
if (rc != CS_SUCCESS)
@@ -599,10 +588,10 @@ static void reader_config(dev_link_t *link, int devno)
link->conf.IntType = 00000002;
- if ((fail_rc = pcmcia_request_configuration(handle,&link->conf))
+ if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
!=CS_SUCCESS) {
fail_fn = RequestConfiguration;
- dev_printk(KERN_INFO, &handle_to_dev(handle),
+ dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_configuration failed 0x%x\n",
fail_rc);
goto cs_release;
@@ -612,57 +601,31 @@ static void reader_config(dev_link_t *link, int devno)
sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
dev->node.major = major;
dev->node.minor = devno;
- dev->node.next = NULL;
- link->dev = &dev->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ dev->node.next = &dev->node;
DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno,
link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1);
DEBUGP(2, dev, "<- reader_config (succ)\n");
- return;
+ return 0;
cs_failed:
- cs_error(handle, fail_fn, fail_rc);
+ cs_error(link, fail_fn, fail_rc);
cs_release:
reader_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
-}
-
-static int reader_suspend(struct pcmcia_device *p_dev)
-{
- dev_link_t *link = dev_to_instance(p_dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
+ return -ENODEV;
}
-static int reader_resume(struct pcmcia_device *p_dev)
-{
- dev_link_t *link = dev_to_instance(p_dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
-static void reader_release(dev_link_t *link)
+static void reader_release(struct pcmcia_device *link)
{
cm4040_reader_release(link->priv);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
+ pcmcia_disable_device(link);
}
-static int reader_attach(struct pcmcia_device *p_dev)
+static int reader_probe(struct pcmcia_device *link)
{
struct reader_dev *dev;
- dev_link_t *link;
- int i;
+ int i, ret;
for (i = 0; i < CM_MAX_DEV; i++) {
if (dev_table[i] == NULL)
@@ -679,8 +642,8 @@ static int reader_attach(struct pcmcia_device *p_dev)
dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
dev->buffer_status = 0;
- link = &dev->link;
link->priv = dev;
+ dev->p_dev = link;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
@@ -692,11 +655,9 @@ static int reader_attach(struct pcmcia_device *p_dev)
init_timer(&dev->poll_timer);
dev->poll_timer.function = &cm4040_do_poll;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- reader_config(link, i);
+ ret = reader_config(link, i);
+ if (ret)
+ return ret;
class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
"cmx%d", i);
@@ -704,9 +665,8 @@ static int reader_attach(struct pcmcia_device *p_dev)
return 0;
}
-static void reader_detach(struct pcmcia_device *p_dev)
+static void reader_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct reader_dev *dev = link->priv;
int devno;
@@ -718,10 +678,7 @@ static void reader_detach(struct pcmcia_device *p_dev)
if (devno == CM_MAX_DEV)
return;
- link->state &= ~DEV_PRESENT;
-
- if (link->state & DEV_CONFIG)
- reader_release(link);
+ reader_release(link);
dev_table[devno] = NULL;
kfree(dev);
@@ -753,10 +710,8 @@ static struct pcmcia_driver reader_driver = {
.drv = {
.name = "cm4040_cs",
},
- .probe = reader_attach,
+ .probe = reader_probe,
.remove = reader_detach,
- .suspend = reader_suspend,
- .resume = reader_resume,
.id_table = cm4040_ids,
};
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index e6b714b6390d..07213454c458 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -228,7 +228,7 @@ typedef struct _mgslpc_info {
struct _input_signal_events input_signal_events;
/* PCMCIA support */
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int stop;
@@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
/* PCMCIA prototypes */
-static void mgslpc_config(dev_link_t *link);
+static int mgslpc_config(struct pcmcia_device *link);
static void mgslpc_release(u_long arg);
static void mgslpc_detach(struct pcmcia_device *p_dev);
@@ -533,14 +533,14 @@ static void ldisc_receive_buf(struct tty_struct *tty,
}
}
-static int mgslpc_attach(struct pcmcia_device *p_dev)
+static int mgslpc_probe(struct pcmcia_device *link)
{
MGSLPC_INFO *info;
- dev_link_t *link;
-
+ int ret;
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_attach\n");
-
+
info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
if (!info) {
printk("Error can't allocate device instance data\n");
@@ -565,25 +565,22 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
info->imrb_value = 0xffff;
info->pim_value = 0xff;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
-
- /* Initialize the dev_link_t structure */
+
+ /* Initialize the struct pcmcia_device structure */
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
-
+
link->conf.Attributes = 0;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- mgslpc_config(link);
+ ret = mgslpc_config(link);
+ if (ret)
+ return ret;
mgslpc_add_device(info);
@@ -596,15 +593,13 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void mgslpc_config(dev_link_t *link)
+static int mgslpc_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
MGSLPC_INFO *info = link->priv;
tuple_t tuple;
cisparse_t parse;
int last_fn, last_ret;
u_char buf[64];
- config_info_t conf;
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg;
@@ -617,27 +612,20 @@ static void mgslpc_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
/* get CIS configuration entry */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
cfg = &(parse.cftable_entry);
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
if (cfg->index == 0)
@@ -658,11 +646,10 @@ static void mgslpc_config(dev_link_t *link)
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
- CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 8;
link->conf.Present = PRESENT_OPTION;
@@ -670,9 +657,9 @@ static void mgslpc_config(dev_link_t *link)
link->irq.Attributes |= IRQ_HANDLE_PRESENT;
link->irq.Handler = mgslpc_isr;
link->irq.Instance = info;
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
info->io_base = link->io.BasePort1;
info->irq_level = link->irq.AssignedIRQ;
@@ -680,7 +667,7 @@ static void mgslpc_config(dev_link_t *link)
/* add to linked list of devices */
sprintf(info->node.dev_name, "mgslpc0");
info->node.major = info->node.minor = 0;
- link->dev = &info->node;
+ link->dev_node = &info->node;
printk(KERN_INFO "%s: index 0x%02x:",
info->node.dev_name, link->conf.ConfigIndex);
@@ -690,13 +677,12 @@ static void mgslpc_config(dev_link_t *link)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
mgslpc_release((u_long)link);
+ return -ENODEV;
}
/* Card has been removed.
@@ -705,58 +691,38 @@ cs_failed:
*/
static void mgslpc_release(u_long arg)
{
- dev_link_t *link = (dev_link_t *)arg;
+ struct pcmcia_device *link = (struct pcmcia_device *)arg;
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_release(0x%p)\n", link);
-
- /* Unlink the device chain */
- link->dev = NULL;
- link->state &= ~DEV_CONFIG;
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("mgslpc_release(0x%p)\n", link);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
+ pcmcia_disable_device(link);
}
-static void mgslpc_detach(struct pcmcia_device *p_dev)
+static void mgslpc_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_detach(0x%p)\n", link);
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("mgslpc_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG) {
- ((MGSLPC_INFO *)link->priv)->stop = 1;
- mgslpc_release((u_long)link);
- }
+ ((MGSLPC_INFO *)link->priv)->stop = 1;
+ mgslpc_release((u_long)link);
- mgslpc_remove_device((MGSLPC_INFO *)link->priv);
+ mgslpc_remove_device((MGSLPC_INFO *)link->priv);
}
-static int mgslpc_suspend(struct pcmcia_device *dev)
+static int mgslpc_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
MGSLPC_INFO *info = link->priv;
- link->state |= DEV_SUSPEND;
info->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int mgslpc_resume(struct pcmcia_device *dev)
+static int mgslpc_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
MGSLPC_INFO *info = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
info->stop = 0;
return 0;
@@ -1280,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs)
if (!info)
return IRQ_NONE;
- if (!(info->link.state & DEV_CONFIG))
+ if (!(info->p_dev->_locked))
return IRQ_HANDLED;
spin_lock(&info->lock);
@@ -3033,7 +2999,7 @@ static struct pcmcia_driver mgslpc_driver = {
.drv = {
.name = "synclink_cs",
},
- .probe = mgslpc_attach,
+ .probe = mgslpc_probe,
.remove = mgslpc_detach,
.id_table = mgslpc_ids,
.suspend = mgslpc_suspend,
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 86be04b241e1..58f3512c52e1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo
return twothirdsMD4Transform(daddr, hash);
}
-EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index b543821d8cb4..56c8243cdb73 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -390,7 +390,8 @@ scdrv_init(void)
format_module_id(devnamep, geo_module(geoid),
MODULE_FORMAT_BRIEF);
devnamep = devname + strlen(devname);
- sprintf(devnamep, "#%d", geo_slab(geoid));
+ sprintf(devnamep, "^%d#%d", geo_slot(geoid),
+ geo_slab(geoid));
/* allocate sysctl device data */
scd = kzalloc(sizeof (struct sysctl_data_s),
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index f8dd8527c6aa..a90f5d97df35 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1341,6 +1341,9 @@ static int __devinit sonypi_probe(struct platform_device *dev)
else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+ else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
else
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index eb2eb3e12d6a..079db5a935a1 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -515,7 +515,7 @@ tipar_init_module(void)
err = PTR_ERR(tipar_class);
goto out_chrdev;
}
- if (parport_register_driver(&tipar_driver) || tp_count == 0) {
+ if (parport_register_driver(&tipar_driver)) {
printk(KERN_ERR "tipar: unable to register with parport\n");
err = -EIO;
goto out_class;
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 2546637a55c0..f58ad7f68267 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -327,7 +327,7 @@ static ssize_t store_received_ref_clk3a(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
store_received_ref_clk3a);
@@ -349,7 +349,7 @@ static ssize_t store_received_ref_clk3b(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
store_received_ref_clk3b);
@@ -371,7 +371,7 @@ static ssize_t store_enable_clk3b_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clk3b_output);
static ssize_t store_enable_clk3a_output(struct device *d,
@@ -392,7 +392,7 @@ static ssize_t store_enable_clk3a_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clk3a_output);
static ssize_t store_enable_clkb1_output(struct device *d,
@@ -413,7 +413,7 @@ static ssize_t store_enable_clkb1_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clkb1_output);
@@ -435,7 +435,7 @@ static ssize_t store_enable_clka1_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clka1_output);
static ssize_t store_enable_clkb0_output(struct device *d,
@@ -456,7 +456,7 @@ static ssize_t store_enable_clkb0_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clkb0_output);
static ssize_t store_enable_clka0_output(struct device *d,
@@ -477,7 +477,7 @@ static ssize_t store_enable_clka0_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clka0_output);
static ssize_t store_select_amcb2_transmit_clock(struct device *d,
@@ -519,7 +519,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
store_select_amcb2_transmit_clock);
static ssize_t store_select_amcb1_transmit_clock(struct device *d,
@@ -560,7 +560,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
store_select_amcb1_transmit_clock);
static ssize_t store_select_redundant_clock(struct device *d,
@@ -581,7 +581,7 @@ static ssize_t store_select_redundant_clock(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
store_select_redundant_clock);
static ssize_t store_select_ref_frequency(struct device *d,
@@ -602,7 +602,7 @@ static ssize_t store_select_ref_frequency(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL,
+static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
store_select_ref_frequency);
static ssize_t store_filter_select(struct device *d,
@@ -623,7 +623,7 @@ static ssize_t store_filter_select(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select);
+static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
static ssize_t store_hardware_switching_mode(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
@@ -643,7 +643,7 @@ static ssize_t store_hardware_switching_mode(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL,
+static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
store_hardware_switching_mode);
static ssize_t store_hardware_switching(struct device *d,
@@ -664,7 +664,7 @@ static ssize_t store_hardware_switching(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL,
+static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
store_hardware_switching);
static ssize_t store_refalign (struct device *d,
@@ -684,7 +684,7 @@ static ssize_t store_refalign (struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign);
+static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
static ssize_t store_mode_select (struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
@@ -704,7 +704,7 @@ static ssize_t store_mode_select (struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select);
+static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
static ssize_t store_reset (struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
@@ -724,7 +724,7 @@ static ssize_t store_reset (struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
+static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
static struct attribute *tlclk_sysfs_entries[] = {
&dev_attr_current_ref.attr,
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a6873bf89ffa..1efde3b27619 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -20,9 +20,18 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
+config TCG_TIS
+ tristate "TPM Interface Specification 1.2 Interface"
+ depends on TCG_TPM
+ ---help---
+ If you have a TPM security chip that is compliant with the
+ TCG TIS 1.2 TPM specification say Yes and it will be accessible
+ from within Linux. To compile this driver as a module, choose
+ M here; the module will be called tpm_tis.
+
config TCG_NSC
tristate "National Semiconductor TPM Interface"
- depends on TCG_TPM
+ depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from National Semicondutor
say Yes and it will be accessible from within Linux. To
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index ba4582d160fd..ea3a1e02a824 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_TCG_TPM) += tpm.o
ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
endif
+obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 5a3870477ef1..6889e7db3aff 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -32,12 +32,291 @@ enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 2048,
TPM_NUM_DEVICES = 256,
- TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
};
+enum tpm_duration {
+ TPM_SHORT = 0,
+ TPM_MEDIUM = 1,
+ TPM_LONG = 2,
+ TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[TPM_NUM_MASK_ENTRIES];
+static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result. The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_LONG,
+ TPM_MEDIUM, /* 15 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT, /* 20 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT, /* 25 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 30 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 35 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 40 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 45 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_MEDIUM, /* 50 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 55 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 60 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 65 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 70 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 75 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 80 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 85 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 90 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 95 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 100 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 105 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 110 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 115 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 120 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 125 */
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 130 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 135 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 140 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 145 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 150 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 155 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 160 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 165 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 170 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 175 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 180 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM, /* 185 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 190 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 195 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 200 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 205 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 210 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 215 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 220 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 225 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 230 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 235 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 240 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+};
static void user_reader_timeout(unsigned long ptr)
{
@@ -46,7 +325,7 @@ static void user_reader_timeout(unsigned long ptr)
schedule_work(&chip->work);
}
-static void timeout_work(void * ptr)
+static void timeout_work(void *ptr)
{
struct tpm_chip *chip = ptr;
@@ -57,17 +336,43 @@ static void timeout_work(void * ptr)
}
/*
+ * Returns max number of jiffies to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+ u32 ordinal)
+{
+ int duration_idx = TPM_UNDEFINED;
+ int duration = 0;
+
+ if (ordinal < TPM_MAX_ORDINAL)
+ duration_idx = tpm_ordinal_duration[ordinal];
+ else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+ TPM_MAX_PROTECTED_ORDINAL)
+ duration_idx =
+ tpm_protected_ordinal_duration[ordinal &
+ TPM_PROTECTED_ORDINAL_MASK];
+
+ if (duration_idx != TPM_UNDEFINED)
+ duration = chip->vendor.duration[duration_idx];
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
+
+/*
* Internal kernel interface to transmit TPM commands
*/
static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
ssize_t rc;
- u32 count;
+ u32 count, ordinal;
unsigned long stop;
count = be32_to_cpu(*((__be32 *) (buf + 2)));
-
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
@@ -78,21 +383,23 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
down(&chip->tpm_mutex);
- if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
dev_err(chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
- stop = jiffies + 2 * 60 * HZ;
+ if (chip->vendor.irq)
+ goto out_recv;
+
+ stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
- u8 status = chip->vendor->status(chip);
- if ((status & chip->vendor->req_complete_mask) ==
- chip->vendor->req_complete_val) {
+ u8 status = chip->vendor.status(chip);
+ if ((status & chip->vendor.req_complete_mask) ==
+ chip->vendor.req_complete_val)
goto out_recv;
- }
- if ((status == chip->vendor->req_canceled)) {
+ if ((status == chip->vendor.req_canceled)) {
dev_err(chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
@@ -102,14 +409,13 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
rmb();
} while (time_before(jiffies, stop));
-
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
dev_err(chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
- rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
dev_err(chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
@@ -119,17 +425,247 @@ out:
}
#define TPM_DIGEST_SIZE 20
-#define CAP_PCR_RESULT_SIZE 18
-static const u8 cap_pcr[] = {
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+#define TPM_GET_CAP_RET_SIZE_IDX 10
+#define TPM_GET_CAP_RET_UINT32_1_IDX 14
+#define TPM_GET_CAP_RET_UINT32_2_IDX 18
+#define TPM_GET_CAP_RET_UINT32_3_IDX 22
+#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TPM_CAP_IDX 13
+#define TPM_CAP_SUBCAP_IDX 21
+
+enum tpm_capabilities {
+ TPM_CAP_FLAG = 4,
+ TPM_CAP_PROP = 5,
+};
+
+enum tpm_sub_capabilities {
+ TPM_CAP_PROP_PCR = 0x1,
+ TPM_CAP_PROP_MANUFACTURER = 0x3,
+ TPM_CAP_FLAG_PERM = 0x8,
+ TPM_CAP_FLAG_VOL = 0x9,
+ TPM_CAP_PROP_OWNER = 0x11,
+ TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+ TPM_CAP_PROP_TIS_DURATION = 0x20,
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tpm_cap[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 1
+ 0, 0, 0, 0, /* TPM_CAP_<TYPE> */
+ 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */
+ 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */
};
-#define READ_PCR_RESULT_SIZE 30
+static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
+ char *desc)
+{
+ int err;
+
+ len = tpm_transmit(chip, data, len);
+ if (len < 0)
+ return len;
+ if (len == TPM_ERROR_SIZE) {
+ err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+ dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+ ssize_t rc;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+ ssize_t rc;
+ u32 timeout;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+ if (rc)
+ goto duration;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the durations");
+ if (rc)
+ return;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TPM_SHORT] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_1_IDX))));
+ chip->vendor.duration[TPM_MEDIUM] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_2_IDX))));
+ chip->vendor.duration[TPM_LONG] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+void tpm_continue_selftest(struct tpm_chip *chip)
+{
+ u8 data[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* length */
+ 0, 0, 0, 83, /* TPM_ORD_GetCapability */
+ };
+
+ tpm_transmit(chip, data, sizeof(data));
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_enabled);
+
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_active);
+
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the owner state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_owned);
+
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the temporary state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
+
static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
@@ -140,8 +676,8 @@ static const u8 pcrread[] = {
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[READ_PCR_RESULT_SIZE];
- ssize_t len;
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
+ ssize_t rc;
int i, j, num_pcrs;
__be32 index;
char *str = buf;
@@ -150,29 +686,24 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_pcr, sizeof(cap_pcr));
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to determine the number of PCRS\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the number of PCRS");
+ if (rc)
return 0;
- }
num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
-
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE){
- dev_dbg(chip->dev, "A TPM error (%d) occurred"
- " attempting to read PCR %d of %d\n",
- be32_to_cpu(*((__be32 *) (data + 6))),
- i, num_pcrs);
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read a PCR");
+ if (rc)
goto out;
- }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -194,7 +725,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
char *buf)
{
u8 *data;
- ssize_t len;
+ ssize_t err;
int i, rc;
char *str = buf;
@@ -208,14 +739,10 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
memcpy(data, readpubek, sizeof(readpubek));
- if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
- READ_PUBEK_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to read the PUBEK\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
- rc = 0;
+ err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+ "attempting to read the PUBEK");
+ if (err)
goto out;
- }
/*
ignore header 10 bytes
@@ -245,67 +772,110 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
- rc = str - buf;
out:
+ rc = str - buf;
kfree(data);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_show_pubek);
-#define CAP_VER_RESULT_SIZE 18
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 18, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 6,
+ 0, 0, 0, 0,
0, 0, 0, 0
};
-#define CAP_MANUFACTURER_RESULT_SIZE 18
-static const u8 cap_manufacturer[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 22, /* length */
- 0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 3
-};
-
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[sizeof(cap_manufacturer)];
- ssize_t len;
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+ ssize_t rc;
char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_MANUFACTURER_RESULT_SIZE)
- return len;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*((__be32 *) (data + 14))));
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the 1.1 version");
+ if (rc)
+ goto out;
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_VER_RESULT_SIZE)
- return len;
-
- str +=
- sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
- (int) data[14], (int) data[15], (int) data[16],
- (int) data[17]);
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+out:
return str - buf;
}
EXPORT_SYMBOL_GPL(tpm_show_caps);
+ssize_t tpm_show_caps_1_2(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the manufacturer\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ return 0;
+ }
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_err(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the 1.2 version\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto out;
+ }
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[16], (int) data[17], (int) data[18],
+ (int) data[19]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
+
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -313,7 +883,7 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
if (chip == NULL)
return 0;
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
return count;
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
@@ -329,7 +899,7 @@ int tpm_open(struct inode *inode, struct file *file)
spin_lock(&driver_lock);
list_for_each_entry(pos, &tpm_chip_list, list) {
- if (pos->vendor->miscdev.minor == minor) {
+ if (pos->vendor.miscdev.minor == minor) {
chip = pos;
break;
}
@@ -387,7 +957,7 @@ int tpm_release(struct inode *inode, struct file *file)
EXPORT_SYMBOL_GPL(tpm_release);
ssize_t tpm_write(struct file *file, const char __user *buf,
- size_t size, loff_t * off)
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int in_size = size, out_size;
@@ -419,11 +989,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
return in_size;
}
-
EXPORT_SYMBOL_GPL(tpm_write);
-ssize_t tpm_read(struct file * file, char __user *buf,
- size_t size, loff_t * off)
+ssize_t tpm_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int ret_size;
@@ -462,14 +1031,13 @@ void tpm_remove_hardware(struct device *dev)
spin_unlock(&driver_lock);
dev_set_drvdata(dev, NULL);
- misc_deregister(&chip->vendor->miscdev);
- kfree(chip->vendor->miscdev.name);
+ misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
- sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
- dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
- ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+ clear_bit(chip->dev_num, dev_mask);
kfree(chip);
@@ -520,18 +1088,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
-int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
+ *entry)
{
#define DEVNAME_SIZE 7
char *devname;
struct tpm_chip *chip;
- int i, j;
/* Driver specific per-device data */
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
- return -ENOMEM;
+ return NULL;
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
@@ -543,45 +1111,37 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
chip->user_read_timer.function = user_reader_timeout;
chip->user_read_timer.data = (unsigned long) chip;
- chip->vendor = entry;
-
- chip->dev_num = -1;
+ memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
- for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
- for (j = 0; j < 8 * sizeof(int); j++)
- if ((dev_mask[i] & (1 << j)) == 0) {
- chip->dev_num =
- i * TPM_NUM_MASK_ENTRIES + j;
- dev_mask[i] |= 1 << j;
- goto dev_num_search_complete;
- }
+ chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
-dev_num_search_complete:
- if (chip->dev_num < 0) {
+ if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
- return -ENODEV;
+ return NULL;
} else if (chip->dev_num == 0)
- chip->vendor->miscdev.minor = TPM_MINOR;
+ chip->vendor.miscdev.minor = TPM_MINOR;
else
- chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ set_bit(chip->dev_num, dev_mask);
devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
- chip->vendor->miscdev.name = devname;
+ chip->vendor.miscdev.name = devname;
- chip->vendor->miscdev.dev = dev;
+ chip->vendor.miscdev.dev = dev;
chip->dev = get_device(dev);
- if (misc_register(&chip->vendor->miscdev)) {
+ if (misc_register(&chip->vendor.miscdev)) {
dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
- chip->vendor->miscdev.name,
- chip->vendor->miscdev.minor);
+ chip->vendor.miscdev.name,
+ chip->vendor.miscdev.minor);
put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
kfree(chip);
- dev_mask[i] &= !(1 << j);
- return -ENODEV;
+ return NULL;
}
spin_lock(&driver_lock);
@@ -592,11 +1152,11 @@ dev_num_search_complete:
spin_unlock(&driver_lock);
- sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
chip->bios_dir = tpm_bios_log_setup(devname);
- return 0;
+ return chip;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index dec0224b4478..54a4c804e25f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -42,18 +42,30 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+ char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
+extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_temp_deactivated(struct device *,
+ struct device_attribute *attr, char *);
struct tpm_chip;
struct tpm_vendor_specific {
- u8 req_complete_mask;
- u8 req_complete_val;
- u8 req_canceled;
+ const u8 req_complete_mask;
+ const u8 req_complete_val;
+ const u8 req_canceled;
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
+ int irq;
+
int region_size;
int have_region;
@@ -63,6 +75,13 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ struct list_head list;
+ int locality;
+ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+ unsigned long duration[3]; /* jiffies */
+
+ wait_queue_head_t read_queue;
+ wait_queue_head_t int_queue;
};
struct tpm_chip {
@@ -81,13 +100,15 @@ struct tpm_chip {
struct work_struct work;
struct semaphore tpm_mutex; /* tpm is processing */
- struct tpm_vendor_specific *vendor;
+ struct tpm_vendor_specific vendor;
struct dentry **bios_dir;
struct list_head list;
};
+#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
@@ -100,8 +121,12 @@ static inline void tpm_write_index(int base, int index, int value)
outb(value & 0xFF, base+1);
}
-extern int tpm_register_hardware(struct device *,
- struct tpm_vendor_specific *);
+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
+extern void tpm_continue_selftest(struct tpm_chip *);
+extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
+extern struct tpm_chip* tpm_register_hardware(struct device *,
+ const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index ff3654964fe3..58a258cec153 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -EIO;
for (i = 0; i < 6; i++) {
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading header\n");
return -EIO;
}
- *buf++ = ioread8(chip->vendor->iobase);
+ *buf++ = ioread8(chip->vendor.iobase);
}
/* size of the data received */
@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
dev_err(chip->dev,
"Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n");
return -EIO;
@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read all the data available */
for (; i < size; i++) {
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n");
return -EIO;
}
- *buf++ = ioread8(chip->vendor->iobase);
+ *buf++ = ioread8(chip->vendor.iobase);
}
/* make sure data available is gone */
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) {
dev_err(chip->dev, "data available is stuck\n");
@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
dev_dbg(chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) {
dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
- iowrite8(buf[i], chip->vendor->iobase);
+ iowrite8(buf[i], chip->vendor.iobase);
}
return count;
@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
static void tpm_atml_cancel(struct tpm_chip *chip)
{
- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
+ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
}
static u8 tpm_atml_status(struct tpm_chip *chip)
{
- return ioread8(chip->vendor->iobase + 1);
+ return ioread8(chip->vendor.iobase + 1);
}
static struct file_operations atmel_ops = {
@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = {
static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
-static struct tpm_vendor_specific tpm_atmel = {
+static const struct tpm_vendor_specific tpm_atmel = {
.recv = tpm_atml_recv,
.send = tpm_atml_send,
.cancel = tpm_atml_cancel,
@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
if (chip) {
- if (chip->vendor->have_region)
- atmel_release_region(chip->vendor->base,
- chip->vendor->region_size);
- atmel_put_base_addr(chip->vendor);
+ if (chip->vendor.have_region)
+ atmel_release_region(chip->vendor.base,
+ chip->vendor.region_size);
+ atmel_put_base_addr(chip->vendor.iobase);
tpm_remove_hardware(chip->dev);
platform_device_unregister(pdev);
}
@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
static int __init init_atmel(void)
{
int rc = 0;
+ void __iomem *iobase = NULL;
+ int have_region, region_size;
+ unsigned long base;
+ struct tpm_chip *chip;
driver_register(&atml_drv);
- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
+ if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
rc = -ENODEV;
goto err_unreg_drv;
}
- tpm_atmel.have_region =
+ have_region =
(atmel_request_region
- (tpm_atmel.base, tpm_atmel.region_size,
- "tpm_atmel0") == NULL) ? 0 : 1;
+ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
+
if (IS_ERR
(pdev =
@@ -199,17 +203,25 @@ static int __init init_atmel(void)
goto err_rel_reg;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
+ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
+ rc = -ENODEV;
goto err_unreg_dev;
+ }
+
+ chip->vendor.iobase = iobase;
+ chip->vendor.base = base;
+ chip->vendor.have_region = have_region;
+ chip->vendor.region_size = region_size;
+
return 0;
err_unreg_dev:
platform_device_unregister(pdev);
err_rel_reg:
- atmel_put_base_addr(&tpm_atmel);
- if (tpm_atmel.have_region)
- atmel_release_region(tpm_atmel.base,
- tpm_atmel.region_size);
+ atmel_put_base_addr(iobase);
+ if (have_region)
+ atmel_release_region(base,
+ region_size);
err_unreg_drv:
driver_unregister(&atml_drv);
return rc;
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h
index d3478aaadd77..2e68eeb8a2cd 100644
--- a/drivers/char/tpm/tpm_atmel.h
+++ b/drivers/char/tpm/tpm_atmel.h
@@ -28,13 +28,12 @@
#define atmel_request_region request_mem_region
#define atmel_release_region release_mem_region
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
- *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
{
- iounmap(vendor->iobase);
+ iounmap(iobase);
}
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
struct device_node *dn;
unsigned long address, size;
@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
else
size = reg[naddrc];
- vendor->base = address;
- vendor->region_size = size;
- return ioremap(vendor->base, vendor->region_size);
+ *base = address;
+ *region_size = size;
+ return ioremap(*base, *region_size);
}
#else
#define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
return 0;
}
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
- *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
{
}
/* Determine where to talk to device */
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
- *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
int lo, hi;
@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
- vendor->base = (hi << 8) | lo;
- vendor->region_size = 2;
+ *base = (hi << 8) | lo;
+ *region_size = 2;
- return ioport_map(vendor->base, vendor->region_size);
+ return ioport_map(*base, *region_size);
}
#endif
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 537aa45d8c67..e45f0d3d12de 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -29,6 +29,11 @@
#define MAX_TEXT_EVENT 1000 /* Max event string length */
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
+enum bios_platform_class {
+ BIOS_CLIENT = 0x00,
+ BIOS_SERVER = 0x01,
+};
+
struct tpm_bios_log {
void *bios_event_log;
void *bios_event_log_end;
@@ -36,9 +41,18 @@ struct tpm_bios_log {
struct acpi_tcpa {
struct acpi_table_header hdr;
- u16 reserved;
- u32 log_max_len __attribute__ ((packed));
- u32 log_start_addr __attribute__ ((packed));
+ u16 platform_class;
+ union {
+ struct client_hdr {
+ u32 log_max_len __attribute__ ((packed));
+ u64 log_start_addr __attribute__ ((packed));
+ } client;
+ struct server_hdr {
+ u16 reserved;
+ u64 log_max_len __attribute__ ((packed));
+ u64 log_start_addr __attribute__ ((packed));
+ } server;
+ };
};
struct tcpa_event {
@@ -120,6 +134,7 @@ static const char* tcpa_pc_event_id_strings[] = {
"S-CRTM Version",
"S-CRTM Contents",
"S-CRTM POST Contents",
+ "POST Contents",
};
/* returns pointer to start of pos. entry of tcg log */
@@ -306,6 +321,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
/* 5th: delimiter */
seq_putc(m, '\0');
+ kfree(eventname);
return 0;
}
@@ -353,6 +369,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
/* 4th: eventname <= max + \'0' delimiter */
seq_printf(m, " %s\n", eventname);
+ kfree(eventname);
return 0;
}
@@ -376,6 +393,7 @@ static int read_log(struct tpm_bios_log *log)
struct acpi_tcpa *buff;
acpi_status status;
struct acpi_table_header *virt;
+ u64 len, start;
if (log->bios_event_log != NULL) {
printk(KERN_ERR
@@ -396,27 +414,37 @@ static int read_log(struct tpm_bios_log *log)
return -EIO;
}
- if (buff->log_max_len == 0) {
+ switch(buff->platform_class) {
+ case BIOS_SERVER:
+ len = buff->server.log_max_len;
+ start = buff->server.log_start_addr;
+ break;
+ case BIOS_CLIENT:
+ default:
+ len = buff->client.log_max_len;
+ start = buff->client.log_start_addr;
+ break;
+ }
+ if (!len) {
printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
return -EIO;
}
/* malloc EventLog space */
- log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
+ log->bios_event_log = kmalloc(len, GFP_KERNEL);
if (!log->bios_event_log) {
- printk
- ("%s: ERROR - Not enough Memory for BIOS measurements\n",
- __func__);
+ printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
+ __func__);
return -ENOMEM;
}
- log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
+ log->bios_event_log_end = log->bios_event_log + len;
- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
+ acpi_os_map_memory(start, len, (void *) &virt);
- memcpy(log->bios_event_log, virt, buff->log_max_len);
+ memcpy(log->bios_event_log, virt, len);
- acpi_os_unmap_memory(virt, buff->log_max_len);
+ acpi_os_unmap_memory(virt, len);
return 0;
}
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 24095f6ee6da..adfff21beb21 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -15,6 +15,7 @@
* License.
*/
+#include <linux/init.h>
#include <linux/pnp.h>
#include "tpm.h"
@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
if (clear_wrfifo) {
for (i = 0; i < 4096; i++) {
- status = inb(chip->vendor->base + WRFIFO);
+ status = inb(chip->vendor.base + WRFIFO);
if (status == 0xff) {
if (check == 5)
break;
@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
*/
i = 0;
do {
- status = inb(chip->vendor->base + RDFIFO);
- status = inb(chip->vendor->base + STAT);
+ status = inb(chip->vendor.base + RDFIFO);
+ status = inb(chip->vendor.base + STAT);
i++;
if (i == TPM_MAX_TRIES)
return -EIO;
@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
int status;
int i;
for (i = 0; i < TPM_MAX_TRIES; i++) {
- status = inb(chip->vendor->base + STAT);
+ status = inb(chip->vendor.base + STAT);
/* check the status-register if wait_for_bit is set */
if (status & 1 << wait_for_bit)
break;
@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
{
wait(chip, STAT_XFE);
- outb(sendbyte, chip->vendor->base + WRFIFO);
+ outb(sendbyte, chip->vendor.base + WRFIFO);
}
/* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
@@ -204,7 +205,7 @@ recv_begin:
ret = wait(chip, STAT_RDA);
if (ret)
return -EIO;
- buf[i] = inb(chip->vendor->base + RDFIFO);
+ buf[i] = inb(chip->vendor.base + RDFIFO);
}
if (buf[0] != TPM_VL_VER) {
@@ -219,7 +220,7 @@ recv_begin:
for (i = 0; i < size; i++) {
wait(chip, STAT_RDA);
- buf[i] = inb(chip->vendor->base + RDFIFO);
+ buf[i] = inb(chip->vendor.base + RDFIFO);
}
if ((size == 0x6D00) && (buf[1] == 0x80)) {
@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
u8 count_high, count_low, count_4, count_3, count_2, count_1;
/* Disabling Reset, LP and IRQC */
- outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
+ outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
ret = empty_fifo(chip, 1);
if (ret) {
@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip)
static u8 tpm_inf_status(struct tpm_chip *chip)
{
- return inb(chip->vendor->base + STAT);
+ return inb(chip->vendor.base + STAT);
}
static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
@@ -346,7 +347,7 @@ static struct file_operations inf_ops = {
.release = tpm_release,
};
-static struct tpm_vendor_specific tpm_inf = {
+static const struct tpm_vendor_specific tpm_inf = {
.recv = tpm_inf_recv,
.send = tpm_inf_send,
.cancel = tpm_inf_cancel,
@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
int version[2];
int productid[2];
char chipname[20];
+ struct tpm_chip *chip;
/* read IO-ports through PnP */
if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
goto err_last;
}
/* publish my base address and request region */
- tpm_inf.base = TPM_INF_BASE;
if (request_region
- (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+ (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
rc = -EINVAL;
goto err_last;
}
- if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
- "tpm_infineon0") == NULL) {
+ if (request_region
+ (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
rc = -EINVAL;
goto err_last;
}
@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
/* configure TPM with IO-ports */
outb(IOLIMH, TPM_INF_ADDR);
- outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+ outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
outb(IOLIML, TPM_INF_ADDR);
- outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+ outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
/* control if IO-ports are set correctly */
outb(IOLIMH, TPM_INF_ADDR);
@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
outb(IOLIML, TPM_INF_ADDR);
iol = inb(TPM_INF_DATA);
- if ((ioh << 8 | iol) != tpm_inf.base) {
+ if ((ioh << 8 | iol) != TPM_INF_BASE) {
dev_err(&dev->dev,
- "Could not set IO-ports to 0x%lx\n",
- tpm_inf.base);
+ "Could not set IO-ports to 0x%x\n",
+ TPM_INF_BASE);
rc = -EIO;
goto err_release_region;
}
@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
/* disable RESET, LP and IRQC */
- outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
+ outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
/* Finally, we're done, print some infos */
dev_info(&dev->dev, "TPM found: "
"config base 0x%x, "
"io base 0x%x, "
- "chip version %02x%02x, "
- "vendor id %x%x (Infineon), "
- "product id %02x%02x"
+ "chip version 0x%02x%02x, "
+ "vendor id 0x%x%x (Infineon), "
+ "product id 0x%02x%02x"
"%s\n",
TPM_INF_ADDR,
TPM_INF_BASE,
@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
vendorid[0], vendorid[1],
productid[0], productid[1], chipname);
- rc = tpm_register_hardware(&dev->dev, &tpm_inf);
- if (rc < 0) {
- rc = -ENODEV;
+ if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
goto err_release_region;
}
+ chip->vendor.base = TPM_INF_BASE;
return 0;
} else {
rc = -ENODEV;
@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
}
err_release_region:
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
err_last:
@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
struct tpm_chip *chip = pnp_get_drvdata(dev);
if (chip) {
- release_region(chip->vendor->base, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
tpm_remove_hardware(chip->dev);
}
}
@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = {
},
.id_table = tpm_pnp_tbl,
.probe = tpm_inf_pnp_probe,
- .remove = tpm_inf_pnp_remove,
+ .remove = __devexit_p(tpm_inf_pnp_remove),
};
static int __init init_inf(void)
@@ -538,5 +539,5 @@ module_exit(cleanup_inf);
MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.8");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 680a8e331887..4c8bc06c7d95 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
unsigned long stop;
/* status immediately available check */
- *data = inb(chip->vendor->base + NSC_STATUS);
+ *data = inb(chip->vendor.base + NSC_STATUS);
if ((*data & mask) == val)
return 0;
@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
stop = jiffies + 10 * HZ;
do {
msleep(TPM_TIMEOUT);
- *data = inb(chip->vendor->base + 1);
+ *data = inb(chip->vendor.base + 1);
if ((*data & mask) == val)
return 0;
}
@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
unsigned long stop;
/* status immediately available check */
- status = inb(chip->vendor->base + NSC_STATUS);
+ status = inb(chip->vendor.base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor->base + NSC_DATA);
+ status = inb(chip->vendor.base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
stop = jiffies + 100;
do {
msleep(TPM_TIMEOUT);
- status = inb(chip->vendor->base + NSC_STATUS);
+ status = inb(chip->vendor.base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor->base + NSC_DATA);
+ status = inb(chip->vendor.base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
}
@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
}
if ((data =
- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
dev_err(chip->dev, "not in normal mode (0x%x)\n",
data);
return -EIO;
@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (data & NSC_STATUS_F0)
break;
- *p = inb(chip->vendor->base + NSC_DATA);
+ *p = inb(chip->vendor.base + NSC_DATA);
}
if ((data & NSC_STATUS_F0) == 0 &&
@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
dev_err(chip->dev, "F0 not set\n");
return -EIO;
}
- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
dev_err(chip->dev,
"expected end of command(0x%x)\n", data);
return -EIO;
@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
* fix it. Not sure why this is needed, we followed the flow
* chart in the manual to the letter.
*/
- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
if (nsc_wait_for_ready(chip) != 0)
return -EIO;
@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
}
- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
dev_err(chip->dev, "IBR timeout\n");
return -EIO;
@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
"IBF timeout (while writing data)\n");
return -EIO;
}
- outb(buf[i], chip->vendor->base + NSC_DATA);
+ outb(buf[i], chip->vendor.base + NSC_DATA);
}
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(chip->dev, "IBF timeout\n");
return -EIO;
}
- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
return count;
}
static void tpm_nsc_cancel(struct tpm_chip *chip)
{
- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
}
static u8 tpm_nsc_status(struct tpm_chip *chip)
{
- return inb(chip->vendor->base + NSC_STATUS);
+ return inb(chip->vendor.base + NSC_STATUS);
}
static struct file_operations nsc_ops = {
@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = {
static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
-static struct tpm_vendor_specific tpm_nsc = {
+static const struct tpm_vendor_specific tpm_nsc = {
.recv = tpm_nsc_recv,
.send = tpm_nsc_send,
.cancel = tpm_nsc_cancel,
@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if ( chip ) {
- release_region(chip->vendor->base, 2);
+ release_region(chip->vendor.base, 2);
tpm_remove_hardware(chip->dev);
}
}
@@ -286,7 +286,8 @@ static int __init init_nsc(void)
int rc = 0;
int lo, hi;
int nscAddrBase = TPM_ADDR;
-
+ struct tpm_chip *chip;
+ unsigned long base;
/* verify that it is a National part (SID) */
if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
@@ -300,7 +301,7 @@ static int __init init_nsc(void)
hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
- tpm_nsc.base = (hi<<8) | lo;
+ base = (hi<<8) | lo;
/* enable the DPM module */
tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
@@ -320,13 +321,15 @@ static int __init init_nsc(void)
if ((rc = platform_device_register(pdev)) < 0)
goto err_free_dev;
- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+ if (request_region(base, 2, "tpm_nsc0") == NULL ) {
rc = -EBUSY;
goto err_unreg_dev;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
+ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
+ rc = -ENODEV;
goto err_rel_reg;
+ }
dev_dbg(&pdev->dev, "NSC TPM detected\n");
dev_dbg(&pdev->dev,
@@ -361,10 +364,12 @@ static int __init init_nsc(void)
"NSC TPM revision %d\n",
tpm_read_index(nscAddrBase, 0x27) & 0x1F);
+ chip->vendor.base = base;
+
return 0;
err_rel_reg:
- release_region(tpm_nsc.base, 2);
+ release_region(base, 2);
err_unreg_dev:
platform_device_unregister(pdev);
err_free_dev:
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
new file mode 100644
index 000000000000..b9cae9a238bb
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.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, version 2 of the
+ * License.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pnp.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+#define TPM_HEADER_SIZE 10
+
+enum tis_access {
+ TPM_ACCESS_VALID = 0x80,
+ TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+ TPM_ACCESS_REQUEST_PENDING = 0x04,
+ TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+ TPM_STS_VALID = 0x80,
+ TPM_STS_COMMAND_READY = 0x40,
+ TPM_STS_GO = 0x20,
+ TPM_STS_DATA_AVAIL = 0x10,
+ TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+ TPM_GLOBAL_INT_ENABLE = 0x80000000,
+ TPM_INTF_BURST_COUNT_STATIC = 0x100,
+ TPM_INTF_CMD_READY_INT = 0x080,
+ TPM_INTF_INT_EDGE_FALLING = 0x040,
+ TPM_INTF_INT_EDGE_RISING = 0x020,
+ TPM_INTF_INT_LEVEL_LOW = 0x010,
+ TPM_INTF_INT_LEVEL_HIGH = 0x008,
+ TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+ TPM_INTF_STS_VALID_INT = 0x002,
+ TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+ TIS_MEM_BASE = 0xFED4000,
+ TIS_MEM_LEN = 0x5000,
+ TIS_SHORT_TIMEOUT = 750, /* ms */
+ TIS_LONG_TIMEOUT = 2000, /* 2 sec */
+};
+
+#define TPM_ACCESS(l) (0x0000 | ((l) << 12))
+#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12))
+#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12))
+#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12))
+#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12))
+#define TPM_STS(l) (0x0018 | ((l) << 12))
+#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12))
+
+#define TPM_DID_VID(l) (0x0F00 | ((l) << 12))
+#define TPM_RID(l) (0x0F04 | ((l) << 12))
+
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+static int check_locality(struct tpm_chip *chip, int l)
+{
+ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+ return chip->vendor.locality = l;
+
+ return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int l, int force)
+{
+ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
+ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
+ chip->vendor.iobase + TPM_ACCESS(l));
+}
+
+static int request_locality(struct tpm_chip *chip, int l)
+{
+ unsigned long stop;
+ long rc;
+
+ if (check_locality(chip, l) >= 0)
+ return l;
+
+ iowrite8(TPM_ACCESS_REQUEST_USE,
+ chip->vendor.iobase + TPM_ACCESS(l));
+
+ if (chip->vendor.irq) {
+ rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
+ (check_locality
+ (chip, l) >= 0),
+ chip->vendor.timeout_a);
+ if (rc > 0)
+ return l;
+
+ } else {
+ /* wait for burstcount */
+ stop = jiffies + chip->vendor.timeout_a;
+ do {
+ if (check_locality(chip, l) >= 0)
+ return l;
+ msleep(TPM_TIMEOUT);
+ }
+ while (time_before(jiffies, stop));
+ }
+ return -1;
+}
+
+static u8 tpm_tis_status(struct tpm_chip *chip)
+{
+ return ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality));
+}
+
+static void tpm_tis_ready(struct tpm_chip *chip)
+{
+ /* this causes the current command to be aborted */
+ iowrite8(TPM_STS_COMMAND_READY,
+ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+}
+
+static int get_burstcount(struct tpm_chip *chip)
+{
+ unsigned long stop;
+ int burstcnt;
+
+ /* wait for burstcount */
+ /* which timeout value, spec has 2 answers (c & d) */
+ stop = jiffies + chip->vendor.timeout_d;
+ do {
+ burstcnt = ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality) + 1);
+ burstcnt += ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality) +
+ 2) << 8;
+ if (burstcnt)
+ return burstcnt;
+ msleep(TPM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+ return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+ wait_queue_head_t *queue)
+{
+ unsigned long stop;
+ long rc;
+ u8 status;
+
+ /* check current status */
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ if (chip->vendor.irq) {
+ rc = wait_event_interruptible_timeout(*queue,
+ ((tpm_tis_status
+ (chip) & mask) ==
+ mask), timeout);
+ if (rc > 0)
+ return 0;
+ } else {
+ stop = jiffies + timeout;
+ do {
+ msleep(TPM_TIMEOUT);
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+ }
+ return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ int size = 0, burstcnt;
+ while (size < count &&
+ wait_for_stat(chip,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue)
+ == 0) {
+ burstcnt = get_burstcount(chip);
+ for (; burstcnt > 0 && size < count; burstcnt--)
+ buf[size++] = ioread8(chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.
+ locality));
+ }
+ return size;
+}
+
+static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ int size = 0;
+ int expected, status;
+
+ if (count < TPM_HEADER_SIZE) {
+ size = -EIO;
+ goto out;
+ }
+
+ /* read first 10 bytes, including tag, paramsize, and result */
+ if ((size =
+ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
+ dev_err(chip->dev, "Unable to read header\n");
+ goto out;
+ }
+
+ expected = be32_to_cpu(*(__be32 *) (buf + 2));
+ if (expected > count) {
+ size = -EIO;
+ goto out;
+ }
+
+ if ((size +=
+ recv_data(chip, &buf[TPM_HEADER_SIZE],
+ expected - TPM_HEADER_SIZE)) < expected) {
+ dev_err(chip->dev, "Unable to read remainder of result\n");
+ size = -ETIME;
+ goto out;
+ }
+
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
+ dev_err(chip->dev, "Error left over data\n");
+ size = -EIO;
+ goto out;
+ }
+
+out:
+ tpm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+ int rc, status, burstcnt;
+ size_t count = 0;
+ u32 ordinal;
+
+ if (request_locality(chip, 0) < 0)
+ return -EBUSY;
+
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_COMMAND_READY) == 0) {
+ tpm_tis_ready(chip);
+ if (wait_for_stat
+ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+ &chip->vendor.int_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+
+ while (count < len - 1) {
+ burstcnt = get_burstcount(chip);
+ for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+ iowrite8(buf[count], chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.locality));
+ count++;
+ }
+
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_DATA_EXPECT) == 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+ }
+
+ /* write last byte */
+ iowrite8(buf[count],
+ chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.locality));
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_DATA_EXPECT) != 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ /* go and do it */
+ iowrite8(TPM_STS_GO,
+ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+
+ if (chip->vendor.irq) {
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+ if (wait_for_stat
+ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ tpm_calc_ordinal_duration(chip, ordinal),
+ &chip->vendor.read_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+ return len;
+out_err:
+ tpm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ return rc;
+}
+
+static struct file_operations tis_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+ NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_active.attr,
+ &dev_attr_owned.attr,
+ &dev_attr_temp_deactivated.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+ .attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis = {
+ .status = tpm_tis_status,
+ .recv = tpm_tis_recv,
+ .send = tpm_tis_send,
+ .cancel = tpm_tis_ready,
+ .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ .req_canceled = TPM_STS_COMMAND_READY,
+ .attr_group = &tis_attr_grp,
+ .miscdev = {
+ .fops = &tis_ops,},
+};
+
+static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ u32 interrupt;
+
+ interrupt = ioread32(chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ if (interrupt == 0)
+ return IRQ_NONE;
+
+ chip->vendor.irq = irq;
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(interrupt,
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ u32 interrupt;
+ int i;
+
+ interrupt = ioread32(chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ if (interrupt == 0)
+ return IRQ_NONE;
+
+ if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+ wake_up_interruptible(&chip->vendor.read_queue);
+ if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+ for (i = 0; i < 5; i++)
+ if (check_locality(chip, i) >= 0)
+ break;
+ if (interrupt &
+ (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+ TPM_INTF_CMD_READY_INT))
+ wake_up_interruptible(&chip->vendor.int_queue);
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(interrupt,
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+ return IRQ_HANDLED;
+}
+
+static int interrupts = 1;
+module_param(interrupts, bool, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+ const struct pnp_device_id *pnp_id)
+{
+ u32 vendor, intfcaps, intmask;
+ int rc, i;
+ unsigned long start, len;
+ struct tpm_chip *chip;
+
+ start = pnp_mem_start(pnp_dev, 0);
+ len = pnp_mem_len(pnp_dev, 0);
+
+ if (!start)
+ start = TIS_MEM_BASE;
+ if (!len)
+ len = TIS_MEM_LEN;
+
+ if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
+ return -ENODEV;
+
+ chip->vendor.iobase = ioremap(start, len);
+ if (!chip->vendor.iobase) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+ if ((vendor & 0xFFFF) == 0xFFFF) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* Default timeouts */
+ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+ dev_info(&pnp_dev->dev,
+ "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
+
+ /* Figure out the capabilities */
+ intfcaps =
+ ioread32(chip->vendor.iobase +
+ TPM_INTF_CAPS(chip->vendor.locality));
+ dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
+ intfcaps);
+ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+ dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
+ if (intfcaps & TPM_INTF_CMD_READY_INT)
+ dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
+ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+ dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
+ if (intfcaps & TPM_INTF_STS_VALID_INT)
+ dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
+ if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+ dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
+
+ if (request_locality(chip, 0) != 0) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* INTERRUPT Setup */
+ init_waitqueue_head(&chip->vendor.read_queue);
+ init_waitqueue_head(&chip->vendor.int_queue);
+
+ intmask =
+ ioread32(chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ intmask |= TPM_INTF_CMD_READY_INT
+ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+ | TPM_INTF_STS_VALID_INT;
+
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ if (interrupts) {
+ chip->vendor.irq =
+ ioread8(chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+
+ for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+ iowrite8(i, chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+ if (request_irq
+ (i, tis_int_probe, SA_SHIRQ,
+ chip->vendor.miscdev.name, chip) != 0) {
+ dev_info(chip->dev,
+ "Unable to request irq: %d for probe\n",
+ i);
+ continue;
+ }
+
+ /* Clear all existing */
+ iowrite32(ioread32
+ (chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality)),
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ /* Turn on */
+ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ /* Generate Interrupts */
+ tpm_gen_interrupt(chip);
+
+ /* Turn off */
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ free_irq(i, chip);
+ }
+ }
+ if (chip->vendor.irq) {
+ iowrite8(chip->vendor.irq,
+ chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+ if (request_irq
+ (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
+ chip->vendor.miscdev.name, chip) != 0) {
+ dev_info(chip->dev,
+ "Unable to request irq: %d for use\n",
+ chip->vendor.irq);
+ chip->vendor.irq = 0;
+ } else {
+ /* Clear all existing */
+ iowrite32(ioread32
+ (chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality)),
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ /* Turn on */
+ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ }
+ }
+
+ INIT_LIST_HEAD(&chip->vendor.list);
+ spin_lock(&tis_lock);
+ list_add(&chip->vendor.list, &tis_chips);
+ spin_unlock(&tis_lock);
+
+ tpm_get_timeouts(chip);
+ tpm_continue_selftest(chip);
+
+ return 0;
+out_err:
+ if (chip->vendor.iobase)
+ iounmap(chip->vendor.iobase);
+ tpm_remove_hardware(chip->dev);
+ return rc;
+}
+
+static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
+{
+ return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_tis_pnp_resume(struct pnp_dev *dev)
+{
+ return tpm_pm_resume(&dev->dev);
+}
+
+static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+ {"PNP0C31", 0}, /* TPM */
+ {"ATM1200", 0}, /* Atmel */
+ {"IFX0102", 0}, /* Infineon */
+ {"BCM0101", 0}, /* Broadcom */
+ {"NSC1200", 0}, /* National */
+ /* Add new here */
+ {"", 0}, /* User Specified */
+ {"", 0} /* Terminator */
+};
+
+static struct pnp_driver tis_pnp_driver = {
+ .name = "tpm_tis",
+ .id_table = tpm_pnp_tbl,
+ .probe = tpm_tis_pnp_init,
+ .suspend = tpm_tis_pnp_suspend,
+ .resume = tpm_tis_pnp_resume,
+};
+
+#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
+module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
+ sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
+MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
+
+static int __init init_tis(void)
+{
+ return pnp_register_driver(&tis_pnp_driver);
+}
+
+static void __exit cleanup_tis(void)
+{
+ struct tpm_vendor_specific *i, *j;
+ struct tpm_chip *chip;
+ spin_lock(&tis_lock);
+ list_for_each_entry_safe(i, j, &tis_chips, list) {
+ chip = to_tpm_chip(i);
+ iowrite32(~TPM_GLOBAL_INT_ENABLE &
+ ioread32(chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.
+ locality)),
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ release_locality(chip, chip->vendor.locality, 1);
+ if (chip->vendor.irq)
+ free_irq(chip->vendor.irq, chip);
+ iounmap(i->iobase);
+ list_del(&i->list);
+ tpm_remove_hardware(chip->dev);
+ }
+ spin_unlock(&tis_lock);
+ pnp_unregister_driver(&tis_pnp_driver);
+}
+
+module_init(init_tis);
+module_exit(cleanup_tis);
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 98b126c2ded8..f07637a8f88f 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -351,10 +351,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
spin_unlock_irqrestore(&tty->buf.lock, flags);
return size;
}
-
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
-int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size)
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
+ size_t size)
{
int copied = 0;
do {
@@ -368,17 +368,16 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s
tb->used += space;
copied += space;
chars += space;
-/* printk("Flip insert %d.\n", space); */
}
/* There is a small chance that we need to split the data over
several buffers. If this is the case we must loop */
while (unlikely(size > copied));
return copied;
}
-
EXPORT_SYMBOL(tty_insert_flip_string);
-int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size)
+int tty_insert_flip_string_flags(struct tty_struct *tty,
+ const unsigned char *chars, const char *flags, size_t size)
{
int copied = 0;
do {
@@ -399,9 +398,20 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *ch
while (unlikely(size > copied));
return copied;
}
-
EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
+void tty_schedule_flip(struct tty_struct *tty)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ if (tty->buf.tail != NULL) {
+ tty->buf.tail->active = 0;
+ tty->buf.tail->commit = tty->buf.tail->used;
+ }
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
/*
* Prepare a block of space in the buffer for data. Returns the length
@@ -1730,7 +1740,7 @@ static void release_dev(struct file * filp)
{
struct tty_struct *tty, *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
- int devpts_master, devpts;
+ int devpts;
int idx;
char buf[64];
unsigned long flags;
@@ -1747,7 +1757,6 @@ static void release_dev(struct file * filp)
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
- devpts_master = pty_master && devpts;
o_tty = tty->link;
#ifdef TTY_PARANOIA_CHECK
@@ -2185,6 +2194,7 @@ static int ptmx_open(struct inode * inode, struct file * filp)
return 0;
out1:
release_dev(filp);
+ return retval;
out:
down(&allocated_ptys_lock);
idr_remove(&allocated_ptys, index);
@@ -2713,7 +2723,11 @@ static void __do_SAK(void *arg)
}
task_lock(p);
if (p->files) {
- rcu_read_lock();
+ /*
+ * We don't take a ref to the file, so we must
+ * hold ->file_lock instead.
+ */
+ spin_lock(&p->files->file_lock);
fdt = files_fdtable(p->files);
for (i=0; i < fdt->max_fds; i++) {
filp = fcheck_files(p->files, i);
@@ -2724,11 +2738,11 @@ static void __do_SAK(void *arg)
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): fd#%d opened to the tty\n",
p->pid, p->comm, i);
- send_sig(SIGKILL, p, 1);
+ force_sig(SIGKILL, p);
break;
}
}
- rcu_read_unlock();
+ spin_unlock(&p->files->file_lock);
}
task_unlock(p);
} while_each_thread(g, p);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 16e99db2e12d..d53f664a4dd8 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -60,6 +60,13 @@ config SOFT_WATCHDOG
# ARM Architecture
+config AT91_WATCHDOG
+ tristate "AT91RM9200 watchdog"
+ depends on WATCHDOG && ARCH_AT91RM9200
+ help
+ Watchdog timer embedded into AT91RM9200 chips. This will reboot your
+ system when the timeout is reached.
+
config 21285_WATCHDOG
tristate "DC21285 watchdog"
depends on WATCHDOG && FOOTBRIDGE
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index d6f27fde9905..6ab77b61a643 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o
obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
# ARM Architecture
+obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c
new file mode 100644
index 000000000000..ac83bc4b019a
--- /dev/null
+++ b/drivers/char/watchdog/at91_wdt.c
@@ -0,0 +1,228 @@
+/*
+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
+ *
+ * Copyright (C) 2003 SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#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/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+
+#define WDT_DEFAULT_TIME 5 /* 5 seconds */
+#define WDT_MAX_TIME 256 /* 256 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) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+
+static unsigned long at91wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline at91_wdt_stop(void)
+{
+ at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline at91_wdt_start(void)
+{
+ at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
+ at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/*
+ * Reload the watchdog timer. (ie, pat the watchdog)
+ */
+static void inline at91_wdt_reload(void)
+{
+ at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at91_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &at91wdt_busy))
+ return -EBUSY;
+
+ at91_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 at91_wdt_close(struct inode *inode, struct file *file)
+{
+ if (!nowayout)
+ at91_wdt_stop(); /* Disable the watchdog when file is closed */
+
+ clear_bit(0, &at91wdt_busy);
+ return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at91_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 at91_wdt_start() is called. */
+ wdt_time = new_time;
+ return 0;
+}
+
+static struct watchdog_info at91_wdt_info = {
+ .identity = "at91 watchdog",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at91_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:
+ at91_wdt_reload(); /* pat the watchdog */
+ return 0;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ if (at91_wdt_settimeout(new_value))
+ return -EINVAL;
+
+ /* Enable new time value */
+ at91_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)
+ at91_wdt_stop();
+ if (new_value & WDIOS_ENABLECARD)
+ at91_wdt_start();
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+ at91_wdt_reload(); /* pat the watchdog */
+ return len;
+}
+
+/* ......................................................................... */
+
+static struct file_operations at91wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = at91_wdt_ioctl,
+ .open = at91_wdt_open,
+ .release = at91_wdt_close,
+ .write = at91_wdt_write,
+};
+
+static struct miscdevice at91wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &at91wdt_fops,
+};
+
+static int __init at91_wdt_init(void)
+{
+ int res;
+
+ /* Check that the heartbeat value is within range; if not reset to the default */
+ if (at91_wdt_settimeout(wdt_time)) {
+ at91_wdt_settimeout(WDT_DEFAULT_TIME);
+ printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
+ }
+
+ res = misc_register(&at91wdt_miscdev);
+ if (res)
+ return res;
+
+ printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout);
+ return 0;
+}
+
+static void __exit at91_wdt_exit(void)
+{
+ misc_deregister(&at91wdt_miscdev);
+}
+
+module_init(at91_wdt_init);
+module_exit(at91_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 8d6b249ad66b..6d44ca68312d 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -66,15 +66,13 @@
#include <linux/fs.h> /* For file operations */
#include <linux/ioport.h> /* For io-port access */
#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
-#include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <linux/slab.h> /* For kmalloc */
#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
#include <asm/io.h> /* For inb/outb/... */
/* Module and version information */
-#define WATCHDOG_VERSION "1.16"
-#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_VERSION "1.17"
+#define WATCHDOG_DATE "12 Feb 2006"
#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
#define WATCHDOG_NAME "pcwd"
#define PFX WATCHDOG_NAME ": "
@@ -96,15 +94,19 @@
* PCI-PC Watchdog card.
*/
/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
-#define WD_WDRST 0x01 /* Previously reset state */
-#define WD_T110 0x02 /* Temperature overheat sense */
-#define WD_HRTBT 0x04 /* Heartbeat sense */
-#define WD_RLY2 0x08 /* External relay triggered */
-#define WD_SRLY2 0x80 /* Software external relay triggered */
+#define WD_WDRST 0x01 /* Previously reset state */
+#define WD_T110 0x02 /* Temperature overheat sense */
+#define WD_HRTBT 0x04 /* Heartbeat sense */
+#define WD_RLY2 0x08 /* External relay triggered */
+#define WD_SRLY2 0x80 /* Software external relay triggered */
/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
-#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
-#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
-#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
+#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
+#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
+#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
+#define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */
+#define WD_REVC_RL1A 0x10 /* Relay 1 active */
+#define WD_REVC_R2DS 0x40 /* Relay 2 disable */
+#define WD_REVC_RLY2 0x80 /* Relay 2 activated? */
/* Port 2 : Control Status #2 */
#define WD_WDIS 0x10 /* Watchdog Disabled */
#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */
@@ -122,9 +124,14 @@
#define CMD_ISA_VERSION_HUNDRETH 0x03
#define CMD_ISA_VERSION_MINOR 0x04
#define CMD_ISA_SWITCH_SETTINGS 0x05
+#define CMD_ISA_RESET_PC 0x06
+#define CMD_ISA_ARM_0 0x07
+#define CMD_ISA_ARM_30 0x08
+#define CMD_ISA_ARM_60 0x09
#define CMD_ISA_DELAY_TIME_2SECS 0x0A
#define CMD_ISA_DELAY_TIME_4SECS 0x0B
#define CMD_ISA_DELAY_TIME_8SECS 0x0C
+#define CMD_ISA_RESET_RELAYS 0x0D
/*
* We are using an kernel timer to do the pinging of the watchdog
@@ -142,6 +149,7 @@ static atomic_t open_allowed = ATOMIC_INIT(1);
static char expect_close;
static int temp_panic;
static struct { /* this is private data for each ISA-PC watchdog card */
+ char fw_ver_str[6]; /* The cards firmware version */
int revision; /* The card's revision */
int supports_temp; /* Wether or not the card has a temperature device */
int command_mode; /* Wether or not the card is in command mode */
@@ -153,6 +161,13 @@ static struct { /* this is private data for each ISA-PC watchdog card */
} pcwd_private;
/* module parameters */
+#define QUIET 0 /* Default */
+#define VERBOSE 1 /* Verbose */
+#define DEBUG 2 /* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */
static int heartbeat = WATCHDOG_HEARTBEAT;
module_param(heartbeat, int, 0);
@@ -172,6 +187,10 @@ static int send_isa_command(int cmd)
int control_status;
int port0, last_port0; /* Double read for stabilising */
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
+ cmd);
+
/* The WCMD bit must be 1 and the command is only 4 bits in size */
control_status = (cmd & 0x0F) | WD_WCMD;
outb_p(control_status, pcwd_private.io_addr + 2);
@@ -188,6 +207,10 @@ static int send_isa_command(int cmd)
udelay (250);
}
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+ cmd, port0, last_port0);
+
return port0;
}
@@ -214,6 +237,10 @@ static int set_command_mode(void)
spin_unlock(&pcwd_private.io_lock);
pcwd_private.command_mode = found;
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "command_mode=%d\n",
+ pcwd_private.command_mode);
+
return(found);
}
@@ -226,6 +253,10 @@ static void unset_command_mode(void)
spin_unlock(&pcwd_private.io_lock);
pcwd_private.command_mode = 0;
+
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "command_mode=%d\n",
+ pcwd_private.command_mode);
}
static inline void pcwd_check_temperature_support(void)
@@ -234,27 +265,22 @@ static inline void pcwd_check_temperature_support(void)
pcwd_private.supports_temp = 1;
}
-static inline char *get_firmware(void)
+static inline void pcwd_get_firmware(void)
{
int one, ten, hund, minor;
- char *ret;
- ret = kmalloc(6, GFP_KERNEL);
- if(ret == NULL)
- return NULL;
+ strcpy(pcwd_private.fw_ver_str, "ERROR");
if (set_command_mode()) {
one = send_isa_command(CMD_ISA_VERSION_INTEGER);
ten = send_isa_command(CMD_ISA_VERSION_TENTH);
hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
minor = send_isa_command(CMD_ISA_VERSION_MINOR);
- sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+ sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor);
}
- else
- sprintf(ret, "ERROR");
-
unset_command_mode();
- return(ret);
+
+ return;
}
static inline int pcwd_get_option_switches(void)
@@ -272,17 +298,15 @@ static inline int pcwd_get_option_switches(void)
static void pcwd_show_card_info(void)
{
- char *firmware;
int option_switches;
/* Get some extra info from the hardware (in command/debug/diag mode) */
if (pcwd_private.revision == PCWD_REVISION_A)
printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
else if (pcwd_private.revision == PCWD_REVISION_C) {
- firmware = get_firmware();
+ pcwd_get_firmware();
printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
- pcwd_private.io_addr, firmware);
- kfree(firmware);
+ pcwd_private.io_addr, pcwd_private.fw_ver_str);
option_switches = pcwd_get_option_switches();
printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
option_switches,
@@ -362,6 +386,10 @@ static int pcwd_start(void)
return -EIO;
}
}
+
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "Watchdog started\n");
+
return 0;
}
@@ -386,6 +414,10 @@ static int pcwd_stop(void)
return -EIO;
}
}
+
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
return 0;
}
@@ -393,6 +425,10 @@ static int pcwd_keepalive(void)
{
/* user land ping */
pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
+
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
return 0;
}
@@ -402,12 +438,17 @@ static int pcwd_set_heartbeat(int t)
return -EINVAL;
heartbeat = t;
+
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+ heartbeat);
+
return 0;
}
static int pcwd_get_status(int *status)
{
- int card_status;
+ int control_status;
*status=0;
spin_lock(&pcwd_private.io_lock);
@@ -415,37 +456,39 @@ static int pcwd_get_status(int *status)
/* Rev A cards return status information from
* the base register, which is used for the
* temperature in other cards. */
- card_status = inb(pcwd_private.io_addr);
+ control_status = inb(pcwd_private.io_addr);
else {
/* Rev C cards return card status in the base
* address + 1 register. And use different bits
* to indicate a card initiated reset, and an
* over-temperature condition. And the reboot
* status can be reset. */
- card_status = inb(pcwd_private.io_addr + 1);
+ control_status = inb(pcwd_private.io_addr + 1);
}
spin_unlock(&pcwd_private.io_lock);
if (pcwd_private.revision == PCWD_REVISION_A) {
- if (card_status & WD_WDRST)
+ if (control_status & WD_WDRST)
*status |= WDIOF_CARDRESET;
- if (card_status & WD_T110) {
+ if (control_status & WD_T110) {
*status |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO PFX "Temperature overheat trip!\n");
kernel_power_off();
+ /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
}
}
} else {
- if (card_status & WD_REVC_WTRP)
+ if (control_status & WD_REVC_WTRP)
*status |= WDIOF_CARDRESET;
- if (card_status & WD_REVC_TTRP) {
+ if (control_status & WD_REVC_TTRP) {
*status |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO PFX "Temperature overheat trip!\n");
kernel_power_off();
+ /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
}
}
}
@@ -455,9 +498,25 @@ static int pcwd_get_status(int *status)
static int pcwd_clear_status(void)
{
+ int control_status;
+
if (pcwd_private.revision == PCWD_REVISION_C) {
spin_lock(&pcwd_private.io_lock);
- outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+
+ if (debug >= VERBOSE)
+ printk(KERN_INFO PFX "clearing watchdog trip status\n");
+
+ control_status = inb_p(pcwd_private.io_addr + 1);
+
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+ printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+ (control_status & WD_REVC_R2DS));
+ }
+
+ /* clear reset status & Keep Relay 2 disable state as it is */
+ outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1);
+
spin_unlock(&pcwd_private.io_lock);
}
return 0;
@@ -481,6 +540,11 @@ static int pcwd_get_temperature(int *temperature)
*temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
spin_unlock(&pcwd_private.io_lock);
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "temperature is: %d F\n",
+ *temperature);
+ }
+
return 0;
}
@@ -599,6 +663,8 @@ static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len,
static int pcwd_open(struct inode *inode, struct file *file)
{
if (!atomic_dec_and_test(&open_allowed) ) {
+ if (debug >= VERBOSE)
+ printk(KERN_ERR PFX "Attempt to open already opened device.\n");
atomic_inc( &open_allowed );
return -EBUSY;
}
@@ -922,7 +988,8 @@ static void __exit pcwd_cleanup_module(void)
{
if (pcwd_private.io_addr)
pcwatchdog_exit();
- return;
+
+ printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
}
module_init(pcwd_init_module);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 2700c5c45b8a..3fdfda9324fa 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -705,7 +705,8 @@ err_out_misc_deregister:
err_out_unregister_reboot:
unregister_reboot_notifier(&usb_pcwd_notifier);
error:
- usb_pcwd_delete (usb_pcwd);
+ if (usb_pcwd)
+ usb_pcwd_delete(usb_pcwd);
usb_pcwd_device = NULL;
return retval;
}
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 60c9be99c6d9..2cc71b66231e 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -99,7 +99,7 @@ config CPU_FREQ_GOV_USERSPACE
Enable this cpufreq governor when you either want to set the
CPU frequency manually or when an userspace program shall
be able to set the CPU dynamically, like on LART
- <http://www.lart.tudelft.nl/>
+ <http://www.lartmaker.nl/>.
For details, take a look at <file:Documentation/cpu-freq/>.
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 9b6ae7dc8b8a..29b2fa5534ae 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -319,7 +319,6 @@ out:
}
return -EINVAL;
}
-EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
/* drivers/base/cpu.c */
@@ -346,6 +345,8 @@ show_one(scaling_min_freq, min);
show_one(scaling_max_freq, max);
show_one(scaling_cur_freq, cur);
+static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
+
/**
* cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
*/
@@ -364,7 +365,10 @@ static ssize_t store_##file_name \
if (ret != 1) \
return -EINVAL; \
\
- ret = cpufreq_set_policy(&new_policy); \
+ mutex_lock(&policy->lock); \
+ ret = __cpufreq_set_policy(policy, &new_policy); \
+ policy->user_policy.object = policy->object; \
+ mutex_unlock(&policy->lock); \
\
return ret ? ret : count; \
}
@@ -420,7 +424,15 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
return -EINVAL;
- ret = cpufreq_set_policy(&new_policy);
+ /* Do not use cpufreq_set_policy here or the user_policy.max
+ will be wrongly overridden */
+ mutex_lock(&policy->lock);
+ ret = __cpufreq_set_policy(policy, &new_policy);
+
+ policy->user_policy.policy = policy->policy;
+ policy->user_policy.governor = policy->governor;
+ mutex_unlock(&policy->lock);
+
return ret ? ret : count;
}
@@ -685,7 +697,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
if (!cpu_online(j))
continue;
- dprintk("CPU already managed, adding link\n");
+ dprintk("CPU %u already managed, adding link\n", j);
cpufreq_cpu_get(cpu);
cpu_sys_dev = get_cpu_sysdev(j);
sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
@@ -695,9 +707,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
mutex_unlock(&policy->lock);
-
+
/* set default policy */
-
ret = cpufreq_set_policy(&new_policy);
if (ret) {
dprintk("setting policy failed\n");
@@ -707,7 +718,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
module_put(cpufreq_driver->owner);
dprintk("initialization complete\n");
cpufreq_debug_enable_ratelimit();
-
+
return 0;
@@ -1486,7 +1497,7 @@ int cpufreq_update_policy(unsigned int cpu)
}
EXPORT_SYMBOL(cpufreq_update_policy);
-static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
+static int cpufreq_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 037f6bf4543c..e07a35487bde 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -176,8 +176,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > 100 || input < 0 ||
- input <= dbs_tuners_ins.down_threshold) {
+ if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
}
@@ -196,8 +195,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > 100 || input < 0 ||
- input >= dbs_tuners_ins.up_threshold) {
+ if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
}
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 85429979d0db..98e395f4bb29 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,7 +1,8 @@
#
# Makefile for the linux kernel.
#
-obj-$(CONFIG_EDD) += edd.o
+obj-$(CONFIG_DMI) += dmi_scan.o
+obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
diff --git a/arch/i386/kernel/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 5efceebc48dc..948bd7e1445a 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -27,7 +27,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
else
printk(KERN_ERR "dmi_string: out of memory.\n");
}
- }
+ }
return str;
}
@@ -41,7 +41,7 @@ static int __init dmi_table(u32 base, int len, int num,
{
u8 *buf, *data;
int i = 0;
-
+
buf = dmi_ioremap(base, len);
if (buf == NULL)
return -1;
@@ -49,9 +49,9 @@ static int __init dmi_table(u32 base, int len, int num,
data = buf;
/*
- * Stop when we see all the items the table claimed to have
- * OR we run off the end of the table (also happens)
- */
+ * Stop when we see all the items the table claimed to have
+ * OR we run off the end of the table (also happens)
+ */
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
struct dmi_header *dm = (struct dmi_header *)data;
/*
@@ -75,7 +75,7 @@ static int __init dmi_checksum(u8 *buf)
{
u8 sum = 0;
int a;
-
+
for (a = 0; a < 15; a++)
sum += buf[a];
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 7636c1a58f9c..1659f6c41458 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/dmi.h>
-#include <linux/mutex.h>
#include <asm/io.h>
#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
@@ -71,10 +70,10 @@ static u8 km_activity;
static int rest_x;
static int rest_y;
-static DEFINE_MUTEX(hdaps_mutex);
+static DECLARE_MUTEX(hdaps_sem);
/*
- * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex.
+ * __get_latch - Get the value from a given port. Callers must hold hdaps_sem.
*/
static inline u8 __get_latch(u16 port)
{
@@ -83,7 +82,7 @@ static inline u8 __get_latch(u16 port)
/*
* __check_latch - Check a port latch for a given value. Returns zero if the
- * port contains the given value. Callers must hold hdaps_mutex.
+ * port contains the given value. Callers must hold hdaps_sem.
*/
static inline int __check_latch(u16 port, u8 val)
{
@@ -94,7 +93,7 @@ static inline int __check_latch(u16 port, u8 val)
/*
* __wait_latch - Wait up to 100us for a port latch to get a certain value,
- * returning zero if the value is obtained. Callers must hold hdaps_mutex.
+ * returning zero if the value is obtained. Callers must hold hdaps_sem.
*/
static int __wait_latch(u16 port, u8 val)
{
@@ -111,7 +110,7 @@ static int __wait_latch(u16 port, u8 val)
/*
* __device_refresh - request a refresh from the accelerometer. Does not wait
- * for refresh to complete. Callers must hold hdaps_mutex.
+ * for refresh to complete. Callers must hold hdaps_sem.
*/
static void __device_refresh(void)
{
@@ -125,7 +124,7 @@ static void __device_refresh(void)
/*
* __device_refresh_sync - request a synchronous refresh from the
* accelerometer. We wait for the refresh to complete. Returns zero if
- * successful and nonzero on error. Callers must hold hdaps_mutex.
+ * successful and nonzero on error. Callers must hold hdaps_sem.
*/
static int __device_refresh_sync(void)
{
@@ -135,7 +134,7 @@ static int __device_refresh_sync(void)
/*
* __device_complete - indicate to the accelerometer that we are done reading
- * data, and then initiate an async refresh. Callers must hold hdaps_mutex.
+ * data, and then initiate an async refresh. Callers must hold hdaps_sem.
*/
static inline void __device_complete(void)
{
@@ -153,7 +152,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
{
int ret;
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
/* do a sync refresh -- we need to be sure that we read fresh data */
ret = __device_refresh_sync();
@@ -164,7 +163,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
__device_complete();
out:
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return ret;
}
@@ -199,9 +198,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2,
{
int ret;
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
ret = __hdaps_read_pair(port1, port2, val1, val2);
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return ret;
}
@@ -214,7 +213,7 @@ static int hdaps_device_init(void)
{
int total, ret = -ENXIO;
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
outb(0x13, 0x1610);
outb(0x01, 0x161f);
@@ -280,7 +279,7 @@ static int hdaps_device_init(void)
}
out:
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return ret;
}
@@ -314,7 +313,7 @@ static struct platform_driver hdaps_driver = {
};
/*
- * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex.
+ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem.
*/
static void hdaps_calibrate(void)
{
@@ -326,7 +325,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
int x, y;
/* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (!mutex_trylock(&hdaps_mutex)) {
+ if (down_trylock(&hdaps_sem)) {
mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
return;
}
@@ -341,7 +340,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
out:
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
}
@@ -421,9 +420,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
hdaps_calibrate();
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return count;
}
@@ -510,12 +509,22 @@ static int hdaps_dmi_match_invert(struct dmi_system_id *id)
} \
}
+#define HDAPS_DMI_MATCH_LENOVO(model) { \
+ .ident = "Lenovo " model, \
+ .callback = hdaps_dmi_match_invert, \
+ .matches = { \
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), \
+ DMI_MATCH(DMI_PRODUCT_VERSION, model) \
+ } \
+}
+
static int __init hdaps_init(void)
{
int ret;
/* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
struct dmi_system_id hdaps_whitelist[] = {
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
@@ -525,15 +534,17 @@ static int __init hdaps_init(void)
HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+ HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
+ HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
{ .ident = NULL }
};
if (!dmi_check_system(hdaps_whitelist)) {
printk(KERN_WARNING "hdaps: supported laptop not found!\n");
- ret = -ENXIO;
+ ret = -ENODEV;
goto out;
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 6865c64d8a51..958602e28412 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1161,7 +1161,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
bank. */
if (kind < 0) {
if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
- dev_warn(dev, "Detection failed at step 3\n");
+ dev_dbg(dev, "Detection failed at step 1\n");
goto ERROR1;
}
val1 = w83792d_read_value(client, W83792D_REG_BANK);
@@ -1170,6 +1170,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
if (!(val1 & 0x07)) { /* is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) {
+ dev_dbg(dev, "Detection failed at step 2\n");
goto ERROR1;
}
}
@@ -1177,7 +1178,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
should match */
if (w83792d_read_value(client,
W83792D_REG_I2C_ADDR) != address) {
- dev_warn(dev, "Detection failed at step 5\n");
+ dev_dbg(dev, "Detection failed at step 3\n");
goto ERROR1;
}
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 089c6f5b24de..d6d44946a283 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -286,7 +286,10 @@ config I2C_PARPORT
This driver is a replacement for (and was inspired by) an older
driver named i2c-philips-par. The new driver supports more devices,
and makes it easier to add support for new devices.
-
+
+ An adapter type parameter is now mandatory. Please read the file
+ Documentation/i2c/busses/i2c-parport for details.
+
Another driver exists, named i2c-parport-light, which doesn't depend
on the parport driver. This is meant for embedded systems. Don't say
Y here if you intend to say Y or M there.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8e0f3158215f..dfca74933625 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -478,6 +478,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
ret = i801_transaction();
}
+ /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ time, so we forcibly disable it after every transaction. */
+ if (hwpec)
+ outb_p(0, SMBAUXCTL);
+
if(block)
return ret;
if(ret)
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index c63025a4c861..e09ebbb2f9f0 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,9 +121,14 @@ static struct i2c_adapter parport_adapter = {
static int __init i2c_parport_init(void)
{
- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ if (type < 0) {
+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+ return -ENODEV;
+ }
+
+ if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
- type = 0;
+ return -ENODEV;
}
if (base == 0) {
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 7e2e8cd1c14a..934bd55bae15 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,9 +241,14 @@ static struct parport_driver i2c_parport_driver = {
static int __init i2c_parport_init(void)
{
- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ if (type < 0) {
+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+ return -ENODEV;
+ }
+
+ if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
- type = 0;
+ return -ENODEV;
}
return parport_register_driver(&i2c_parport_driver);
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index d702e5e0388d..9ddd816d5d0f 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -90,7 +90,7 @@ static struct adapter_parm adapter_parm[] = {
},
};
-static int type;
+static int type = -1;
module_param(type, int, 0);
MODULE_PARM_DESC(type,
"Type of adapter:\n"
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 3024907cdafe..1a73c0532fc7 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -43,13 +43,6 @@
#include <linux/init.h>
#include <asm/io.h>
-/*
- HISTORY:
- 2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5
- (was i2c-sis645.c from lm_sensors 2.7.0)
-*/
-#define SIS96x_VERSION "1.0.0"
-
/* base address register in PCI config space */
#define SIS96x_BAR 0x04
@@ -337,7 +330,6 @@ static struct pci_driver sis96x_driver = {
static int __init i2c_sis96x_init(void)
{
- printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION);
return pci_register_driver(&sis96x_driver);
}
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 03d09ed5ec2c..4630f1969a09 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -27,6 +27,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#define DS1374_REG_TOD0 0x00
#define DS1374_REG_TOD1 0x01
@@ -139,7 +140,7 @@ ulong ds1374_get_rtc_time(void)
return t1;
}
-static void ds1374_set_tlet(ulong arg)
+static void ds1374_set_work(void *arg)
{
ulong t1, t2;
int limit = 10; /* arbitrary retry limit */
@@ -168,17 +169,18 @@ static void ds1374_set_tlet(ulong arg)
static ulong new_time;
-static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
- (ulong) & new_time);
+static struct workqueue_struct *ds1374_workqueue;
+
+static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time);
int ds1374_set_rtc_time(ulong nowtime)
{
new_time = nowtime;
if (in_interrupt())
- tasklet_schedule(&ds1374_tasklet);
+ queue_work(ds1374_workqueue, &ds1374_work);
else
- ds1374_set_tlet((ulong) & new_time);
+ ds1374_set_work(&new_time);
return 0;
}
@@ -204,6 +206,8 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
client->adapter = adap;
client->driver = &ds1374_driver;
+ ds1374_workqueue = create_singlethread_workqueue("ds1374");
+
if ((rc = i2c_attach_client(client)) != 0) {
kfree(client);
return rc;
@@ -227,7 +231,7 @@ static int ds1374_detach(struct i2c_client *client)
if ((rc = i2c_detach_client(client)) == 0) {
kfree(i2c_get_clientdata(client));
- tasklet_kill(&ds1374_tasklet);
+ destroy_workqueue(ds1374_workqueue);
}
return rc;
}
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index b5aabe7cf792..99ab4ec34390 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -25,6 +25,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <asm/time.h>
#include <asm/rtc.h>
@@ -111,7 +112,7 @@ m41t00_get_rtc_time(void)
}
static void
-m41t00_set_tlet(ulong arg)
+m41t00_set(void *arg)
{
struct rtc_time tm;
ulong nowtime = *(ulong *)arg;
@@ -130,13 +131,13 @@ m41t00_set_tlet(ulong arg)
if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
< 0))
dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
@@ -145,9 +146,9 @@ m41t00_set_tlet(ulong arg)
return;
}
-static ulong new_time;
-
-DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
+static ulong new_time;
+static struct workqueue_struct *m41t00_wq;
+static DECLARE_WORK(m41t00_work, m41t00_set, &new_time);
int
m41t00_set_rtc_time(ulong nowtime)
@@ -155,9 +156,9 @@ m41t00_set_rtc_time(ulong nowtime)
new_time = nowtime;
if (in_interrupt())
- tasklet_schedule(&m41t00_tasklet);
+ queue_work(m41t00_wq, &m41t00_work);
else
- m41t00_set_tlet((ulong)&new_time);
+ m41t00_set(&new_time);
return 0;
}
@@ -189,6 +190,7 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
return rc;
}
+ m41t00_wq = create_singlethread_workqueue("m41t00");
save_client = client;
return 0;
}
@@ -206,7 +208,7 @@ m41t00_detach(struct i2c_client *client)
if ((rc = i2c_detach_client(client)) == 0) {
kfree(client);
- tasklet_kill(&m41t00_tasklet);
+ destroy_workqueue(m41t00_wq);
}
return rc;
}
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 6213bd3caee5..4961f1e764a7 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -81,14 +81,14 @@ static const char ide_major[] = {
};
typedef struct ide_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
int ndev;
dev_node_t node;
int hd;
} ide_info_t;
-static void ide_release(dev_link_t *);
-static void ide_config(dev_link_t *);
+static void ide_release(struct pcmcia_device *);
+static int ide_config(struct pcmcia_device *);
static void ide_detach(struct pcmcia_device *p_dev);
@@ -103,10 +103,9 @@ static void ide_detach(struct pcmcia_device *p_dev);
======================================================================*/
-static int ide_attach(struct pcmcia_device *p_dev)
+static int ide_probe(struct pcmcia_device *link)
{
ide_info_t *info;
- dev_link_t *link;
DEBUG(0, "ide_attach()\n");
@@ -114,7 +113,9 @@ static int ide_attach(struct pcmcia_device *p_dev)
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link; link->priv = info;
+
+ info->p_dev = link;
+ link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@@ -122,16 +123,9 @@ static int ide_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ide_config(link);
-
- return 0;
+ return ide_config(link);
} /* ide_attach */
/*======================================================================
@@ -143,14 +137,11 @@ static int ide_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void ide_detach(struct pcmcia_device *p_dev)
+static void ide_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "ide_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- ide_release(link);
+ ide_release(link);
kfree(link->priv);
} /* ide_detach */
@@ -177,9 +168,8 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void ide_config(dev_link_t *link)
+static int ide_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
ide_info_t *info = link->priv;
tuple_t tuple;
struct {
@@ -203,34 +193,30 @@ static void ide_config(dev_link_t *link)
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse));
link->conf.ConfigBase = stk->parse.config.base;
link->conf.Present = stk->parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID;
- if (!pcmcia_get_first_tuple(handle, &tuple) &&
- !pcmcia_get_tuple_data(handle, &tuple) &&
- !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
+ if (!pcmcia_get_first_tuple(link, &tuple) &&
+ !pcmcia_get_tuple_data(link, &tuple) &&
+ !pcmcia_parse_tuple(link, &tuple, &stk->parse))
is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
(stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
- link->conf.Vcc = stk->conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
pass = io_base = ctl_base = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
- if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
+ if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
+ if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
/* Check for matching Vcc, unless we're desperate */
if (!pass) {
@@ -244,10 +230,10 @@ static void ide_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
@@ -261,14 +247,14 @@ static void ide_config(dev_link_t *link)
link->io.NumPorts1 = 8;
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = (is_kme) ? 2 : 1;
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
io_base = link->io.BasePort1;
ctl_base = link->io.BasePort2;
} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
link->io.NumPorts1 = io->win[0].len;
link->io.NumPorts2 = 0;
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
io_base = link->io.BasePort1;
ctl_base = link->io.BasePort1 + 0x0e;
@@ -281,16 +267,16 @@ static void ide_config(dev_link_t *link)
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
if (pass) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
- } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
memset(&stk->dflt, 0, sizeof(stk->dflt));
pass++;
}
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/* disable drive interrupts during IDE probe */
outb(0x02, ctl_base);
@@ -301,12 +287,12 @@ static void ide_config(dev_link_t *link)
/* retry registration in case device is still spinning up */
for (hd = -1, i = 0; i < 10; i++) {
- hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle);
+ hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
if (hd >= 0) break;
if (link->io.NumPorts1 == 0x20) {
outb(0x02, ctl_base + 0x10);
hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
- link->irq.AssignedIRQ, handle);
+ link->irq.AssignedIRQ, link);
if (hd >= 0) {
io_base += 0x10;
ctl_base += 0x10;
@@ -328,25 +314,23 @@ static void ide_config(dev_link_t *link)
info->node.major = ide_major[hd];
info->node.minor = 0;
info->hd = hd;
- link->dev = &info->node;
- printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
- info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
- link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
+ link->dev_node = &info->node;
+ printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
+ info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
- link->state &= ~DEV_CONFIG_PENDING;
kfree(stk);
- return;
+ return 0;
err_mem:
printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
goto failed;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
kfree(stk);
ide_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
} /* ide_config */
/*======================================================================
@@ -357,7 +341,7 @@ failed:
======================================================================*/
-void ide_release(dev_link_t *link)
+void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
@@ -369,37 +353,10 @@ void ide_release(dev_link_t *link)
ide_unregister(info->hd);
}
info->ndev = 0;
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* ide_release */
-static int ide_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int ide_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
/*======================================================================
@@ -459,11 +416,9 @@ static struct pcmcia_driver ide_cs_driver = {
.drv = {
.name = "ide-cs",
},
- .probe = ide_attach,
+ .probe = ide_probe,
.remove = ide_detach,
.id_table = ide_ids,
- .suspend = ide_suspend,
- .resume = ide_resume,
};
static int __init init_ide_cs(void)
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index cf84350efc55..8b24b4f2a839 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -731,6 +731,8 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
if(m5229_revision <= 0x20)
tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+ else if (m5229_revision == 0xc7)
+ tmpbyte |= 0x03;
else
tmpbyte |= 0x01;
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index df9ee9a78435..900efd1da587 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -348,6 +348,7 @@ static struct pci_device_id atiixp_pci_tbl[] = {
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 6f8f8645b02c..7ce5bf783688 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -798,7 +798,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.extra = 48,
- .flags = IDEPCI_FLAG_FORCE_PDC,
},{ /* 2 */
.name = "PDC20263",
.init_setup = init_setup_pdc202ata4,
@@ -819,7 +818,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.extra = 48,
- .flags = IDEPCI_FLAG_FORCE_PDC,
},{ /* 4 */
.name = "PDC20267",
.init_setup = init_setup_pdc202xx,
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 7ebf992e8c2f..462ed3006c30 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -580,7 +580,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
int port;
int at_least_one_hwif_enabled = 0;
ide_hwif_t *hwif, *mate = NULL;
- static int secondpdc = 0;
u8 tmp;
index->all = 0xf0f0;
@@ -592,21 +591,9 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
for (port = 0; port <= 1; ++port) {
ide_pci_enablebit_t *e = &(d->enablebits[port]);
- /*
- * If this is a Promise FakeRaid controller,
- * the 2nd controller will be marked as
- * disabled while it is actually there and enabled
- * by the bios for raid purposes.
- * Skip the normal "is it enabled" test for those.
- */
- if ((d->flags & IDEPCI_FLAG_FORCE_PDC) &&
- (secondpdc++==1) && (port==1))
- goto controller_ok;
-
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
(tmp & e->mask) != e->val))
continue; /* port not enabled */
-controller_ok:
if (d->channels <= port)
break;
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 2c765ca5aa50..f4206604db03 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -496,22 +496,17 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
/*
* This function finds the sbp2_command for a given outstanding SCpnt.
* Only looks at the inuse list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
*/
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
+static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
+ struct scsi_id_instance_data *scsi_id, void *SCpnt)
{
struct sbp2_command_info *command;
- unsigned long flags;
- spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
- if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
- list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
- if (command->Current_SCpnt == SCpnt) {
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+ if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
+ list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
+ if (command->Current_SCpnt == SCpnt)
return command;
- }
- }
- }
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return NULL;
}
@@ -580,17 +575,15 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
/*
* This function moves a command to the completed orb list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
*/
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
- struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(
+ struct scsi_id_instance_data *scsi_id,
+ struct sbp2_command_info *command)
{
- unsigned long flags;
-
- spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
list_del(&command->list);
sbp2util_free_command_dma(command);
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
}
/*
@@ -2148,7 +2141,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
* Matched status with command, now grab scsi command pointers and check status
*/
SCpnt = command->Current_SCpnt;
+ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
sbp2util_mark_command_completed(scsi_id, command);
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
if (SCpnt) {
@@ -2484,6 +2479,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
struct sbp2scsi_host_info *hi = scsi_id->hi;
struct sbp2_command_info *command;
+ unsigned long flags;
SBP2_ERR("aborting sbp2 command");
scsi_print_command(SCpnt);
@@ -2494,6 +2490,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
* Right now, just return any matching command structures
* to the free pool.
*/
+ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
if (command) {
SBP2_DEBUG("Found command to abort");
@@ -2511,6 +2508,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
command->Current_done(command->Current_SCpnt);
}
}
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
/*
* Initiate a fetch agent reset.
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index bdf0891a92dd..afc612b8577d 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -30,6 +30,7 @@ config INFINIBAND_USER_ACCESS
<http://www.openib.org>.
source "drivers/infiniband/hw/mthca/Kconfig"
+source "drivers/infiniband/hw/ipath/Kconfig"
source "drivers/infiniband/ulp/ipoib/Kconfig"
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index a43fb34cca94..eea27322a22d 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_INFINIBAND) += core/
obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/
+obj-$(CONFIG_IPATH_CORE) += hw/ipath/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index c57a3871184c..50364c0b090c 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -302,7 +302,7 @@ static void ib_cache_setup_one(struct ib_device *device)
kmalloc(sizeof *device->cache.pkey_cache *
(end_port(device) - start_port(device) + 1), GFP_KERNEL);
device->cache.gid_cache =
- kmalloc(sizeof *device->cache.pkey_cache *
+ kmalloc(sizeof *device->cache.gid_cache *
(end_port(device) - start_port(device) + 1), GFP_KERNEL);
if (!device->cache.pkey_cache || !device->cache.gid_cache) {
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index ba54c856b0e5..469b6923a2e2 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -228,10 +228,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
goto error1;
}
/* Make sure class supplied is consistent with RMPP */
- if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
- if (!rmpp_version)
- goto error1;
- } else {
+ if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
if (rmpp_version)
goto error1;
}
@@ -2311,6 +2308,7 @@ static void local_completions(void *data)
local = list_entry(mad_agent_priv->local_list.next,
struct ib_mad_local_private,
completion_list);
+ list_del(&local->completion_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
if (local->mad_priv) {
recv_mad_agent = local->recv_mad_agent;
@@ -2362,7 +2360,6 @@ local_send_completion:
&mad_send_wc);
spin_lock_irqsave(&mad_agent_priv->lock, flags);
- list_del(&local->completion_list);
atomic_dec(&mad_agent_priv->refcount);
if (!recv)
kmem_cache_free(ib_mad_cache, local->mad_priv);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index cae0845f472a..b78e7dc69330 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -45,6 +45,40 @@
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
+int ib_rate_to_mult(enum ib_rate rate)
+{
+ switch (rate) {
+ case IB_RATE_2_5_GBPS: return 1;
+ case IB_RATE_5_GBPS: return 2;
+ case IB_RATE_10_GBPS: return 4;
+ case IB_RATE_20_GBPS: return 8;
+ case IB_RATE_30_GBPS: return 12;
+ case IB_RATE_40_GBPS: return 16;
+ case IB_RATE_60_GBPS: return 24;
+ case IB_RATE_80_GBPS: return 32;
+ case IB_RATE_120_GBPS: return 48;
+ default: return -1;
+ }
+}
+EXPORT_SYMBOL(ib_rate_to_mult);
+
+enum ib_rate mult_to_ib_rate(int mult)
+{
+ switch (mult) {
+ case 1: return IB_RATE_2_5_GBPS;
+ case 2: return IB_RATE_5_GBPS;
+ case 4: return IB_RATE_10_GBPS;
+ case 8: return IB_RATE_20_GBPS;
+ case 12: return IB_RATE_30_GBPS;
+ case 16: return IB_RATE_40_GBPS;
+ case 24: return IB_RATE_60_GBPS;
+ case 32: return IB_RATE_80_GBPS;
+ case 48: return IB_RATE_120_GBPS;
+ default: return IB_RATE_PORT_CURRENT;
+ }
+}
+EXPORT_SYMBOL(mult_to_ib_rate);
+
/* Protection domains */
struct ib_pd *ib_alloc_pd(struct ib_device *device)
diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
new file mode 100644
index 000000000000..9ea67c409b6d
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/Kconfig
@@ -0,0 +1,16 @@
+config IPATH_CORE
+ tristate "PathScale InfiniPath Driver"
+ depends on 64BIT && PCI_MSI && NET
+ ---help---
+ This is a low-level driver for PathScale InfiniPath host channel
+ adapters (HCAs) based on the HT-400 and PE-800 chips.
+
+config INFINIBAND_IPATH
+ tristate "PathScale InfiniPath Verbs Driver"
+ depends on IPATH_CORE && INFINIBAND
+ ---help---
+ This is a driver that provides InfiniBand verbs support for
+ PathScale InfiniPath host channel adapters (HCAs). This
+ allows these devices to be used with both kernel upper level
+ protocols such as IP-over-InfiniBand as well as with userspace
+ applications (in conjunction with InfiniBand userspace access).
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
new file mode 100644
index 000000000000..b4d084abfd22
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/Makefile
@@ -0,0 +1,36 @@
+EXTRA_CFLAGS += -DIPATH_IDSTR='"PathScale kernel.org driver"' \
+ -DIPATH_KERN_TYPE=0
+
+obj-$(CONFIG_IPATH_CORE) += ipath_core.o
+obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
+
+ipath_core-y := \
+ ipath_diag.o \
+ ipath_driver.o \
+ ipath_eeprom.o \
+ ipath_file_ops.o \
+ ipath_fs.o \
+ ipath_ht400.o \
+ ipath_init_chip.o \
+ ipath_intr.o \
+ ipath_layer.o \
+ ipath_pe800.o \
+ ipath_stats.o \
+ ipath_sysfs.o \
+ ipath_user_pages.o
+
+ipath_core-$(CONFIG_X86_64) += ipath_wc_x86_64.o
+
+ib_ipath-y := \
+ ipath_cq.o \
+ ipath_keys.o \
+ ipath_mad.o \
+ ipath_mr.o \
+ ipath_qp.o \
+ ipath_rc.o \
+ ipath_ruc.o \
+ ipath_srq.o \
+ ipath_uc.o \
+ ipath_ud.o \
+ ipath_verbs.o \
+ ipath_verbs_mcast.o
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
new file mode 100644
index 000000000000..48a55247b832
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_COMMON_H
+#define _IPATH_COMMON_H
+
+/*
+ * This file contains defines, structures, etc. that are used
+ * to communicate between kernel and user code.
+ */
+
+/* This is the IEEE-assigned OUI for PathScale, Inc. */
+#define IPATH_SRC_OUI_1 0x00
+#define IPATH_SRC_OUI_2 0x11
+#define IPATH_SRC_OUI_3 0x75
+
+/* version of protocol header (known to chip also). In the long run,
+ * we should be able to generate and accept a range of version numbers;
+ * for now we only accept one, and it's compiled in.
+ */
+#define IPS_PROTO_VERSION 2
+
+/*
+ * These are compile time constants that you may want to enable or disable
+ * if you are trying to debug problems with code or performance.
+ * IPATH_VERBOSE_TRACING define as 1 if you want additional tracing in
+ * fastpath code
+ * IPATH_TRACE_REGWRITES define as 1 if you want register writes to be
+ * traced in faspath code
+ * _IPATH_TRACING define as 0 if you want to remove all tracing in a
+ * compilation unit
+ * _IPATH_DEBUGGING define as 0 if you want to remove debug prints
+ */
+
+/*
+ * The value in the BTH QP field that InfiniPath uses to differentiate
+ * an infinipath protocol IB packet vs standard IB transport
+ */
+#define IPATH_KD_QP 0x656b79
+
+/*
+ * valid states passed to ipath_set_linkstate() user call
+ */
+#define IPATH_IB_LINKDOWN 0
+#define IPATH_IB_LINKARM 1
+#define IPATH_IB_LINKACTIVE 2
+#define IPATH_IB_LINKINIT 3
+#define IPATH_IB_LINKDOWN_SLEEP 4
+#define IPATH_IB_LINKDOWN_DISABLE 5
+
+/*
+ * stats maintained by the driver. For now, at least, this is global
+ * to all minor devices.
+ */
+struct infinipath_stats {
+ /* number of interrupts taken */
+ __u64 sps_ints;
+ /* number of interrupts for errors */
+ __u64 sps_errints;
+ /* number of errors from chip (not incl. packet errors or CRC) */
+ __u64 sps_errs;
+ /* number of packet errors from chip other than CRC */
+ __u64 sps_pkterrs;
+ /* number of packets with CRC errors (ICRC and VCRC) */
+ __u64 sps_crcerrs;
+ /* number of hardware errors reported (parity, etc.) */
+ __u64 sps_hwerrs;
+ /* number of times IB link changed state unexpectedly */
+ __u64 sps_iblink;
+ /* no longer used; left for compatibility */
+ __u64 sps_unused3;
+ /* number of kernel (port0) packets received */
+ __u64 sps_port0pkts;
+ /* number of "ethernet" packets sent by driver */
+ __u64 sps_ether_spkts;
+ /* number of "ethernet" packets received by driver */
+ __u64 sps_ether_rpkts;
+ /* number of SMA packets sent by driver */
+ __u64 sps_sma_spkts;
+ /* number of SMA packets received by driver */
+ __u64 sps_sma_rpkts;
+ /* number of times all ports rcvhdrq was full and packet dropped */
+ __u64 sps_hdrqfull;
+ /* number of times all ports egrtid was full and packet dropped */
+ __u64 sps_etidfull;
+ /*
+ * number of times we tried to send from driver, but no pio buffers
+ * avail
+ */
+ __u64 sps_nopiobufs;
+ /* number of ports currently open */
+ __u64 sps_ports;
+ /* list of pkeys (other than default) accepted (0 means not set) */
+ __u16 sps_pkeys[4];
+ /* lids for up to 4 infinipaths, indexed by infinipath # */
+ __u16 sps_lid[4];
+ /* number of user ports per chip (not IB ports) */
+ __u32 sps_nports;
+ /* not our interrupt, or already handled */
+ __u32 sps_nullintr;
+ /* max number of packets handled per receive call */
+ __u32 sps_maxpkts_call;
+ /* avg number of packets handled per receive call */
+ __u32 sps_avgpkts_call;
+ /* total number of pages locked */
+ __u64 sps_pagelocks;
+ /* total number of pages unlocked */
+ __u64 sps_pageunlocks;
+ /*
+ * Number of packets dropped in kernel other than errors (ether
+ * packets if ipath not configured, sma/mad, etc.)
+ */
+ __u64 sps_krdrops;
+ /* mlids for up to 4 infinipaths, indexed by infinipath # */
+ __u16 sps_mlid[4];
+ /* pad for future growth */
+ __u64 __sps_pad[45];
+};
+
+/*
+ * These are the status bits readable (in ascii form, 64bit value)
+ * from the "status" sysfs file.
+ */
+#define IPATH_STATUS_INITTED 0x1 /* basic initialization done */
+#define IPATH_STATUS_DISABLED 0x2 /* hardware disabled */
+/* Device has been disabled via admin request */
+#define IPATH_STATUS_ADMIN_DISABLED 0x4
+#define IPATH_STATUS_OIB_SMA 0x8 /* ipath_mad kernel SMA running */
+#define IPATH_STATUS_SMA 0x10 /* user SMA running */
+/* Chip has been found and initted */
+#define IPATH_STATUS_CHIP_PRESENT 0x20
+/* IB link is at ACTIVE, usable for data traffic */
+#define IPATH_STATUS_IB_READY 0x40
+/* link is configured, LID, MTU, etc. have been set */
+#define IPATH_STATUS_IB_CONF 0x80
+/* no link established, probably no cable */
+#define IPATH_STATUS_IB_NOCABLE 0x100
+/* A Fatal hardware error has occurred. */
+#define IPATH_STATUS_HWERROR 0x200
+
+/*
+ * The list of usermode accessible registers. Also see Reg_* later in file.
+ */
+typedef enum _ipath_ureg {
+ /* (RO) DMA RcvHdr to be used next. */
+ ur_rcvhdrtail = 0,
+ /* (RW) RcvHdr entry to be processed next by host. */
+ ur_rcvhdrhead = 1,
+ /* (RO) Index of next Eager index to use. */
+ ur_rcvegrindextail = 2,
+ /* (RW) Eager TID to be processed next */
+ ur_rcvegrindexhead = 3,
+ /* For internal use only; max register number. */
+ _IPATH_UregMax
+} ipath_ureg;
+
+/* bit values for spi_runtime_flags */
+#define IPATH_RUNTIME_HT 0x1
+#define IPATH_RUNTIME_PCIE 0x2
+#define IPATH_RUNTIME_FORCE_WC_ORDER 0x4
+#define IPATH_RUNTIME_RCVHDR_COPY 0x8
+
+/*
+ * This structure is returned by ipath_userinit() immediately after
+ * open to get implementation-specific info, and info specific to this
+ * instance.
+ *
+ * This struct must have explict pad fields where type sizes
+ * may result in different alignments between 32 and 64 bit
+ * programs, since the 64 bit * bit kernel requires the user code
+ * to have matching offsets
+ */
+struct ipath_base_info {
+ /* version of hardware, for feature checking. */
+ __u32 spi_hw_version;
+ /* version of software, for feature checking. */
+ __u32 spi_sw_version;
+ /* InfiniPath port assigned, goes into sent packets */
+ __u32 spi_port;
+ /*
+ * IB MTU, packets IB data must be less than this.
+ * The MTU is in bytes, and will be a multiple of 4 bytes.
+ */
+ __u32 spi_mtu;
+ /*
+ * Size of a PIO buffer. Any given packet's total size must be less
+ * than this (in words). Included is the starting control word, so
+ * if 513 is returned, then total pkt size is 512 words or less.
+ */
+ __u32 spi_piosize;
+ /* size of the TID cache in infinipath, in entries */
+ __u32 spi_tidcnt;
+ /* size of the TID Eager list in infinipath, in entries */
+ __u32 spi_tidegrcnt;
+ /* size of a single receive header queue entry. */
+ __u32 spi_rcvhdrent_size;
+ /*
+ * Count of receive header queue entries allocated.
+ * This may be less than the spu_rcvhdrcnt passed in!.
+ */
+ __u32 spi_rcvhdr_cnt;
+
+ /* per-chip and other runtime features bitmap (IPATH_RUNTIME_*) */
+ __u32 spi_runtime_flags;
+
+ /* address where receive buffer queue is mapped into */
+ __u64 spi_rcvhdr_base;
+
+ /* user program. */
+
+ /* base address of eager TID receive buffers. */
+ __u64 spi_rcv_egrbufs;
+
+ /* Allocated by initialization code, not by protocol. */
+
+ /*
+ * Size of each TID buffer in host memory, starting at
+ * spi_rcv_egrbufs. The buffers are virtually contiguous.
+ */
+ __u32 spi_rcv_egrbufsize;
+ /*
+ * The special QP (queue pair) value that identifies an infinipath
+ * protocol packet from standard IB packets. More, probably much
+ * more, to be added.
+ */
+ __u32 spi_qpair;
+
+ /*
+ * User register base for init code, not to be used directly by
+ * protocol or applications.
+ */
+ __u64 __spi_uregbase;
+ /*
+ * Maximum buffer size in bytes that can be used in a single TID
+ * entry (assuming the buffer is aligned to this boundary). This is
+ * the minimum of what the hardware and software support Guaranteed
+ * to be a power of 2.
+ */
+ __u32 spi_tid_maxsize;
+ /*
+ * alignment of each pio send buffer (byte count
+ * to add to spi_piobufbase to get to second buffer)
+ */
+ __u32 spi_pioalign;
+ /*
+ * The index of the first pio buffer available to this process;
+ * needed to do lookup in spi_pioavailaddr; not added to
+ * spi_piobufbase.
+ */
+ __u32 spi_pioindex;
+ /* number of buffers mapped for this process */
+ __u32 spi_piocnt;
+
+ /*
+ * Base address of writeonly pio buffers for this process.
+ * Each buffer has spi_piosize words, and is aligned on spi_pioalign
+ * boundaries. spi_piocnt buffers are mapped from this address
+ */
+ __u64 spi_piobufbase;
+
+ /*
+ * Base address of readonly memory copy of the pioavail registers.
+ * There are 2 bits for each buffer.
+ */
+ __u64 spi_pioavailaddr;
+
+ /*
+ * Address where driver updates a copy of the interface and driver
+ * status (IPATH_STATUS_*) as a 64 bit value. It's followed by a
+ * string indicating hardware error, if there was one.
+ */
+ __u64 spi_status;
+
+ /* number of chip ports available to user processes */
+ __u32 spi_nports;
+ /* unit number of chip we are using */
+ __u32 spi_unit;
+ /* num bufs in each contiguous set */
+ __u32 spi_rcv_egrperchunk;
+ /* size in bytes of each contiguous set */
+ __u32 spi_rcv_egrchunksize;
+ /* total size of mmap to cover full rcvegrbuffers */
+ __u32 spi_rcv_egrbuftotlen;
+} __attribute__ ((aligned(8)));
+
+
+/*
+ * This version number is given to the driver by the user code during
+ * initialization in the spu_userversion field of ipath_user_info, so
+ * the driver can check for compatibility with user code.
+ *
+ * The major version changes when data structures
+ * change in an incompatible way. The driver must be the same or higher
+ * for initialization to succeed. In some cases, a higher version
+ * driver will not interoperate with older software, and initialization
+ * will return an error.
+ */
+#define IPATH_USER_SWMAJOR 1
+
+/*
+ * Minor version differences are always compatible
+ * a within a major version, however if if user software is larger
+ * than driver software, some new features and/or structure fields
+ * may not be implemented; the user code must deal with this if it
+ * cares, or it must abort after initialization reports the difference
+ */
+#define IPATH_USER_SWMINOR 2
+
+#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
+
+#define IPATH_KERN_TYPE 0
+
+/*
+ * Similarly, this is the kernel version going back to the user. It's
+ * slightly different, in that we want to tell if the driver was built as
+ * part of a PathScale release, or from the driver from OpenIB, kernel.org,
+ * or a standard distribution, for support reasons. The high bit is 0 for
+ * non-PathScale, and 1 for PathScale-built/supplied.
+ *
+ * It's returned by the driver to the user code during initialization in the
+ * spi_sw_version field of ipath_base_info, so the user code can in turn
+ * check for compatibility with the kernel.
+*/
+#define IPATH_KERN_SWVERSION ((IPATH_KERN_TYPE<<31) | IPATH_USER_SWVERSION)
+
+/*
+ * This structure is passed to ipath_userinit() to tell the driver where
+ * user code buffers are, sizes, etc. The offsets and sizes of the
+ * fields must remain unchanged, for binary compatibility. It can
+ * be extended, if userversion is changed so user code can tell, if needed
+ */
+struct ipath_user_info {
+ /*
+ * version of user software, to detect compatibility issues.
+ * Should be set to IPATH_USER_SWVERSION.
+ */
+ __u32 spu_userversion;
+
+ /* desired number of receive header queue entries */
+ __u32 spu_rcvhdrcnt;
+
+ /* size of struct base_info to write to */
+ __u32 spu_base_info_size;
+
+ /*
+ * number of words in KD protocol header
+ * This tells InfiniPath how many words to copy to rcvhdrq. If 0,
+ * kernel uses a default. Once set, attempts to set any other value
+ * are an error (EAGAIN) until driver is reloaded.
+ */
+ __u32 spu_rcvhdrsize;
+
+ /*
+ * cache line aligned (64 byte) user address to
+ * which the rcvhdrtail register will be written by infinipath
+ * whenever it changes, so that no chip registers are read in
+ * the performance path.
+ */
+ __u64 spu_rcvhdraddr;
+
+ /*
+ * address of struct base_info to write to
+ */
+ __u64 spu_base_info;
+
+} __attribute__ ((aligned(8)));
+
+/* User commands. */
+
+#define IPATH_CMD_MIN 16
+
+#define IPATH_CMD_USER_INIT 16 /* set up userspace */
+#define IPATH_CMD_PORT_INFO 17 /* find out what resources we got */
+#define IPATH_CMD_RECV_CTRL 18 /* control receipt of packets */
+#define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */
+#define IPATH_CMD_TID_FREE 20 /* free expected TID entries */
+#define IPATH_CMD_SET_PART_KEY 21 /* add partition key */
+
+#define IPATH_CMD_MAX 21
+
+struct ipath_port_info {
+ __u32 num_active; /* number of active units */
+ __u32 unit; /* unit (chip) assigned to caller */
+ __u32 port; /* port on unit assigned to caller */
+};
+
+struct ipath_tid_info {
+ __u32 tidcnt;
+ /* make structure same size in 32 and 64 bit */
+ __u32 tid__unused;
+ /* virtual address of first page in transfer */
+ __u64 tidvaddr;
+ /* pointer (same size 32/64 bit) to __u16 tid array */
+ __u64 tidlist;
+
+ /*
+ * pointer (same size 32/64 bit) to bitmap of TIDs used
+ * for this call; checked for being large enough at open
+ */
+ __u64 tidmap;
+};
+
+struct ipath_cmd {
+ __u32 type; /* command type */
+ union {
+ struct ipath_tid_info tid_info;
+ struct ipath_user_info user_info;
+ /* address in userspace of struct ipath_port_info to
+ write result to */
+ __u64 port_info;
+ /* enable/disable receipt of packets */
+ __u32 recv_ctrl;
+ /* partition key to set */
+ __u16 part_key;
+ } cmd;
+};
+
+struct ipath_iovec {
+ /* Pointer to data, but same size 32 and 64 bit */
+ __u64 iov_base;
+
+ /*
+ * Length of data; don't need 64 bits, but want
+ * ipath_sendpkt to remain same size as before 32 bit changes, so...
+ */
+ __u64 iov_len;
+};
+
+/*
+ * Describes a single packet for send. Each packet can have one or more
+ * buffers, but the total length (exclusive of IB headers) must be less
+ * than the MTU, and if using the PIO method, entire packet length,
+ * including IB headers, must be less than the ipath_piosize value (words).
+ * Use of this necessitates including sys/uio.h
+ */
+struct __ipath_sendpkt {
+ __u32 sps_flags; /* flags for packet (TBD) */
+ __u32 sps_cnt; /* number of entries to use in sps_iov */
+ /* array of iov's describing packet. TEMPORARY */
+ struct ipath_iovec sps_iov[4];
+};
+
+/* Passed into SMA special file's ->read and ->write methods. */
+struct ipath_sma_pkt
+{
+ __u32 unit; /* unit on which to send packet */
+ __u64 data; /* address of payload in userspace */
+ __u32 len; /* length of payload */
+};
+
+/*
+ * Data layout in I2C flash (for GUID, etc.)
+ * All fields are little-endian binary unless otherwise stated
+ */
+#define IPATH_FLASH_VERSION 1
+struct ipath_flash {
+ /* flash layout version (IPATH_FLASH_VERSION) */
+ __u8 if_fversion;
+ /* checksum protecting if_length bytes */
+ __u8 if_csum;
+ /*
+ * valid length (in use, protected by if_csum), including
+ * if_fversion and if_sum themselves)
+ */
+ __u8 if_length;
+ /* the GUID, in network order */
+ __u8 if_guid[8];
+ /* number of GUIDs to use, starting from if_guid */
+ __u8 if_numguid;
+ /* the board serial number, in ASCII */
+ char if_serial[12];
+ /* board mfg date (YYYYMMDD ASCII) */
+ char if_mfgdate[8];
+ /* last board rework/test date (YYYYMMDD ASCII) */
+ char if_testdate[8];
+ /* logging of error counts, TBD */
+ __u8 if_errcntp[4];
+ /* powered on hours, updated at driver unload */
+ __u8 if_powerhour[2];
+ /* ASCII free-form comment field */
+ char if_comment[32];
+ /* 78 bytes used, min flash size is 128 bytes */
+ __u8 if_future[50];
+};
+
+/*
+ * These are the counters implemented in the chip, and are listed in order.
+ * The InterCaps naming is taken straight from the chip spec.
+ */
+struct infinipath_counters {
+ __u64 LBIntCnt;
+ __u64 LBFlowStallCnt;
+ __u64 Reserved1;
+ __u64 TxUnsupVLErrCnt;
+ __u64 TxDataPktCnt;
+ __u64 TxFlowPktCnt;
+ __u64 TxDwordCnt;
+ __u64 TxLenErrCnt;
+ __u64 TxMaxMinLenErrCnt;
+ __u64 TxUnderrunCnt;
+ __u64 TxFlowStallCnt;
+ __u64 TxDroppedPktCnt;
+ __u64 RxDroppedPktCnt;
+ __u64 RxDataPktCnt;
+ __u64 RxFlowPktCnt;
+ __u64 RxDwordCnt;
+ __u64 RxLenErrCnt;
+ __u64 RxMaxMinLenErrCnt;
+ __u64 RxICRCErrCnt;
+ __u64 RxVCRCErrCnt;
+ __u64 RxFlowCtrlErrCnt;
+ __u64 RxBadFormatCnt;
+ __u64 RxLinkProblemCnt;
+ __u64 RxEBPCnt;
+ __u64 RxLPCRCErrCnt;
+ __u64 RxBufOvflCnt;
+ __u64 RxTIDFullErrCnt;
+ __u64 RxTIDValidErrCnt;
+ __u64 RxPKeyMismatchCnt;
+ __u64 RxP0HdrEgrOvflCnt;
+ __u64 RxP1HdrEgrOvflCnt;
+ __u64 RxP2HdrEgrOvflCnt;
+ __u64 RxP3HdrEgrOvflCnt;
+ __u64 RxP4HdrEgrOvflCnt;
+ __u64 RxP5HdrEgrOvflCnt;
+ __u64 RxP6HdrEgrOvflCnt;
+ __u64 RxP7HdrEgrOvflCnt;
+ __u64 RxP8HdrEgrOvflCnt;
+ __u64 Reserved6;
+ __u64 Reserved7;
+ __u64 IBStatusChangeCnt;
+ __u64 IBLinkErrRecoveryCnt;
+ __u64 IBLinkDownedCnt;
+ __u64 IBSymbolErrCnt;
+};
+
+/*
+ * The next set of defines are for packet headers, and chip register
+ * and memory bits that are visible to and/or used by user-mode software
+ * The other bits that are used only by the driver or diags are in
+ * ipath_registers.h
+ */
+
+/* RcvHdrFlags bits */
+#define INFINIPATH_RHF_LENGTH_MASK 0x7FF
+#define INFINIPATH_RHF_LENGTH_SHIFT 0
+#define INFINIPATH_RHF_RCVTYPE_MASK 0x7
+#define INFINIPATH_RHF_RCVTYPE_SHIFT 11
+#define INFINIPATH_RHF_EGRINDEX_MASK 0x7FF
+#define INFINIPATH_RHF_EGRINDEX_SHIFT 16
+#define INFINIPATH_RHF_H_ICRCERR 0x80000000
+#define INFINIPATH_RHF_H_VCRCERR 0x40000000
+#define INFINIPATH_RHF_H_PARITYERR 0x20000000
+#define INFINIPATH_RHF_H_LENERR 0x10000000
+#define INFINIPATH_RHF_H_MTUERR 0x08000000
+#define INFINIPATH_RHF_H_IHDRERR 0x04000000
+#define INFINIPATH_RHF_H_TIDERR 0x02000000
+#define INFINIPATH_RHF_H_MKERR 0x01000000
+#define INFINIPATH_RHF_H_IBERR 0x00800000
+#define INFINIPATH_RHF_L_SWA 0x00008000
+#define INFINIPATH_RHF_L_SWB 0x00004000
+
+/* infinipath header fields */
+#define INFINIPATH_I_VERS_MASK 0xF
+#define INFINIPATH_I_VERS_SHIFT 28
+#define INFINIPATH_I_PORT_MASK 0xF
+#define INFINIPATH_I_PORT_SHIFT 24
+#define INFINIPATH_I_TID_MASK 0x7FF
+#define INFINIPATH_I_TID_SHIFT 13
+#define INFINIPATH_I_OFFSET_MASK 0x1FFF
+#define INFINIPATH_I_OFFSET_SHIFT 0
+
+/* K_PktFlags bits */
+#define INFINIPATH_KPF_INTR 0x1
+
+/* SendPIO per-buffer control */
+#define INFINIPATH_SP_LENGTHP1_MASK 0x3FF
+#define INFINIPATH_SP_LENGTHP1_SHIFT 0
+#define INFINIPATH_SP_INTR 0x80000000
+#define INFINIPATH_SP_TEST 0x40000000
+#define INFINIPATH_SP_TESTEBP 0x20000000
+
+/* SendPIOAvail bits */
+#define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1
+#define INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT 0
+
+#endif /* _IPATH_COMMON_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
new file mode 100644
index 000000000000..7ece1135ddfe
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_cq_enter - add a new entry to the completion queue
+ * @cq: completion queue
+ * @entry: work completion entry to add
+ * @sig: true if @entry is a solicitated entry
+ *
+ * This may be called with one of the qp->s_lock or qp->r_rq.lock held.
+ */
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
+{
+ unsigned long flags;
+ u32 next;
+
+ spin_lock_irqsave(&cq->lock, flags);
+
+ if (cq->head == cq->ibcq.cqe)
+ next = 0;
+ else
+ next = cq->head + 1;
+ if (unlikely(next == cq->tail)) {
+ spin_unlock_irqrestore(&cq->lock, flags);
+ if (cq->ibcq.event_handler) {
+ struct ib_event ev;
+
+ ev.device = cq->ibcq.device;
+ ev.element.cq = &cq->ibcq;
+ ev.event = IB_EVENT_CQ_ERR;
+ cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);
+ }
+ return;
+ }
+ cq->queue[cq->head] = *entry;
+ cq->head = next;
+
+ if (cq->notify == IB_CQ_NEXT_COMP ||
+ (cq->notify == IB_CQ_SOLICITED && solicited)) {
+ cq->notify = IB_CQ_NONE;
+ cq->triggered++;
+ /*
+ * This will cause send_complete() to be called in
+ * another thread.
+ */
+ tasklet_hi_schedule(&cq->comptask);
+ }
+
+ spin_unlock_irqrestore(&cq->lock, flags);
+
+ if (entry->status != IB_WC_SUCCESS)
+ to_idev(cq->ibcq.device)->n_wqe_errs++;
+}
+
+/**
+ * ipath_poll_cq - poll for work completion entries
+ * @ibcq: the completion queue to poll
+ * @num_entries: the maximum number of entries to return
+ * @entry: pointer to array where work completions are placed
+ *
+ * Returns the number of completion entries polled.
+ *
+ * This may be called from interrupt context. Also called by ib_poll_cq()
+ * in the generic verbs code.
+ */
+int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+ unsigned long flags;
+ int npolled;
+
+ spin_lock_irqsave(&cq->lock, flags);
+
+ for (npolled = 0; npolled < num_entries; ++npolled, ++entry) {
+ if (cq->tail == cq->head)
+ break;
+ *entry = cq->queue[cq->tail];
+ if (cq->tail == cq->ibcq.cqe)
+ cq->tail = 0;
+ else
+ cq->tail++;
+ }
+
+ spin_unlock_irqrestore(&cq->lock, flags);
+
+ return npolled;
+}
+
+static void send_complete(unsigned long data)
+{
+ struct ipath_cq *cq = (struct ipath_cq *)data;
+
+ /*
+ * The completion handler will most likely rearm the notification
+ * and poll for all pending entries. If a new completion entry
+ * is added while we are in this routine, tasklet_hi_schedule()
+ * won't call us again until we return so we check triggered to
+ * see if we need to call the handler again.
+ */
+ for (;;) {
+ u8 triggered = cq->triggered;
+
+ cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+
+ if (cq->triggered == triggered)
+ return;
+ }
+}
+
+/**
+ * ipath_create_cq - create a completion queue
+ * @ibdev: the device this completion queue is attached to
+ * @entries: the minimum size of the completion queue
+ * @context: unused by the InfiniPath driver
+ * @udata: unused by the InfiniPath driver
+ *
+ * Returns a pointer to the completion queue or negative errno values
+ * for failure.
+ *
+ * Called by ib_create_cq() in the generic verbs code.
+ */
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct ipath_cq *cq;
+ struct ib_wc *wc;
+ struct ib_cq *ret;
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of
+ * entries.
+ */
+ cq = kmalloc(sizeof(*cq), GFP_KERNEL);
+ if (!cq) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of entries.
+ */
+ wc = vmalloc(sizeof(*wc) * (entries + 1));
+ if (!wc) {
+ kfree(cq);
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+ /*
+ * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe.
+ * The number of entries should be >= the number requested or return
+ * an error.
+ */
+ cq->ibcq.cqe = entries;
+ cq->notify = IB_CQ_NONE;
+ cq->triggered = 0;
+ spin_lock_init(&cq->lock);
+ tasklet_init(&cq->comptask, send_complete, (unsigned long)cq);
+ cq->head = 0;
+ cq->tail = 0;
+ cq->queue = wc;
+
+ ret = &cq->ibcq;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_destroy_cq - destroy a completion queue
+ * @ibcq: the completion queue to destroy.
+ *
+ * Returns 0 for success.
+ *
+ * Called by ib_destroy_cq() in the generic verbs code.
+ */
+int ipath_destroy_cq(struct ib_cq *ibcq)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+
+ tasklet_kill(&cq->comptask);
+ vfree(cq->queue);
+ kfree(cq);
+
+ return 0;
+}
+
+/**
+ * ipath_req_notify_cq - change the notification type for a completion queue
+ * @ibcq: the completion queue
+ * @notify: the type of notification to request
+ *
+ * Returns 0 for success.
+ *
+ * This may be called from interrupt context. Also called by
+ * ib_req_notify_cq() in the generic verbs code.
+ */
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&cq->lock, flags);
+ /*
+ * Don't change IB_CQ_NEXT_COMP to IB_CQ_SOLICITED but allow
+ * any other transitions.
+ */
+ if (cq->notify != IB_CQ_NEXT_COMP)
+ cq->notify = notify;
+ spin_unlock_irqrestore(&cq->lock, flags);
+ return 0;
+}
+
+int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+ struct ib_wc *wc, *old_wc;
+ u32 n;
+ int ret;
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of entries.
+ */
+ wc = vmalloc(sizeof(*wc) * (cqe + 1));
+ if (!wc) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irq(&cq->lock);
+ if (cq->head < cq->tail)
+ n = cq->ibcq.cqe + 1 + cq->head - cq->tail;
+ else
+ n = cq->head - cq->tail;
+ if (unlikely((u32)cqe < n)) {
+ spin_unlock_irq(&cq->lock);
+ vfree(wc);
+ ret = -EOVERFLOW;
+ goto bail;
+ }
+ for (n = 0; cq->tail != cq->head; n++) {
+ wc[n] = cq->queue[cq->tail];
+ if (cq->tail == cq->ibcq.cqe)
+ cq->tail = 0;
+ else
+ cq->tail++;
+ }
+ cq->ibcq.cqe = cqe;
+ cq->head = n;
+ cq->tail = 0;
+ old_wc = cq->queue;
+ cq->queue = wc;
+ spin_unlock_irq(&cq->lock);
+
+ vfree(old_wc);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
new file mode 100644
index 000000000000..593e28969c69
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_DEBUG_H
+#define _IPATH_DEBUG_H
+
+#ifndef _IPATH_DEBUGGING /* debugging enabled or not */
+#define _IPATH_DEBUGGING 1
+#endif
+
+#if _IPATH_DEBUGGING
+
+/*
+ * Mask values for debugging. The scheme allows us to compile out any
+ * of the debug tracing stuff, and if compiled in, to enable or disable
+ * dynamically. This can be set at modprobe time also:
+ * modprobe infinipath.ko infinipath_debug=7
+ */
+
+#define __IPATH_INFO 0x1 /* generic low verbosity stuff */
+#define __IPATH_DBG 0x2 /* generic debug */
+#define __IPATH_TRSAMPLE 0x8 /* generate trace buffer sample entries */
+/* leave some low verbosity spots open */
+#define __IPATH_VERBDBG 0x40 /* very verbose debug */
+#define __IPATH_PKTDBG 0x80 /* print packet data */
+/* print process startup (init)/exit messages */
+#define __IPATH_PROCDBG 0x100
+/* print mmap/nopage stuff, not using VDBG any more */
+#define __IPATH_MMDBG 0x200
+#define __IPATH_USER_SEND 0x1000 /* use user mode send */
+#define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */
+#define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */
+#define __IPATH_SMADBG 0x8000 /* sma packet debug */
+#define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) general debug on */
+#define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings on */
+#define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors on */
+#define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump on */
+#define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump on */
+
+#else /* _IPATH_DEBUGGING */
+
+/*
+ * define all of these even with debugging off, for the few places that do
+ * if(infinipath_debug & _IPATH_xyzzy), but in a way that will make the
+ * compiler eliminate the code
+ */
+
+#define __IPATH_INFO 0x0 /* generic low verbosity stuff */
+#define __IPATH_DBG 0x0 /* generic debug */
+#define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */
+#define __IPATH_VERBDBG 0x0 /* very verbose debug */
+#define __IPATH_PKTDBG 0x0 /* print packet data */
+#define __IPATH_PROCDBG 0x0 /* print process startup (init)/exit messages */
+/* print mmap/nopage stuff, not using VDBG any more */
+#define __IPATH_MMDBG 0x0
+#define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */
+#define __IPATH_SMADBG 0x0 /* print process startup (init)/exit messages */#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */
+#define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */
+#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */
+#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */
+#define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */
+
+#endif /* _IPATH_DEBUGGING */
+
+#define __IPATH_VERBOSEDBG __IPATH_VERBDBG
+
+#endif /* _IPATH_DEBUG_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
new file mode 100644
index 000000000000..7d3fb6996b41
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contains support for diagnostic functions. It is accessed by
+ * opening the ipath_diag device, normally minor number 129. Diagnostic use
+ * of the InfiniPath chip may render the chip or board unusable until the
+ * driver is unloaded, or in some cases, until the system is rebooted.
+ *
+ * Accesses to the chip through this interface are not similar to going
+ * through the /sys/bus/pci resource mmap interface.
+ */
+
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+#include "ipath_common.h"
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+int ipath_diag_inuse;
+static int diag_set_link;
+
+static int ipath_diag_open(struct inode *in, struct file *fp);
+static int ipath_diag_release(struct inode *in, struct file *fp);
+static ssize_t ipath_diag_read(struct file *fp, char __user *data,
+ size_t count, loff_t *off);
+static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
+ size_t count, loff_t *off);
+
+static struct file_operations diag_file_ops = {
+ .owner = THIS_MODULE,
+ .write = ipath_diag_write,
+ .read = ipath_diag_read,
+ .open = ipath_diag_open,
+ .release = ipath_diag_release
+};
+
+static struct cdev *diag_cdev;
+static struct class_device *diag_class_dev;
+
+int ipath_diag_init(void)
+{
+ return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag",
+ &diag_file_ops, &diag_cdev, &diag_class_dev);
+}
+
+void ipath_diag_cleanup(void)
+{
+ ipath_cdev_cleanup(&diag_cdev, &diag_class_dev);
+}
+
+/**
+ * ipath_read_umem64 - read a 64-bit quantity from the chip into user space
+ * @dd: the infinipath device
+ * @uaddr: the location to store the data in user memory
+ * @caddr: the source chip address (full pointer, not offset)
+ * @count: number of bytes to copy (multiple of 32 bits)
+ *
+ * This function also localizes all chip memory accesses.
+ * The copy should be written such that we read full cacheline packets
+ * from the chip. This is usually used for a single qword
+ *
+ * NOTE: This assumes the chip address is 64-bit aligned.
+ */
+static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
+ const void __iomem *caddr, size_t count)
+{
+ const u64 __iomem *reg_addr = caddr;
+ const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
+ int ret;
+
+ /* not very efficient, but it works for now */
+ if (reg_addr < dd->ipath_kregbase ||
+ reg_end > dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ while (reg_addr < reg_end) {
+ u64 data = readq(reg_addr);
+ if (copy_to_user(uaddr, &data, sizeof(u64))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+/**
+ * ipath_write_umem64 - write a 64-bit quantity to the chip from user space
+ * @dd: the infinipath device
+ * @caddr: the destination chip address (full pointer, not offset)
+ * @uaddr: the source of the data in user memory
+ * @count: the number of bytes to copy (multiple of 32 bits)
+ *
+ * This is usually used for a single qword
+ * NOTE: This assumes the chip address is 64-bit aligned.
+ */
+
+static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
+ const void __user *uaddr, size_t count)
+{
+ u64 __iomem *reg_addr = caddr;
+ const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
+ int ret;
+
+ /* not very efficient, but it works for now */
+ if (reg_addr < dd->ipath_kregbase ||
+ reg_end > dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ while (reg_addr < reg_end) {
+ u64 data;
+ if (copy_from_user(&data, uaddr, sizeof(data))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ writeq(data, reg_addr);
+
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+/**
+ * ipath_read_umem32 - read a 32-bit quantity from the chip into user space
+ * @dd: the infinipath device
+ * @uaddr: the location to store the data in user memory
+ * @caddr: the source chip address (full pointer, not offset)
+ * @count: number of bytes to copy
+ *
+ * read 32 bit values, not 64 bit; for memories that only
+ * support 32 bit reads; usually a single dword.
+ */
+static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr,
+ const void __iomem *caddr, size_t count)
+{
+ const u32 __iomem *reg_addr = caddr;
+ const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
+ int ret;
+
+ if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
+ reg_end > (u32 __iomem *) dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ /* not very efficient, but it works for now */
+ while (reg_addr < reg_end) {
+ u32 data = readl(reg_addr);
+ if (copy_to_user(uaddr, &data, sizeof(data))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+/**
+ * ipath_write_umem32 - write a 32-bit quantity to the chip from user space
+ * @dd: the infinipath device
+ * @caddr: the destination chip address (full pointer, not offset)
+ * @uaddr: the source of the data in user memory
+ * @count: number of bytes to copy
+ *
+ * write 32 bit values, not 64 bit; for memories that only
+ * support 32 bit write; usually a single dword.
+ */
+
+static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr,
+ const void __user *uaddr, size_t count)
+{
+ u32 __iomem *reg_addr = caddr;
+ const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
+ int ret;
+
+ if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
+ reg_end > (u32 __iomem *) dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ while (reg_addr < reg_end) {
+ u32 data;
+ if (copy_from_user(&data, uaddr, sizeof(data))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ writel(data, reg_addr);
+
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+static int ipath_diag_open(struct inode *in, struct file *fp)
+{
+ struct ipath_devdata *dd;
+ int unit = 0; /* XXX this is bogus */
+ unsigned long flags;
+ int ret;
+
+ dd = ipath_lookup(unit);
+
+ mutex_lock(&ipath_mutex);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ if (ipath_diag_inuse) {
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+ /*
+ * we need at least one infinipath device to be present
+ * (don't use INITTED, because we want to be able to open
+ * even if device is in freeze mode, which cleared INITTED).
+ * There is a small amount of risk to this, which is why we
+ * also verify kregbase is set.
+ */
+
+ if (!(dd->ipath_flags & IPATH_PRESENT) ||
+ !dd->ipath_kregbase)
+ continue;
+
+ ipath_diag_inuse = 1;
+ diag_set_link = 0;
+ ret = 0;
+ goto bail;
+ }
+
+ ret = -ENODEV;
+
+bail:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ mutex_unlock(&ipath_mutex);
+
+ /* Only expose a way to reset the device if we
+ make it into diag mode. */
+ if (ret == 0)
+ ipath_expose_reset(&dd->pcidev->dev);
+
+ return ret;
+}
+
+static int ipath_diag_release(struct inode *i, struct file *f)
+{
+ mutex_lock(&ipath_mutex);
+ ipath_diag_inuse = 0;
+ mutex_unlock(&ipath_mutex);
+ return 0;
+}
+
+static ssize_t ipath_diag_read(struct file *fp, char __user *data,
+ size_t count, loff_t *off)
+{
+ int unit = 0; /* XXX provide for reads on other units some day */
+ struct ipath_devdata *dd;
+ void __iomem *kreg_base;
+ ssize_t ret;
+
+ dd = ipath_lookup(unit);
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ kreg_base = dd->ipath_kregbase;
+
+ if (count == 0)
+ ret = 0;
+ else if ((count % 4) || (*off % 4))
+ /* address or length is not 32-bit aligned, hence invalid */
+ ret = -EINVAL;
+ else if ((count % 8) || (*off % 8))
+ /* address or length not 64-bit aligned; do 32-bit reads */
+ ret = ipath_read_umem32(dd, data, kreg_base + *off, count);
+ else
+ ret = ipath_read_umem64(dd, data, kreg_base + *off, count);
+
+ if (ret >= 0) {
+ *off += count;
+ ret = count;
+ }
+
+bail:
+ return ret;
+}
+
+static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
+ size_t count, loff_t *off)
+{
+ int unit = 0; /* XXX this is bogus */
+ struct ipath_devdata *dd;
+ void __iomem *kreg_base;
+ ssize_t ret;
+
+ dd = ipath_lookup(unit);
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+ kreg_base = dd->ipath_kregbase;
+
+ if (count == 0)
+ ret = 0;
+ else if ((count % 4) || (*off % 4))
+ /* address or length is not 32-bit aligned, hence invalid */
+ ret = -EINVAL;
+ else if ((count % 8) || (*off % 8))
+ /* address or length not 64-bit aligned; do 32-bit writes */
+ ret = ipath_write_umem32(dd, kreg_base + *off, data, count);
+ else
+ ret = ipath_write_umem64(dd, kreg_base + *off, data, count);
+
+ if (ret >= 0) {
+ *off += count;
+ ret = count;
+ }
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
new file mode 100644
index 000000000000..e7617c3982ea
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -0,0 +1,1983 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+static void ipath_update_pio_bufs(struct ipath_devdata *);
+
+const char *ipath_get_unit_name(int unit)
+{
+ static char iname[16];
+ snprintf(iname, sizeof iname, "infinipath%u", unit);
+ return iname;
+}
+
+EXPORT_SYMBOL_GPL(ipath_get_unit_name);
+
+#define DRIVER_LOAD_MSG "PathScale " IPATH_DRV_NAME " loaded: "
+#define PFX IPATH_DRV_NAME ": "
+
+/*
+ * The size has to be longer than this string, so we can append
+ * board/chip information to it in the init code.
+ */
+const char ipath_core_version[] = IPATH_IDSTR "\n";
+
+static struct idr unit_table;
+DEFINE_SPINLOCK(ipath_devs_lock);
+LIST_HEAD(ipath_dev_list);
+
+wait_queue_head_t ipath_sma_state_wait;
+
+unsigned ipath_debug = __IPATH_INFO;
+
+module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "mask for debug prints");
+EXPORT_SYMBOL_GPL(ipath_debug);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("PathScale <support@pathscale.com>");
+MODULE_DESCRIPTION("Pathscale InfiniPath driver");
+
+const char *ipath_ibcstatus_str[] = {
+ "Disabled",
+ "LinkUp",
+ "PollActive",
+ "PollQuiet",
+ "SleepDelay",
+ "SleepQuiet",
+ "LState6", /* unused */
+ "LState7", /* unused */
+ "CfgDebounce",
+ "CfgRcvfCfg",
+ "CfgWaitRmt",
+ "CfgIdle",
+ "RecovRetrain",
+ "LState0xD", /* unused */
+ "RecovWaitRmt",
+ "RecovIdle",
+};
+
+/*
+ * These variables are initialized in the chip-specific files
+ * but are defined here.
+ */
+u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
+u64 ipath_gpio_sda, ipath_gpio_scl;
+u64 infinipath_i_bitsextant;
+ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
+u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
+
+static void __devexit ipath_remove_one(struct pci_dev *);
+static int __devinit ipath_init_one(struct pci_dev *,
+ const struct pci_device_id *);
+
+/* Only needed for registration, nothing else needs this info */
+#define PCI_VENDOR_ID_PATHSCALE 0x1fc1
+#define PCI_DEVICE_ID_INFINIPATH_HT 0xd
+#define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
+
+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)},
+};
+
+MODULE_DEVICE_TABLE(pci, ipath_pci_tbl);
+
+static struct pci_driver ipath_driver = {
+ .name = IPATH_DRV_NAME,
+ .probe = ipath_init_one,
+ .remove = __devexit_p(ipath_remove_one),
+ .id_table = ipath_pci_tbl,
+};
+
+/*
+ * This is where port 0's rcvhdrtail register is written back; we also
+ * want nothing else sharing the cache line, so make it a cache line
+ * in size. Used for all units.
+ */
+volatile __le64 *ipath_port0_rcvhdrtail;
+dma_addr_t ipath_port0_rcvhdrtail_dma;
+static int port0_rcvhdrtail_refs;
+
+static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
+ u32 *bar0, u32 *bar1)
+{
+ int ret;
+
+ ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
+ if (ret)
+ ipath_dev_err(dd, "failed to read bar0 before enable: "
+ "error %d\n", -ret);
+
+ ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, bar1);
+ if (ret)
+ ipath_dev_err(dd, "failed to read bar1 before enable: "
+ "error %d\n", -ret);
+
+ ipath_dbg("Read bar0 %x bar1 %x\n", *bar0, *bar1);
+}
+
+static void ipath_free_devdata(struct pci_dev *pdev,
+ struct ipath_devdata *dd)
+{
+ unsigned long flags;
+
+ pci_set_drvdata(pdev, NULL);
+
+ if (dd->ipath_unit != -1) {
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ idr_remove(&unit_table, dd->ipath_unit);
+ list_del(&dd->ipath_list);
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ }
+ dma_free_coherent(&pdev->dev, sizeof(*dd), dd, dd->ipath_dma_addr);
+}
+
+static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
+{
+ unsigned long flags;
+ struct ipath_devdata *dd;
+ dma_addr_t dma_addr;
+ int ret;
+
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+ dd = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ dd = dma_alloc_coherent(&pdev->dev, sizeof(*dd), &dma_addr,
+ GFP_KERNEL);
+
+ if (!dd) {
+ dd = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ dd->ipath_dma_addr = dma_addr;
+ dd->ipath_unit = -1;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ ret = idr_get_new(&unit_table, dd, &dd->ipath_unit);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate unit ID: error %d\n", -ret);
+ ipath_free_devdata(pdev, dd);
+ dd = ERR_PTR(ret);
+ goto bail_unlock;
+ }
+
+ dd->pcidev = pdev;
+ pci_set_drvdata(pdev, dd);
+
+ list_add(&dd->ipath_list, &ipath_dev_list);
+
+bail_unlock:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+bail:
+ return dd;
+}
+
+static inline struct ipath_devdata *__ipath_lookup(int unit)
+{
+ return idr_find(&unit_table, unit);
+}
+
+struct ipath_devdata *ipath_lookup(int unit)
+{
+ struct ipath_devdata *dd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ dd = __ipath_lookup(unit);
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ return dd;
+}
+
+int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
+{
+ int nunits, npresent, nup;
+ struct ipath_devdata *dd;
+ unsigned long flags;
+ u32 maxports;
+
+ nunits = npresent = nup = maxports = 0;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+ nunits++;
+ if ((dd->ipath_flags & IPATH_PRESENT) && dd->ipath_kregbase)
+ npresent++;
+ if (dd->ipath_lid &&
+ !(dd->ipath_flags & (IPATH_DISABLED | IPATH_LINKDOWN
+ | IPATH_LINKUNK)))
+ nup++;
+ if (dd->ipath_cfgports > maxports)
+ maxports = dd->ipath_cfgports;
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ if (npresentp)
+ *npresentp = npresent;
+ if (nupp)
+ *nupp = nup;
+ if (maxportsp)
+ *maxportsp = maxports;
+
+ return nunits;
+}
+
+static int init_port0_rcvhdrtail(struct pci_dev *pdev)
+{
+ int ret;
+
+ mutex_lock(&ipath_mutex);
+
+ if (!ipath_port0_rcvhdrtail) {
+ ipath_port0_rcvhdrtail =
+ dma_alloc_coherent(&pdev->dev,
+ IPATH_PORT0_RCVHDRTAIL_SIZE,
+ &ipath_port0_rcvhdrtail_dma,
+ GFP_KERNEL);
+
+ if (!ipath_port0_rcvhdrtail) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ }
+ port0_rcvhdrtail_refs++;
+ ret = 0;
+
+bail:
+ mutex_unlock(&ipath_mutex);
+
+ return ret;
+}
+
+static void cleanup_port0_rcvhdrtail(struct pci_dev *pdev)
+{
+ mutex_lock(&ipath_mutex);
+
+ if (!--port0_rcvhdrtail_refs) {
+ dma_free_coherent(&pdev->dev, IPATH_PORT0_RCVHDRTAIL_SIZE,
+ (void *) ipath_port0_rcvhdrtail,
+ ipath_port0_rcvhdrtail_dma);
+ ipath_port0_rcvhdrtail = NULL;
+ }
+
+ mutex_unlock(&ipath_mutex);
+}
+
+/*
+ * These next two routines are placeholders in case we don't have per-arch
+ * code for controlling write combining. If explicit control of write
+ * combining is not available, performance will probably be awful.
+ */
+
+int __attribute__((weak)) ipath_enable_wc(struct ipath_devdata *dd)
+{
+ return -EOPNOTSUPP;
+}
+
+void __attribute__((weak)) ipath_disable_wc(struct ipath_devdata *dd)
+{
+}
+
+static int __devinit ipath_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int ret, len, j;
+ struct ipath_devdata *dd;
+ unsigned long long addr;
+ u32 bar0 = 0, bar1 = 0;
+ u8 rev;
+
+ ret = init_port0_rcvhdrtail(pdev);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate port0_rcvhdrtail: error %d\n",
+ -ret);
+ goto bail;
+ }
+
+ dd = ipath_alloc_devdata(pdev);
+ if (IS_ERR(dd)) {
+ ret = PTR_ERR(dd);
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate devdata: error %d\n", -ret);
+ goto bail_rcvhdrtail;
+ }
+
+ ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit);
+
+ read_bars(dd, pdev, &bar0, &bar1);
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ /* This can happen iff:
+ *
+ * We did a chip reset, and then failed to reprogram the
+ * BAR, or the chip reset due to an internal error. We then
+ * unloaded the driver and reloaded it.
+ *
+ * Both reset cases set the BAR back to initial state. For
+ * the latter case, the AER sticky error bit at offset 0x718
+ * should be set, but the Linux kernel doesn't yet know
+ * about that, it appears. If the original BAR was retained
+ * in the kernel data structures, this may be OK.
+ */
+ ipath_dev_err(dd, "enable unit %d failed: error %d\n",
+ dd->ipath_unit, -ret);
+ goto bail_devdata;
+ }
+ addr = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+ ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %x, vend %x/%x "
+ "driver_data %lx\n", addr, len, pdev->irq, ent->vendor,
+ ent->device, ent->driver_data);
+
+ read_bars(dd, pdev, &bar0, &bar1);
+
+ if (!bar1 && !(bar0 & ~0xf)) {
+ if (addr) {
+ dev_info(&pdev->dev, "BAR is 0 (probable RESET), "
+ "rewriting as %llx\n", addr);
+ ret = pci_write_config_dword(
+ pdev, PCI_BASE_ADDRESS_0, addr);
+ if (ret) {
+ ipath_dev_err(dd, "rewrite of BAR0 "
+ "failed: err %d\n", -ret);
+ goto bail_disable;
+ }
+ ret = pci_write_config_dword(
+ pdev, PCI_BASE_ADDRESS_1, addr >> 32);
+ if (ret) {
+ ipath_dev_err(dd, "rewrite of BAR1 "
+ "failed: err %d\n", -ret);
+ goto bail_disable;
+ }
+ } else {
+ ipath_dev_err(dd, "BAR is 0 (probable RESET), "
+ "not usable until reboot\n");
+ ret = -ENODEV;
+ goto bail_disable;
+ }
+ }
+
+ ret = pci_request_regions(pdev, IPATH_DRV_NAME);
+ if (ret) {
+ dev_info(&pdev->dev, "pci_request_regions unit %u fails: "
+ "err %d\n", dd->ipath_unit, -ret);
+ goto bail_disable;
+ }
+
+ ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (ret) {
+ dev_info(&pdev->dev, "pci_set_dma_mask unit %u "
+ "fails: %d\n", dd->ipath_unit, ret);
+ goto bail_regions;
+ }
+
+ pci_set_master(pdev);
+
+ /*
+ * Save BARs to rewrite after device reset. Save all 64 bits of
+ * BAR, just in case.
+ */
+ dd->ipath_pcibar0 = addr;
+ dd->ipath_pcibar1 = addr >> 32;
+ dd->ipath_deviceid = ent->device; /* save for later use */
+ dd->ipath_vendorid = ent->vendor;
+
+ /* setup the chip-specific functions, as early as possible. */
+ switch (ent->device) {
+ case PCI_DEVICE_ID_INFINIPATH_HT:
+ ipath_init_ht400_funcs(dd);
+ break;
+ case PCI_DEVICE_ID_INFINIPATH_PE800:
+ ipath_init_pe800_funcs(dd);
+ break;
+ default:
+ ipath_dev_err(dd, "Found unknown PathScale deviceid 0x%x, "
+ "failing\n", ent->device);
+ return -ENODEV;
+ }
+
+ for (j = 0; j < 6; j++) {
+ if (!pdev->resource[j].start)
+ continue;
+ ipath_cdbg(VERBOSE, "BAR %d start %lx, end %lx, len %lx\n",
+ j, pdev->resource[j].start,
+ pdev->resource[j].end,
+ pci_resource_len(pdev, j));
+ }
+
+ if (!addr) {
+ ipath_dev_err(dd, "No valid address in BAR 0!\n");
+ ret = -ENODEV;
+ goto bail_regions;
+ }
+
+ 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_kregbase = ioremap_nocache(addr, len);
+
+ if (!dd->ipath_kregbase) {
+ ipath_dbg("Unable to map io addr %llx to kvirt, failing\n",
+ addr);
+ ret = -ENOMEM;
+ goto bail_iounmap;
+ }
+ dd->ipath_kregend = (u64 __iomem *)
+ ((void __iomem *)dd->ipath_kregbase + len);
+ dd->ipath_physaddr = addr; /* used for io_remap, etc. */
+ /* for user mmap */
+ dd->ipath_kregvirt = (u64 __iomem *) phys_to_virt(addr);
+ ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p "
+ "kregvirt %p\n", addr, dd->ipath_kregbase,
+ dd->ipath_kregvirt);
+
+ /*
+ * clear ipath_flags here instead of in ipath_init_chip as it is set
+ * by ipath_setup_htconfig.
+ */
+ dd->ipath_flags = 0;
+
+ if (dd->ipath_f_bus(dd, pdev))
+ ipath_dev_err(dd, "Failed to setup config space; "
+ "continuing anyway\n");
+
+ /*
+ * set up our interrupt handler; SA_SHIRQ probably not needed,
+ * since MSI interrupts shouldn't be shared but won't hurt for now.
+ * check 0 irq after we return from chip-specific bus setup, since
+ * that can affect this due to setup
+ */
+ if (!pdev->irq)
+ ipath_dev_err(dd, "irq is 0, BIOS error? Interrupts won't "
+ "work\n");
+ else {
+ ret = request_irq(pdev->irq, ipath_intr, SA_SHIRQ,
+ IPATH_DRV_NAME, dd);
+ if (ret) {
+ ipath_dev_err(dd, "Couldn't setup irq handler, "
+ "irq=%u: %d\n", pdev->irq, ret);
+ goto bail_iounmap;
+ }
+ }
+
+ ret = ipath_init_chip(dd, 0); /* do the chip-specific init */
+ if (ret)
+ goto bail_iounmap;
+
+ ret = ipath_enable_wc(dd);
+
+ if (ret) {
+ ipath_dev_err(dd, "Write combining not enabled "
+ "(err %d): performance may be poor\n",
+ -ret);
+ ret = 0;
+ }
+
+ ipath_device_create_group(&pdev->dev, dd);
+ ipathfs_add_device(dd);
+ ipath_user_add(dd);
+ ipath_layer_add(dd);
+
+ goto bail;
+
+bail_iounmap:
+ iounmap((volatile void __iomem *) dd->ipath_kregbase);
+
+bail_regions:
+ pci_release_regions(pdev);
+
+bail_disable:
+ pci_disable_device(pdev);
+
+bail_devdata:
+ ipath_free_devdata(pdev, dd);
+
+bail_rcvhdrtail:
+ cleanup_port0_rcvhdrtail(pdev);
+
+bail:
+ return ret;
+}
+
+static void __devexit ipath_remove_one(struct pci_dev *pdev)
+{
+ struct ipath_devdata *dd;
+
+ ipath_cdbg(VERBOSE, "removing, pdev=%p\n", pdev);
+ if (!pdev)
+ return;
+
+ dd = pci_get_drvdata(pdev);
+ ipath_layer_del(dd);
+ ipath_user_del(dd);
+ ipathfs_remove_device(dd);
+ ipath_device_remove_group(&pdev->dev, dd);
+ ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, "
+ "unit %u\n", dd, (u32) dd->ipath_unit);
+ if (dd->ipath_kregbase) {
+ ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n",
+ dd->ipath_kregbase);
+ iounmap((volatile void __iomem *) dd->ipath_kregbase);
+ dd->ipath_kregbase = NULL;
+ }
+ pci_release_regions(pdev);
+ ipath_cdbg(VERBOSE, "calling pci_disable_device\n");
+ pci_disable_device(pdev);
+
+ ipath_free_devdata(pdev, dd);
+ cleanup_port0_rcvhdrtail(pdev);
+}
+
+/* general driver use */
+DEFINE_MUTEX(ipath_mutex);
+
+static DEFINE_SPINLOCK(ipath_pioavail_lock);
+
+/**
+ * ipath_disarm_piobufs - cancel a range of PIO buffers
+ * @dd: the infinipath device
+ * @first: the first PIO buffer to cancel
+ * @cnt: the number of PIO buffers to cancel
+ *
+ * cancel a range of PIO buffers, used when they might be armed, but
+ * not triggered. Used at init to ensure buffer state, and also user
+ * process close, in case it died while writing to a PIO buffer
+ * Also after errors.
+ */
+void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+ unsigned cnt)
+{
+ unsigned i, last = first + cnt;
+ u64 sendctrl, sendorig;
+
+ ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
+ sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM;
+ for (i = first; i < last; i++) {
+ sendctrl = sendorig |
+ (i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ sendctrl);
+ }
+
+ /*
+ * Write it again with current value, in case ipath_sendctrl changed
+ * while we were looping; no critical bits that would require
+ * locking.
+ *
+ * Write a 0, and then the original value, 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_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+}
+
+/**
+ * ipath_wait_linkstate - wait for an IB link state change to occur
+ * @dd: the infinipath device
+ * @state: the state to wait for
+ * @msecs: the number of milliseconds to wait
+ *
+ * wait up to msecs milliseconds for IB link state change to occur for
+ * now, take the easy polling route. Currently used only by
+ * ipath_layer_set_linkstate. Returns 0 if state reached, otherwise
+ * -ETIMEDOUT state can have multiple states set, for any of several
+ * transitions.
+ */
+int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
+{
+ dd->ipath_sma_state_wanted = state;
+ wait_event_interruptible_timeout(ipath_sma_state_wait,
+ (dd->ipath_flags & state),
+ msecs_to_jiffies(msecs));
+ dd->ipath_sma_state_wanted = 0;
+
+ if (!(dd->ipath_flags & state)) {
+ u64 val;
+ ipath_cdbg(SMA, "Didn't reach linkstate %s within %u ms\n",
+ /* test INIT ahead of DOWN, both can be set */
+ (state & IPATH_LINKINIT) ? "INIT" :
+ ((state & IPATH_LINKDOWN) ? "DOWN" :
+ ((state & IPATH_LINKARMED) ? "ARM" : "ACTIVE")),
+ msecs);
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ ipath_cdbg(VERBOSE, "ibcc=%llx ibcstatus=%llx (%s)\n",
+ (unsigned long long) ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_ibcctrl),
+ (unsigned long long) val,
+ ipath_ibcstatus_str[val & 0xf]);
+ }
+ return (dd->ipath_flags & state) ? 0 : -ETIMEDOUT;
+}
+
+void ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+{
+ *buf = '\0';
+ if (err & INFINIPATH_E_RHDRLEN)
+ strlcat(buf, "rhdrlen ", blen);
+ if (err & INFINIPATH_E_RBADTID)
+ strlcat(buf, "rbadtid ", blen);
+ if (err & INFINIPATH_E_RBADVERSION)
+ strlcat(buf, "rbadversion ", blen);
+ if (err & INFINIPATH_E_RHDR)
+ strlcat(buf, "rhdr ", blen);
+ if (err & INFINIPATH_E_RLONGPKTLEN)
+ strlcat(buf, "rlongpktlen ", blen);
+ if (err & INFINIPATH_E_RSHORTPKTLEN)
+ strlcat(buf, "rshortpktlen ", blen);
+ if (err & INFINIPATH_E_RMAXPKTLEN)
+ strlcat(buf, "rmaxpktlen ", blen);
+ if (err & INFINIPATH_E_RMINPKTLEN)
+ strlcat(buf, "rminpktlen ", blen);
+ if (err & INFINIPATH_E_RFORMATERR)
+ strlcat(buf, "rformaterr ", blen);
+ if (err & INFINIPATH_E_RUNSUPVL)
+ strlcat(buf, "runsupvl ", blen);
+ if (err & INFINIPATH_E_RUNEXPCHAR)
+ strlcat(buf, "runexpchar ", blen);
+ if (err & INFINIPATH_E_RIBFLOW)
+ strlcat(buf, "ribflow ", blen);
+ if (err & INFINIPATH_E_REBP)
+ strlcat(buf, "EBP ", blen);
+ if (err & INFINIPATH_E_SUNDERRUN)
+ strlcat(buf, "sunderrun ", blen);
+ if (err & INFINIPATH_E_SPIOARMLAUNCH)
+ strlcat(buf, "spioarmlaunch ", blen);
+ if (err & INFINIPATH_E_SUNEXPERRPKTNUM)
+ strlcat(buf, "sunexperrpktnum ", blen);
+ if (err & INFINIPATH_E_SDROPPEDDATAPKT)
+ strlcat(buf, "sdroppeddatapkt ", blen);
+ if (err & INFINIPATH_E_SDROPPEDSMPPKT)
+ strlcat(buf, "sdroppedsmppkt ", blen);
+ if (err & INFINIPATH_E_SMAXPKTLEN)
+ strlcat(buf, "smaxpktlen ", blen);
+ if (err & INFINIPATH_E_SMINPKTLEN)
+ strlcat(buf, "sminpktlen ", blen);
+ if (err & INFINIPATH_E_SUNSUPVL)
+ strlcat(buf, "sunsupVL ", blen);
+ if (err & INFINIPATH_E_SPKTLEN)
+ strlcat(buf, "spktlen ", blen);
+ if (err & INFINIPATH_E_INVALIDADDR)
+ strlcat(buf, "invalidaddr ", blen);
+ if (err & INFINIPATH_E_RICRC)
+ strlcat(buf, "CRC ", blen);
+ if (err & INFINIPATH_E_RVCRC)
+ strlcat(buf, "VCRC ", blen);
+ if (err & INFINIPATH_E_RRCVEGRFULL)
+ strlcat(buf, "rcvegrfull ", blen);
+ if (err & INFINIPATH_E_RRCVHDRFULL)
+ strlcat(buf, "rcvhdrfull ", blen);
+ if (err & INFINIPATH_E_IBSTATUSCHANGED)
+ strlcat(buf, "ibcstatuschg ", blen);
+ if (err & INFINIPATH_E_RIBLOSTLINK)
+ strlcat(buf, "riblostlink ", blen);
+ if (err & INFINIPATH_E_HARDWARE)
+ strlcat(buf, "hardware ", blen);
+ if (err & INFINIPATH_E_RESET)
+ strlcat(buf, "reset ", blen);
+}
+
+/**
+ * get_rhf_errstring - decode RHF errors
+ * @err: the err number
+ * @msg: the output buffer
+ * @len: the length of the output buffer
+ *
+ * only used one place now, may want more later
+ */
+static void get_rhf_errstring(u32 err, char *msg, size_t len)
+{
+ /* if no errors, and so don't need to check what's first */
+ *msg = '\0';
+
+ if (err & INFINIPATH_RHF_H_ICRCERR)
+ strlcat(msg, "icrcerr ", len);
+ if (err & INFINIPATH_RHF_H_VCRCERR)
+ strlcat(msg, "vcrcerr ", len);
+ if (err & INFINIPATH_RHF_H_PARITYERR)
+ strlcat(msg, "parityerr ", len);
+ if (err & INFINIPATH_RHF_H_LENERR)
+ strlcat(msg, "lenerr ", len);
+ if (err & INFINIPATH_RHF_H_MTUERR)
+ strlcat(msg, "mtuerr ", len);
+ if (err & INFINIPATH_RHF_H_IHDRERR)
+ /* infinipath hdr checksum error */
+ strlcat(msg, "ipathhdrerr ", len);
+ if (err & INFINIPATH_RHF_H_TIDERR)
+ strlcat(msg, "tiderr ", len);
+ if (err & INFINIPATH_RHF_H_MKERR)
+ /* bad port, offset, etc. */
+ strlcat(msg, "invalid ipathhdr ", len);
+ if (err & INFINIPATH_RHF_H_IBERR)
+ strlcat(msg, "iberr ", len);
+ if (err & INFINIPATH_RHF_L_SWA)
+ strlcat(msg, "swA ", len);
+ if (err & INFINIPATH_RHF_L_SWB)
+ strlcat(msg, "swB ", len);
+}
+
+/**
+ * ipath_get_egrbuf - get an eager buffer
+ * @dd: the infinipath device
+ * @bufnum: the eager buffer to get
+ * @err: unused
+ *
+ * must only be called if ipath_pd[port] is known to be allocated
+ */
+static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
+ int err)
+{
+ return dd->ipath_port0_skbs ?
+ (void *)dd->ipath_port0_skbs[bufnum]->data : NULL;
+}
+
+/**
+ * ipath_alloc_skb - allocate an skb and buffer with possible constraints
+ * @dd: the infinipath device
+ * @gfp_mask: the sk_buff SFP mask
+ */
+struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd,
+ gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+ u32 len;
+
+ /*
+ * Only fully supported way to handle this is to allocate lots
+ * extra, align as needed, and then do skb_reserve(). That wastes
+ * a lot of memory... I'll have to hack this into infinipath_copy
+ * also.
+ */
+
+ /*
+ * We need 4 extra bytes for unaligned transfer copying
+ */
+ if (dd->ipath_flags & IPATH_4BYTE_TID) {
+ /* we need a 4KB multiple alignment, and there is no way
+ * to do it except to allocate extra and then skb_reserve
+ * enough to bring it up to the right alignment.
+ */
+ len = dd->ipath_ibmaxlen + 4 + (1 << 11) - 1;
+ }
+ else
+ len = dd->ipath_ibmaxlen + 4;
+ skb = __dev_alloc_skb(len, gfp_mask);
+ if (!skb) {
+ ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n",
+ len);
+ goto bail;
+ }
+ if (dd->ipath_flags & IPATH_4BYTE_TID) {
+ u32 una = ((1 << 11) - 1) & (unsigned long)(skb->data + 4);
+ if (una)
+ skb_reserve(skb, 4 + (1 << 11) - una);
+ else
+ skb_reserve(skb, 4);
+ } else
+ skb_reserve(skb, 4);
+
+bail:
+ return skb;
+}
+
+/**
+ * ipath_rcv_layer - receive a packet for the layered (ethernet) driver
+ * @dd: the infinipath device
+ * @etail: the sk_buff number
+ * @tlen: the total packet length
+ * @hdr: the ethernet header
+ *
+ * Separate routine for better overall optimization
+ */
+static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail,
+ u32 tlen, struct ether_header *hdr)
+{
+ u32 elen;
+ u8 pad, *bthbytes;
+ struct sk_buff *skb, *nskb;
+
+ if (dd->ipath_port0_skbs && hdr->sub_opcode == OPCODE_ENCAP) {
+ /*
+ * Allocate a new sk_buff to replace the one we give
+ * to the network stack.
+ */
+ nskb = ipath_alloc_skb(dd, GFP_ATOMIC);
+ if (!nskb) {
+ /* count OK packets that we drop */
+ ipath_stats.sps_krdrops++;
+ return;
+ }
+
+ bthbytes = (u8 *) hdr->bth;
+ pad = (bthbytes[1] >> 4) & 3;
+ /* +CRC32 */
+ elen = tlen - (sizeof(*hdr) + pad + sizeof(u32));
+
+ skb = dd->ipath_port0_skbs[etail];
+ dd->ipath_port0_skbs[etail] = nskb;
+ skb_put(skb, elen);
+
+ dd->ipath_f_put_tid(dd, etail + (u64 __iomem *)
+ ((char __iomem *) dd->ipath_kregbase
+ + dd->ipath_rcvegrbase), 0,
+ virt_to_phys(nskb->data));
+
+ __ipath_layer_rcv(dd, hdr, skb);
+
+ /* another ether packet received */
+ ipath_stats.sps_ether_rpkts++;
+ }
+ else if (hdr->sub_opcode == OPCODE_LID_ARP)
+ __ipath_layer_rcv_lid(dd, hdr);
+}
+
+/*
+ * ipath_kreceive - receive a packet
+ * @dd: the infinipath device
+ *
+ * called from interrupt handler for errors or receive interrupt
+ */
+void ipath_kreceive(struct ipath_devdata *dd)
+{
+ u64 *rc;
+ void *ebuf;
+ const u32 rsize = dd->ipath_rcvhdrentsize; /* words */
+ const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */
+ u32 etail = -1, l, hdrqtail;
+ struct ips_message_header *hdr;
+ u32 eflags, i, etype, tlen, pkttot = 0;
+ static u64 totcalls; /* stats, may eventually remove */
+ char emsg[128];
+
+ if (!dd->ipath_hdrqtailptr) {
+ ipath_dev_err(dd,
+ "hdrqtailptr not set, can't do receives\n");
+ goto bail;
+ }
+
+ /* There is already a thread processing this queue. */
+ if (test_and_set_bit(0, &dd->ipath_rcv_pending))
+ goto bail;
+
+ if (dd->ipath_port0head ==
+ (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
+ goto done;
+
+gotmore:
+ /*
+ * read only once at start. If in flood situation, this helps
+ * performance slightly. If more arrive while we are processing,
+ * we'll come back here and do them
+ */
+ hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
+
+ for (i = 0, l = dd->ipath_port0head; l != hdrqtail; i++) {
+ u32 qp;
+ u8 *bthbytes;
+
+ rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2));
+ hdr = (struct ips_message_header *)&rc[1];
+ /*
+ * could make a network order version of IPATH_KD_QP, and
+ * do the obvious shift before masking to speed this up.
+ */
+ qp = ntohl(hdr->bth[1]) & 0xffffff;
+ bthbytes = (u8 *) hdr->bth;
+
+ eflags = ips_get_hdr_err_flags((__le32 *) rc);
+ etype = ips_get_rcv_type((__le32 *) rc);
+ /* total length */
+ tlen = ips_get_length_in_bytes((__le32 *) rc);
+ ebuf = NULL;
+ if (etype != RCVHQ_RCV_TYPE_EXPECTED) {
+ /*
+ * it turns out that the chips uses an eager buffer
+ * for all non-expected packets, whether it "needs"
+ * one or not. So always get the index, but don't
+ * set ebuf (so we try to copy data) unless the
+ * length requires it.
+ */
+ etail = ips_get_index((__le32 *) rc);
+ if (tlen > sizeof(*hdr) ||
+ etype == RCVHQ_RCV_TYPE_NON_KD)
+ ebuf = ipath_get_egrbuf(dd, etail, 0);
+ }
+
+ /*
+ * both tiderr and ipathhdrerr are set for all plain IB
+ * packets; only ipathhdrerr should be set.
+ */
+
+ if (etype != RCVHQ_RCV_TYPE_NON_KD && etype !=
+ RCVHQ_RCV_TYPE_ERROR && ips_get_ipath_ver(
+ hdr->iph.ver_port_tid_offset) !=
+ IPS_PROTO_VERSION) {
+ ipath_cdbg(PKT, "Bad InfiniPath protocol version "
+ "%x\n", etype);
+ }
+
+ if (eflags & ~(INFINIPATH_RHF_H_TIDERR |
+ INFINIPATH_RHF_H_IHDRERR)) {
+ get_rhf_errstring(eflags, emsg, sizeof emsg);
+ ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
+ "tlen=%x opcode=%x egridx=%x: %s\n",
+ eflags, l, etype, tlen, bthbytes[0],
+ ips_get_index((__le32 *) rc), emsg);
+ } else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
+ int ret = __ipath_verbs_rcv(dd, rc + 1,
+ ebuf, tlen);
+ if (ret == -ENODEV)
+ ipath_cdbg(VERBOSE,
+ "received IB packet, "
+ "not SMA (QP=%x)\n", qp);
+ } else if (etype == RCVHQ_RCV_TYPE_EAGER) {
+ if (qp == IPATH_KD_QP &&
+ bthbytes[0] == ipath_layer_rcv_opcode &&
+ ebuf)
+ ipath_rcv_layer(dd, etail, tlen,
+ (struct ether_header *)hdr);
+ else
+ ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+ "qp=%x), len %x; ignored\n",
+ etype, bthbytes[0], qp, tlen);
+ }
+ else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
+ ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
+ be32_to_cpu(hdr->bth[0]) & 0xff);
+ else if (eflags & (INFINIPATH_RHF_H_TIDERR |
+ INFINIPATH_RHF_H_IHDRERR)) {
+ /*
+ * This is a type 3 packet, only the LRH is in the
+ * rcvhdrq, the rest of the header is in the eager
+ * buffer.
+ */
+ u8 opcode;
+ if (ebuf) {
+ bthbytes = (u8 *) ebuf;
+ opcode = *bthbytes;
+ }
+ else
+ opcode = 0;
+ get_rhf_errstring(eflags, emsg, sizeof emsg);
+ ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, "
+ "len %x\n", eflags, emsg, opcode, etail,
+ tlen);
+ } else {
+ /*
+ * error packet, type of error unknown.
+ * Probably type 3, but we don't know, so don't
+ * even try to print the opcode, etc.
+ */
+ ipath_dbg("Error Pkt, but no eflags! egrbuf %x, "
+ "len %x\nhdrq@%lx;hdrq+%x rhf: %llx; "
+ "hdr %llx %llx %llx %llx %llx\n",
+ etail, tlen, (unsigned long) rc, l,
+ (unsigned long long) rc[0],
+ (unsigned long long) rc[1],
+ (unsigned long long) rc[2],
+ (unsigned long long) rc[3],
+ (unsigned long long) rc[4],
+ (unsigned long long) rc[5]);
+ }
+ l += rsize;
+ if (l >= maxcnt)
+ l = 0;
+ /*
+ * update for each packet, to help prevent overflows if we
+ * have lots of packets.
+ */
+ (void)ipath_write_ureg(dd, ur_rcvhdrhead,
+ dd->ipath_rhdrhead_intr_off | l, 0);
+ if (etype != RCVHQ_RCV_TYPE_EXPECTED)
+ (void)ipath_write_ureg(dd, ur_rcvegrindexhead,
+ etail, 0);
+ }
+
+ pkttot += i;
+
+ dd->ipath_port0head = l;
+
+ if (hdrqtail != (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
+ /* more arrived while we handled first batch */
+ goto gotmore;
+
+ if (pkttot > ipath_stats.sps_maxpkts_call)
+ ipath_stats.sps_maxpkts_call = pkttot;
+ ipath_stats.sps_port0pkts += pkttot;
+ ipath_stats.sps_avgpkts_call =
+ ipath_stats.sps_port0pkts / ++totcalls;
+
+done:
+ clear_bit(0, &dd->ipath_rcv_pending);
+ smp_mb__after_clear_bit();
+
+bail:;
+}
+
+/**
+ * ipath_update_pio_bufs - update shadow copy of the PIO availability map
+ * @dd: the infinipath device
+ *
+ * called whenever our local copy indicates we have run out of send buffers
+ * NOTE: This can be called from interrupt context by some code
+ * and from non-interrupt context by ipath_getpiobuf().
+ */
+
+static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+{
+ unsigned long flags;
+ int i;
+ const unsigned piobregs = (unsigned)dd->ipath_pioavregs;
+
+ /* If the generation (check) bits have changed, then we update the
+ * busy bit for the corresponding PIO buffer. This algorithm will
+ * modify positions to the value they already have in some cases
+ * (i.e., no change), but it's faster than changing only the bits
+ * that have changed.
+ *
+ * We would like to do this atomicly, to avoid spinlocks in the
+ * critical send path, but that's not really possible, given the
+ * type of changes, and that this routine could be called on
+ * multiple cpu's simultaneously, so we lock in this routine only,
+ * to avoid conflicting updates; all we change is the shadow, and
+ * it's a single 64 bit memory location, so by definition the update
+ * is atomic in terms of what other cpu's can see in testing the
+ * bits. The spin_lock overhead isn't too bad, since it only
+ * happens when all buffers are in use, so only cpu overhead, not
+ * latency or bandwidth is affected.
+ */
+#define _IPATH_ALL_CHECKBITS 0x5555555555555555ULL
+ if (!dd->ipath_pioavailregs_dma) {
+ ipath_dbg("Update shadow pioavail, but regs_dma NULL!\n");
+ return;
+ }
+ if (ipath_debug & __IPATH_VERBDBG) {
+ /* only if packet debug and verbose */
+ volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+ unsigned long *shadow = dd->ipath_pioavailshadow;
+
+ ipath_cdbg(PKT, "Refill avail, dma0=%llx shad0=%lx, "
+ "d1=%llx s1=%lx, d2=%llx s2=%lx, d3=%llx "
+ "s3=%lx\n",
+ (unsigned long long) le64_to_cpu(dma[0]),
+ shadow[0],
+ (unsigned long long) le64_to_cpu(dma[1]),
+ shadow[1],
+ (unsigned long long) le64_to_cpu(dma[2]),
+ shadow[2],
+ (unsigned long long) le64_to_cpu(dma[3]),
+ shadow[3]);
+ if (piobregs > 4)
+ ipath_cdbg(
+ PKT, "2nd group, dma4=%llx shad4=%lx, "
+ "d5=%llx s5=%lx, d6=%llx s6=%lx, "
+ "d7=%llx s7=%lx\n",
+ (unsigned long long) le64_to_cpu(dma[4]),
+ shadow[4],
+ (unsigned long long) le64_to_cpu(dma[5]),
+ shadow[5],
+ (unsigned long long) le64_to_cpu(dma[6]),
+ shadow[6],
+ (unsigned long long) le64_to_cpu(dma[7]),
+ shadow[7]);
+ }
+ spin_lock_irqsave(&ipath_pioavail_lock, flags);
+ for (i = 0; i < piobregs; i++) {
+ u64 pchbusy, pchg, piov, pnew;
+ /*
+ * Chip Errata: bug 6641; even and odd qwords>3 are swapped
+ */
+ if (i > 3) {
+ if (i & 1)
+ piov = le64_to_cpu(
+ dd->ipath_pioavailregs_dma[i - 1]);
+ else
+ piov = le64_to_cpu(
+ dd->ipath_pioavailregs_dma[i + 1]);
+ } else
+ piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
+ pchg = _IPATH_ALL_CHECKBITS &
+ ~(dd->ipath_pioavailshadow[i] ^ piov);
+ pchbusy = pchg << INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT;
+ if (pchg && (pchbusy & dd->ipath_pioavailshadow[i])) {
+ pnew = dd->ipath_pioavailshadow[i] & ~pchbusy;
+ pnew |= piov & pchbusy;
+ dd->ipath_pioavailshadow[i] = pnew;
+ }
+ }
+ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+}
+
+/**
+ * ipath_setrcvhdrsize - set the receive header size
+ * @dd: the infinipath device
+ * @rhdrsize: the receive header size
+ *
+ * called from user init code, and also layered driver init
+ */
+int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize)
+{
+ int ret = 0;
+
+ if (dd->ipath_flags & IPATH_RCVHDRSZ_SET) {
+ if (dd->ipath_rcvhdrsize != rhdrsize) {
+ dev_info(&dd->pcidev->dev,
+ "Error: can't set protocol header "
+ "size %u, already %u\n",
+ rhdrsize, dd->ipath_rcvhdrsize);
+ ret = -EAGAIN;
+ } else
+ ipath_cdbg(VERBOSE, "Reuse same protocol header "
+ "size %u\n", dd->ipath_rcvhdrsize);
+ } else if (rhdrsize > (dd->ipath_rcvhdrentsize -
+ (sizeof(u64) / sizeof(u32)))) {
+ ipath_dbg("Error: can't set protocol header size %u "
+ "(> max %u)\n", rhdrsize,
+ dd->ipath_rcvhdrentsize -
+ (u32) (sizeof(u64) / sizeof(u32)));
+ ret = -EOVERFLOW;
+ } else {
+ dd->ipath_flags |= IPATH_RCVHDRSZ_SET;
+ dd->ipath_rcvhdrsize = rhdrsize;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize,
+ dd->ipath_rcvhdrsize);
+ ipath_cdbg(VERBOSE, "Set protocol header size to %u\n",
+ dd->ipath_rcvhdrsize);
+ }
+ return ret;
+}
+
+/**
+ * ipath_getpiobuf - find an available pio buffer
+ * @dd: the infinipath device
+ * @pbufnum: the buffer number is placed here
+ *
+ * do appropriate marking as busy, etc.
+ * returns buffer number if one found (>=0), negative number is error.
+ * Used by ipath_sma_send_pkt and ipath_layer_send
+ */
+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
+{
+ int i, j, starti, updated = 0;
+ unsigned piobcnt, iter;
+ unsigned long flags;
+ unsigned long *shadow = dd->ipath_pioavailshadow;
+ u32 __iomem *buf;
+
+ piobcnt = (unsigned)(dd->ipath_piobcnt2k
+ + dd->ipath_piobcnt4k);
+ starti = dd->ipath_lastport_piobuf;
+ iter = piobcnt - starti;
+ if (dd->ipath_upd_pio_shadow) {
+ /*
+ * Minor optimization. If we had no buffers on last call,
+ * start out by doing the update; continue and do scan even
+ * if no buffers were updated, to be paranoid
+ */
+ ipath_update_pio_bufs(dd);
+ /* we scanned here, don't do it at end of scan */
+ updated = 1;
+ i = starti;
+ } else
+ i = dd->ipath_lastpioindex;
+
+rescan:
+ /*
+ * while test_and_set_bit() is atomic, we do that and then the
+ * change_bit(), and the pair is not. See if this is the cause
+ * of the remaining armlaunch errors.
+ */
+ spin_lock_irqsave(&ipath_pioavail_lock, flags);
+ for (j = 0; j < iter; j++, i++) {
+ if (i >= piobcnt)
+ i = starti;
+ /*
+ * To avoid bus lock overhead, we first find a candidate
+ * buffer, then do the test and set, and continue if that
+ * fails.
+ */
+ if (test_bit((2 * i) + 1, shadow) ||
+ test_and_set_bit((2 * i) + 1, shadow))
+ continue;
+ /* flip generation bit */
+ change_bit(2 * i, shadow);
+ break;
+ }
+ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+
+ if (j == iter) {
+ volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+
+ /*
+ * first time through; shadow exhausted, but may be real
+ * buffers available, so go see; if any updated, rescan
+ * (once)
+ */
+ if (!updated) {
+ ipath_update_pio_bufs(dd);
+ updated = 1;
+ i = starti;
+ goto rescan;
+ }
+ dd->ipath_upd_pio_shadow = 1;
+ /*
+ * not atomic, but if we lose one once in a while, that's OK
+ */
+ ipath_stats.sps_nopiobufs++;
+ if (!(++dd->ipath_consec_nopiobuf % 100000)) {
+ ipath_dbg(
+ "%u pio sends with no bufavail; dmacopy: "
+ "%llx %llx %llx %llx; shadow: "
+ "%lx %lx %lx %lx\n",
+ dd->ipath_consec_nopiobuf,
+ (unsigned long long) le64_to_cpu(dma[0]),
+ (unsigned long long) le64_to_cpu(dma[1]),
+ (unsigned long long) le64_to_cpu(dma[2]),
+ (unsigned long long) le64_to_cpu(dma[3]),
+ shadow[0], shadow[1], shadow[2],
+ shadow[3]);
+ /*
+ * 4 buffers per byte, 4 registers above, cover rest
+ * below
+ */
+ if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
+ (sizeof(shadow[0]) * 4 * 4))
+ ipath_dbg("2nd group: dmacopy: %llx %llx "
+ "%llx %llx; shadow: %lx %lx "
+ "%lx %lx\n",
+ (unsigned long long)
+ le64_to_cpu(dma[4]),
+ (unsigned long long)
+ le64_to_cpu(dma[5]),
+ (unsigned long long)
+ le64_to_cpu(dma[6]),
+ (unsigned long long)
+ le64_to_cpu(dma[7]),
+ shadow[4], shadow[5],
+ shadow[6], shadow[7]);
+ }
+ buf = NULL;
+ goto bail;
+ }
+
+ if (updated)
+ /*
+ * ran out of bufs, now some (at least this one we just
+ * got) are now available, so tell the layered driver.
+ */
+ __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
+
+ /*
+ * set next starting place. Since it's just an optimization,
+ * it doesn't matter who wins on this, so no locking
+ */
+ dd->ipath_lastpioindex = i + 1;
+ if (dd->ipath_upd_pio_shadow)
+ dd->ipath_upd_pio_shadow = 0;
+ if (dd->ipath_consec_nopiobuf)
+ dd->ipath_consec_nopiobuf = 0;
+ if (i < dd->ipath_piobcnt2k)
+ buf = (u32 __iomem *) (dd->ipath_pio2kbase +
+ i * dd->ipath_palign);
+ else
+ buf = (u32 __iomem *)
+ (dd->ipath_pio4kbase +
+ (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
+ ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
+ i, (i < dd->ipath_piobcnt2k) ? 2 : 4, buf);
+ if (pbufnum)
+ *pbufnum = i;
+
+bail:
+ return buf;
+}
+
+/**
+ * ipath_create_rcvhdrq - create a receive header queue
+ * @dd: the infinipath device
+ * @pd: the port data
+ *
+ * this *must* be physically contiguous memory, and for now,
+ * that limits it to what kmalloc can do.
+ */
+int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ struct ipath_portdata *pd)
+{
+ int ret = 0, amt;
+
+ amt = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+ sizeof(u32), PAGE_SIZE);
+ if (!pd->port_rcvhdrq) {
+ /*
+ * not using REPEAT isn't viable; at 128KB, we can easily
+ * fail this. The problem with REPEAT is we can block here
+ * "forever". There isn't an inbetween, unfortunately. We
+ * could reduce the risk by never freeing the rcvhdrq except
+ * at unload, but even then, the first time a port is used,
+ * we could delay for some time...
+ */
+ gfp_t gfp_flags = GFP_USER | __GFP_COMP;
+
+ pd->port_rcvhdrq = dma_alloc_coherent(
+ &dd->pcidev->dev, amt, &pd->port_rcvhdrq_phys,
+ gfp_flags);
+
+ if (!pd->port_rcvhdrq) {
+ ipath_dev_err(dd, "attempt to allocate %d bytes "
+ "for port %u rcvhdrq failed\n",
+ amt, pd->port_port);
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ pd->port_rcvhdrq_size = amt;
+
+ ipath_cdbg(VERBOSE, "%d pages at %p (phys %lx) size=%lu "
+ "for port %u rcvhdr Q\n",
+ amt >> PAGE_SHIFT, pd->port_rcvhdrq,
+ (unsigned long) pd->port_rcvhdrq_phys,
+ (unsigned long) pd->port_rcvhdrq_size,
+ pd->port_port);
+ } else {
+ /*
+ * clear for security, sanity, and/or debugging, each
+ * time we reuse
+ */
+ memset(pd->port_rcvhdrq, 0, amt);
+ }
+
+ /*
+ * tell chip each time we init it, even if we are re-using previous
+ * memory (we zero it at process close)
+ */
+ ipath_cdbg(VERBOSE, "writing port %d rcvhdraddr as %lx\n",
+ pd->port_port, (unsigned long) pd->port_rcvhdrq_phys);
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
+ pd->port_port, pd->port_rcvhdrq_phys);
+
+ ret = 0;
+bail:
+ return ret;
+}
+
+int ipath_waitfor_complete(struct ipath_devdata *dd, ipath_kreg reg_id,
+ u64 bits_to_wait_for, u64 * valp)
+{
+ unsigned long timeout;
+ u64 lastval, val;
+ int ret;
+
+ lastval = ipath_read_kreg64(dd, reg_id);
+ /* wait a ridiculously long time */
+ timeout = jiffies + msecs_to_jiffies(5);
+ do {
+ val = ipath_read_kreg64(dd, reg_id);
+ /* set so they have something, even on failures. */
+ *valp = val;
+ if ((val & bits_to_wait_for) == bits_to_wait_for) {
+ ret = 0;
+ break;
+ }
+ if (val != lastval)
+ ipath_cdbg(VERBOSE, "Changed from %llx to %llx, "
+ "waiting for %llx bits\n",
+ (unsigned long long) lastval,
+ (unsigned long long) val,
+ (unsigned long long) bits_to_wait_for);
+ cond_resched();
+ if (time_after(jiffies, timeout)) {
+ ipath_dbg("Didn't get bits %llx in register 0x%x, "
+ "got %llx\n",
+ (unsigned long long) bits_to_wait_for,
+ reg_id, (unsigned long long) *valp);
+ ret = -ENODEV;
+ break;
+ }
+ } while (1);
+
+ return ret;
+}
+
+/**
+ * ipath_waitfor_mdio_cmdready - wait for last command to complete
+ * @dd: the infinipath device
+ *
+ * Like ipath_waitfor_complete(), but we wait for the CMDVALID bit to go
+ * away indicating the last command has completed. It doesn't return data
+ */
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
+{
+ unsigned long timeout;
+ u64 val;
+ int ret;
+
+ /* wait a ridiculously long time */
+ timeout = jiffies + msecs_to_jiffies(5);
+ do {
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_mdio);
+ if (!(val & IPATH_MDIO_CMDVALID)) {
+ ret = 0;
+ break;
+ }
+ cond_resched();
+ if (time_after(jiffies, timeout)) {
+ ipath_dbg("CMDVALID stuck in mdio reg? (%llx)\n",
+ (unsigned long long) val);
+ ret = -ENODEV;
+ break;
+ }
+ } while (1);
+
+ return ret;
+}
+
+void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
+{
+ static const char *what[4] = {
+ [0] = "DOWN",
+ [INFINIPATH_IBCC_LINKCMD_INIT] = "INIT",
+ [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
+ [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
+ };
+ ipath_cdbg(SMA, "Trying to move unit %u to %s, current ltstate "
+ "is %s\n", dd->ipath_unit,
+ what[(which >> INFINIPATH_IBCC_LINKCMD_SHIFT) &
+ INFINIPATH_IBCC_LINKCMD_MASK],
+ ipath_ibcstatus_str[
+ (ipath_read_kreg64
+ (dd, dd->ipath_kregs->kr_ibcstatus) >>
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl | which);
+}
+
+/**
+ * ipath_read_kreg64_port - read a device's per-port 64-bit kernel register
+ * @dd: the infinipath device
+ * @regno: the register number to read
+ * @port: the port containing the register
+ *
+ * Registers that vary with the chip implementation constants (port)
+ * use this routine.
+ */
+u64 ipath_read_kreg64_port(const struct ipath_devdata *dd, ipath_kreg regno,
+ unsigned port)
+{
+ u16 where;
+
+ if (port < dd->ipath_portcnt &&
+ (regno == dd->ipath_kregs->kr_rcvhdraddr ||
+ regno == dd->ipath_kregs->kr_rcvhdrtailaddr))
+ where = regno + port;
+ else
+ where = -1;
+
+ return ipath_read_kreg64(dd, where);
+}
+
+/**
+ * ipath_write_kreg_port - write a device's per-port 64-bit kernel register
+ * @dd: the infinipath device
+ * @regno: the register number to write
+ * @port: the port containing the register
+ * @value: the value to write
+ *
+ * Registers that vary with the chip implementation constants (port)
+ * use this routine.
+ */
+void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno,
+ unsigned port, u64 value)
+{
+ u16 where;
+
+ if (port < dd->ipath_portcnt &&
+ (regno == dd->ipath_kregs->kr_rcvhdraddr ||
+ regno == dd->ipath_kregs->kr_rcvhdrtailaddr))
+ where = regno + port;
+ else
+ where = -1;
+
+ ipath_write_kreg(dd, where, value);
+}
+
+/**
+ * ipath_shutdown_device - shut down a device
+ * @dd: the infinipath device
+ *
+ * This is called to make the device quiet when we are about to
+ * unload the driver, and also when the device is administratively
+ * disabled. It does not free any data structures.
+ * Everything it does has to be setup again by ipath_init_chip(dd,1)
+ */
+void ipath_shutdown_device(struct ipath_devdata *dd)
+{
+ u64 val;
+
+ ipath_dbg("Shutting down the device\n");
+
+ dd->ipath_flags |= IPATH_LINKUNK;
+ dd->ipath_flags &= ~(IPATH_INITTED | IPATH_LINKDOWN |
+ IPATH_LINKINIT | IPATH_LINKARMED |
+ IPATH_LINKACTIVE);
+ *dd->ipath_statusp &= ~(IPATH_STATUS_IB_CONF |
+ IPATH_STATUS_IB_READY);
+
+ /* mask interrupts, but not errors */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+
+ dd->ipath_rcvctrl = 0;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ /*
+ * gracefully stop all sends allowing any in progress to trickle out
+ * first.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
+ /* flush it */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ /*
+ * enough for anything that's going to trickle out to have actually
+ * done so.
+ */
+ 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);
+
+ /*
+ * we are shutting down, so tell the layered driver. We don't do
+ * this on just a link state change, much like ethernet, a cable
+ * unplug, etc. doesn't change driver state
+ */
+ ipath_layer_intr(dd, IPATH_LAYER_INT_IF_DOWN);
+
+ /* disable IBC */
+ dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+
+ /*
+ * clear SerdesEnable and turn the leds off; do this here because
+ * we are unloading, so don't count on interrupts to move along
+ * 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);
+ dd->ipath_stats_timer_active = 0;
+ }
+
+ /*
+ * clear all interrupts and errors, so that the next time the driver
+ * is loaded or device is enabled, we know that whatever is set
+ * happened while we were unloaded
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ ~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_free_pddata - free a port's allocated data
+ * @dd: the infinipath device
+ * @port: the port
+ * @freehdrq: free the port data structure if true
+ *
+ * when closing, free up any allocated data for a port, if the
+ * reference count goes to zero
+ * Note: this also optionally frees the portdata itself!
+ * Any changes here have to be matched up with the reinit case
+ * of ipath_init_chip(), which calls this routine on reinit after reset.
+ */
+void ipath_free_pddata(struct ipath_devdata *dd, u32 port, int freehdrq)
+{
+ struct ipath_portdata *pd = dd->ipath_pd[port];
+
+ if (!pd)
+ return;
+ if (freehdrq)
+ /*
+ * only clear and free portdata if we are going to also
+ * release the hdrq, otherwise we leak the hdrq on each
+ * open/close cycle
+ */
+ dd->ipath_pd[port] = NULL;
+ if (freehdrq && pd->port_rcvhdrq) {
+ ipath_cdbg(VERBOSE, "free closed port %d rcvhdrq @ %p "
+ "(size=%lu)\n", pd->port_port, pd->port_rcvhdrq,
+ (unsigned long) pd->port_rcvhdrq_size);
+ dma_free_coherent(&dd->pcidev->dev, pd->port_rcvhdrq_size,
+ pd->port_rcvhdrq, pd->port_rcvhdrq_phys);
+ pd->port_rcvhdrq = NULL;
+ }
+ if (port && pd->port_rcvegrbuf) {
+ /* always free this */
+ if (pd->port_rcvegrbuf) {
+ unsigned e;
+
+ for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) {
+ void *base = pd->port_rcvegrbuf[e];
+ size_t size = pd->port_rcvegrbuf_size;
+
+ ipath_cdbg(VERBOSE, "egrbuf free(%p, %lu), "
+ "chunk %u/%u\n", base,
+ (unsigned long) size,
+ e, pd->port_rcvegrbuf_chunks);
+ dma_free_coherent(
+ &dd->pcidev->dev, size, base,
+ pd->port_rcvegrbuf_phys[e]);
+ }
+ vfree(pd->port_rcvegrbuf);
+ pd->port_rcvegrbuf = NULL;
+ vfree(pd->port_rcvegrbuf_phys);
+ pd->port_rcvegrbuf_phys = NULL;
+ }
+ pd->port_rcvegrbuf_chunks = 0;
+ } else if (port == 0 && dd->ipath_port0_skbs) {
+ unsigned e;
+ struct sk_buff **skbs = dd->ipath_port0_skbs;
+
+ dd->ipath_port0_skbs = NULL;
+ ipath_cdbg(VERBOSE, "free closed port %d ipath_port0_skbs "
+ "@ %p\n", pd->port_port, skbs);
+ for (e = 0; e < dd->ipath_rcvegrcnt; e++)
+ if (skbs[e])
+ dev_kfree_skb(skbs[e]);
+ vfree(skbs);
+ }
+ if (freehdrq) {
+ kfree(pd->port_tid_pg_list);
+ kfree(pd);
+ }
+}
+
+static int __init infinipath_init(void)
+{
+ int ret;
+
+ ipath_dbg(KERN_INFO DRIVER_LOAD_MSG "%s", ipath_core_version);
+
+ /*
+ * These must be called before the driver is registered with
+ * the PCI subsystem.
+ */
+ idr_init(&unit_table);
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ ret = pci_register_driver(&ipath_driver);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Unable to register driver: error %d\n", -ret);
+ goto bail_unit;
+ }
+
+ ret = ipath_driver_create_group(&ipath_driver.driver);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME ": Unable to create driver "
+ "sysfs entries: error %d\n", -ret);
+ goto bail_pci;
+ }
+
+ ret = ipath_init_ipathfs();
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
+ "ipathfs: error %d\n", -ret);
+ goto bail_group;
+ }
+
+ goto bail;
+
+bail_group:
+ ipath_driver_remove_group(&ipath_driver.driver);
+
+bail_pci:
+ pci_unregister_driver(&ipath_driver);
+
+bail_unit:
+ idr_destroy(&unit_table);
+
+bail:
+ return ret;
+}
+
+static void cleanup_device(struct ipath_devdata *dd)
+{
+ int port;
+
+ ipath_shutdown_device(dd);
+
+ if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) {
+ /* can't do anything more with chip; needs re-init */
+ *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT;
+ if (dd->ipath_kregbase) {
+ /*
+ * if we haven't already cleaned up before these are
+ * to ensure any register reads/writes "fail" until
+ * re-init
+ */
+ dd->ipath_kregbase = NULL;
+ dd->ipath_kregvirt = NULL;
+ dd->ipath_uregbase = 0;
+ dd->ipath_sregbase = 0;
+ dd->ipath_cregbase = 0;
+ dd->ipath_kregsize = 0;
+ }
+ ipath_disable_wc(dd);
+ }
+
+ if (dd->ipath_pioavailregs_dma) {
+ dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
+ (void *) dd->ipath_pioavailregs_dma,
+ dd->ipath_pioavailregs_phys);
+ dd->ipath_pioavailregs_dma = NULL;
+ }
+
+ if (dd->ipath_pageshadow) {
+ struct page **tmpp = dd->ipath_pageshadow;
+ int i, cnt = 0;
+
+ ipath_cdbg(VERBOSE, "Unlocking any expTID pages still "
+ "locked\n");
+ for (port = 0; port < dd->ipath_cfgports; port++) {
+ int port_tidbase = port * dd->ipath_rcvtidcnt;
+ int maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+ for (i = port_tidbase; i < maxtid; i++) {
+ if (!tmpp[i])
+ continue;
+ ipath_release_user_pages(&tmpp[i], 1);
+ tmpp[i] = NULL;
+ cnt++;
+ }
+ }
+ if (cnt) {
+ ipath_stats.sps_pageunlocks += cnt;
+ ipath_cdbg(VERBOSE, "There were still %u expTID "
+ "entries locked\n", cnt);
+ }
+ if (ipath_stats.sps_pagelocks ||
+ ipath_stats.sps_pageunlocks)
+ ipath_cdbg(VERBOSE, "%llu pages locked, %llu "
+ "unlocked via ipath_m{un}lock\n",
+ (unsigned long long)
+ ipath_stats.sps_pagelocks,
+ (unsigned long long)
+ ipath_stats.sps_pageunlocks);
+
+ ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n",
+ dd->ipath_pageshadow);
+ vfree(dd->ipath_pageshadow);
+ dd->ipath_pageshadow = NULL;
+ }
+
+ /*
+ * free any resources still in use (usually just kernel ports)
+ * at unload
+ */
+ for (port = 0; port < dd->ipath_cfgports; port++)
+ ipath_free_pddata(dd, port, 1);
+ kfree(dd->ipath_pd);
+ /*
+ * debuggability, in case some cleanup path tries to use it
+ * after this
+ */
+ dd->ipath_pd = NULL;
+}
+
+static void __exit infinipath_cleanup(void)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ ipath_exit_ipathfs();
+
+ ipath_driver_remove_group(&ipath_driver.driver);
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ /*
+ * turn off rcv, send, and interrupts for all ports, all drivers
+ * should also hard reset the chip here?
+ * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs
+ * for all versions of the driver, if they were allocated
+ */
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ if (dd->ipath_kregbase)
+ cleanup_device(dd);
+
+ if (dd->pcidev) {
+ if (dd->pcidev->irq) {
+ ipath_cdbg(VERBOSE,
+ "unit %u free_irq of irq %x\n",
+ dd->ipath_unit, dd->pcidev->irq);
+ free_irq(dd->pcidev->irq, dd);
+ } else
+ ipath_dbg("irq is 0, not doing free_irq "
+ "for unit %u\n", dd->ipath_unit);
+ dd->pcidev = NULL;
+ }
+
+ /*
+ * we check for NULL here, because it's outside the kregbase
+ * check, and we need to call it after the free_irq. Thus
+ * it's possible that the function pointers were never
+ * initialized.
+ */
+ if (dd->ipath_f_cleanup)
+ /* clean up chip-specific stuff */
+ dd->ipath_f_cleanup(dd);
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
+ pci_unregister_driver(&ipath_driver);
+
+ idr_destroy(&unit_table);
+}
+
+/**
+ * ipath_reset_device - reset the chip if possible
+ * @unit: the device to reset
+ *
+ * Whether or not reset is successful, we attempt to re-initialize the chip
+ * (that is, much like a driver unload/reload). We clear the INITTED flag
+ * so that the various entry points will fail until we reinitialize. For
+ * now, we only allow this if no user ports are open that use chip resources
+ */
+int ipath_reset_device(int unit)
+{
+ int ret, i;
+ struct ipath_devdata *dd = ipath_lookup(unit);
+
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit);
+
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) {
+ dev_info(&dd->pcidev->dev, "Invalid unit number %u or "
+ "not initialized or not present\n", unit);
+ ret = -ENXIO;
+ goto bail;
+ }
+
+ if (dd->ipath_pd)
+ for (i = 1; i < dd->ipath_portcnt; i++) {
+ if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) {
+ ipath_dbg("unit %u port %d is in use "
+ "(PID %u cmd %s), can't reset\n",
+ unit, i,
+ dd->ipath_pd[i]->port_pid,
+ dd->ipath_pd[i]->port_comm);
+ ret = -EBUSY;
+ goto bail;
+ }
+ }
+
+ dd->ipath_flags &= ~IPATH_INITTED;
+ ret = dd->ipath_f_reset(dd);
+ if (ret != 1)
+ ipath_dbg("reset was not successful\n");
+ ipath_dbg("Trying to reinitialize unit %u after reset attempt\n",
+ unit);
+ ret = ipath_init_chip(dd, 1);
+ if (ret)
+ ipath_dev_err(dd, "Reinitialize unit %u after "
+ "reset failed with %d\n", unit, ret);
+ else
+ dev_info(&dd->pcidev->dev, "Reinitialized unit %u after "
+ "resetting\n", unit);
+
+bail:
+ return ret;
+}
+
+module_init(infinipath_init);
+module_exit(infinipath_cleanup);
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
new file mode 100644
index 000000000000..f11a900e8cd7
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+
+/*
+ * InfiniPath I2C driver for a serial eeprom. This is not a generic
+ * I2C interface. For a start, the device we're using (Atmel AT24C11)
+ * doesn't work like a regular I2C device. It looks like one
+ * electrically, but not logically. Normal I2C devices have a single
+ * 7-bit or 10-bit I2C address that they respond to. Valid 7-bit
+ * addresses range from 0x03 to 0x77. Addresses 0x00 to 0x02 and 0x78
+ * to 0x7F are special reserved addresses (e.g. 0x00 is the "general
+ * call" address.) The Atmel device, on the other hand, responds to ALL
+ * 7-bit addresses. It's designed to be the only device on a given I2C
+ * bus. A 7-bit address corresponds to the memory address within the
+ * Atmel device itself.
+ *
+ * Also, the timing requirements mean more than simple software
+ * bitbanging, with readbacks from chip to ensure timing (simple udelay
+ * is not enough).
+ *
+ * This all means that accessing the device is specialized enough
+ * that using the standard kernel I2C bitbanging interface would be
+ * impossible. For example, the core I2C eeprom driver expects to find
+ * a device at one or more of a limited set of addresses only. It doesn't
+ * allow writing to an eeprom. It also doesn't provide any means of
+ * accessing eeprom contents from within the kernel, only via sysfs.
+ */
+
+enum i2c_type {
+ i2c_line_scl = 0,
+ i2c_line_sda
+};
+
+enum i2c_state {
+ i2c_line_low = 0,
+ i2c_line_high
+};
+
+#define READ_CMD 1
+#define WRITE_CMD 0
+
+static int eeprom_init;
+
+/*
+ * The gpioval manipulation really should be protected by spinlocks
+ * or be converted to use atomic operations.
+ */
+
+/**
+ * i2c_gpio_set - set a GPIO line
+ * @dd: the infinipath device
+ * @line: the line to set
+ * @new_line_state: the state to set
+ *
+ * Returns 0 if the line was set to the new state successfully, non-zero
+ * on error.
+ */
+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;
+
+ gpioval = &dd->ipath_gpio_out;
+ read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
+ if (line == i2c_line_scl)
+ mask = ipath_gpio_scl;
+ else
+ mask = ipath_gpio_sda;
+
+ if (new_line_state == i2c_line_high)
+ /* tri-state the output rather than force high */
+ write_val = read_val & ~mask;
+ else
+ /* config line to be an output */
+ write_val = read_val | mask;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+
+ /* set high and verify */
+ if (new_line_state == i2c_line_high)
+ write_val = 0x1UL;
+ else
+ write_val = 0x0UL;
+
+ if (line == i2c_line_scl) {
+ write_val <<= ipath_gpio_scl_num;
+ *gpioval = *gpioval & ~(1UL << ipath_gpio_scl_num);
+ *gpioval |= write_val;
+ } else {
+ write_val <<= ipath_gpio_sda_num;
+ *gpioval = *gpioval & ~(1UL << ipath_gpio_sda_num);
+ *gpioval |= write_val;
+ }
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
+
+ return 0;
+}
+
+/**
+ * i2c_gpio_get - get a GPIO line state
+ * @dd: the infinipath device
+ * @line: the line to get
+ * @curr_statep: where to put the line state
+ *
+ * Returns 0 if the line was set to the new state successfully, non-zero
+ * on error. curr_state is not set on error.
+ */
+static int i2c_gpio_get(struct ipath_devdata *dd,
+ enum i2c_type line,
+ enum i2c_state *curr_statep)
+{
+ u64 read_val, write_val, mask;
+ int ret;
+
+ /* check args */
+ if (curr_statep == NULL) {
+ ret = 1;
+ 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 = ipath_gpio_scl;
+ else
+ mask = ipath_gpio_sda;
+ write_val = read_val & ~mask;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+ read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+ if (read_val & mask)
+ *curr_statep = i2c_line_high;
+ else
+ *curr_statep = i2c_line_low;
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * i2c_wait_for_writes - wait for a write
+ * @dd: the infinipath device
+ *
+ * We use this instead of udelay directly, so we can make sure
+ * that previous register writes have been flushed all the way
+ * to the chip. Since we are delaying anyway, the cost doesn't
+ * hurt, and makes the bit twiddling more regular
+ */
+static void i2c_wait_for_writes(struct ipath_devdata *dd)
+{
+ (void)ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
+}
+
+static void scl_out(struct ipath_devdata *dd, u8 bit)
+{
+ i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
+
+ i2c_wait_for_writes(dd);
+}
+
+static void sda_out(struct ipath_devdata *dd, u8 bit)
+{
+ i2c_gpio_set(dd, i2c_line_sda, bit ? i2c_line_high : i2c_line_low);
+
+ i2c_wait_for_writes(dd);
+}
+
+static u8 sda_in(struct ipath_devdata *dd, int wait)
+{
+ enum i2c_state bit;
+
+ if (i2c_gpio_get(dd, i2c_line_sda, &bit))
+ ipath_dbg("get bit failed!\n");
+
+ if (wait)
+ i2c_wait_for_writes(dd);
+
+ return bit == i2c_line_high ? 1U : 0;
+}
+
+/**
+ * i2c_ackrcv - see if ack following write is true
+ * @dd: the infinipath device
+ */
+static int i2c_ackrcv(struct ipath_devdata *dd)
+{
+ u8 ack_received;
+
+ /* AT ENTRY SCL = LOW */
+ /* change direction, ignore data */
+ ack_received = sda_in(dd, 1);
+ scl_out(dd, i2c_line_high);
+ ack_received = sda_in(dd, 1) == 0;
+ scl_out(dd, i2c_line_low);
+ return ack_received;
+}
+
+/**
+ * wr_byte - write a byte, one bit at a time
+ * @dd: the infinipath device
+ * @data: the byte to write
+ *
+ * Returns 0 if we got the following ack, otherwise 1
+ */
+static int wr_byte(struct ipath_devdata *dd, u8 data)
+{
+ int bit_cntr;
+ u8 bit;
+
+ for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) {
+ bit = (data >> bit_cntr) & 1;
+ sda_out(dd, bit);
+ scl_out(dd, i2c_line_high);
+ scl_out(dd, i2c_line_low);
+ }
+ return (!i2c_ackrcv(dd)) ? 1 : 0;
+}
+
+static void send_ack(struct ipath_devdata *dd)
+{
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_high);
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_high);
+}
+
+/**
+ * i2c_startcmd - transmit the start condition, followed by address/cmd
+ * @dd: the infinipath device
+ * @offset_dir: direction byte
+ *
+ * (both clock/data high, clock high, data low while clock is high)
+ */
+static int i2c_startcmd(struct ipath_devdata *dd, u8 offset_dir)
+{
+ int res;
+
+ /* issue start sequence */
+ sda_out(dd, i2c_line_high);
+ scl_out(dd, i2c_line_high);
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_low);
+
+ /* issue length and direction byte */
+ res = wr_byte(dd, offset_dir);
+
+ if (res)
+ ipath_cdbg(VERBOSE, "No ack to complete start\n");
+
+ return res;
+}
+
+/**
+ * stop_cmd - transmit the stop condition
+ * @dd: the infinipath device
+ *
+ * (both clock/data low, clock high, data high while clock is high)
+ */
+static void stop_cmd(struct ipath_devdata *dd)
+{
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_high);
+ sda_out(dd, i2c_line_high);
+ udelay(2);
+}
+
+/**
+ * eeprom_reset - reset I2C communication
+ * @dd: the infinipath device
+ */
+
+static int eeprom_reset(struct ipath_devdata *dd)
+{
+ int clock_cycles_left = 9;
+ u64 *gpioval = &dd->ipath_gpio_out;
+ int ret;
+
+ eeprom_init = 1;
+ *gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
+ ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
+ "is %llx\n", (unsigned long long) *gpioval);
+
+ /*
+ * This is to get the i2c into a known state, by first going low,
+ * then tristate sda (and then tristate scl as first thing
+ * in loop)
+ */
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_high);
+
+ while (clock_cycles_left--) {
+ scl_out(dd, i2c_line_high);
+
+ if (sda_in(dd, 0)) {
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_low);
+ ret = 0;
+ goto bail;
+ }
+
+ scl_out(dd, i2c_line_low);
+ }
+
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_eeprom_read - receives bytes from the eeprom via I2C
+ * @dd: the infinipath device
+ * @eeprom_offset: address to read from
+ * @buffer: where to store result
+ * @len: number of bytes to receive
+ */
+
+int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ void *buffer, int len)
+{
+ /* compiler complains unless initialized */
+ u8 single_byte = 0;
+ int bit_cntr;
+ int ret;
+
+ if (!eeprom_init)
+ eeprom_reset(dd);
+
+ eeprom_offset = (eeprom_offset << 1) | READ_CMD;
+
+ if (i2c_startcmd(dd, eeprom_offset)) {
+ ipath_dbg("Failed startcmd\n");
+ stop_cmd(dd);
+ ret = 1;
+ goto bail;
+ }
+
+ /*
+ * eeprom keeps clocking data out as long as we ack, automatically
+ * incrementing the address.
+ */
+ while (len-- > 0) {
+ /* get data */
+ single_byte = 0;
+ for (bit_cntr = 8; bit_cntr; bit_cntr--) {
+ u8 bit;
+ scl_out(dd, i2c_line_high);
+ bit = sda_in(dd, 0);
+ single_byte |= bit << (bit_cntr - 1);
+ scl_out(dd, i2c_line_low);
+ }
+
+ /* send ack if not the last byte */
+ if (len)
+ send_ack(dd);
+
+ *((u8 *) buffer) = single_byte;
+ buffer++;
+ }
+
+ stop_cmd(dd);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_eeprom_write - writes data to the eeprom via I2C
+ * @dd: the infinipath device
+ * @eeprom_offset: where to place data
+ * @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)
+{
+ u8 single_byte;
+ int sub_len;
+ const u8 *bp = buffer;
+ int max_wait_time, i;
+ int ret;
+
+ if (!eeprom_init)
+ eeprom_reset(dd);
+
+ while (len > 0) {
+ if (i2c_startcmd(dd, (eeprom_offset << 1) | WRITE_CMD)) {
+ ipath_dbg("Failed to start cmd offset %u\n",
+ eeprom_offset);
+ goto failed_write;
+ }
+
+ sub_len = min(len, 4);
+ eeprom_offset += sub_len;
+ len -= sub_len;
+
+ for (i = 0; i < sub_len; i++) {
+ if (wr_byte(dd, *bp++)) {
+ ipath_dbg("no ack after byte %u/%u (%u "
+ "total remain)\n", i, sub_len,
+ len + sub_len - i);
+ goto failed_write;
+ }
+ }
+
+ stop_cmd(dd);
+
+ /*
+ * wait for write complete by waiting for a successful
+ * read (the chip replies with a zero after the write
+ * cmd completes, and before it writes to the eeprom.
+ * The startcmd for the read will fail the ack until
+ * the writes have completed. We do this inline to avoid
+ * the debug prints that are in the real read routine
+ * if the startcmd fails.
+ */
+ max_wait_time = 100;
+ while (i2c_startcmd(dd, READ_CMD)) {
+ stop_cmd(dd);
+ if (!--max_wait_time) {
+ ipath_dbg("Did not get successful read to "
+ "complete write\n");
+ goto failed_write;
+ }
+ }
+ /* now read the zero byte */
+ for (i = single_byte = 0; i < 8; i++) {
+ u8 bit;
+ scl_out(dd, i2c_line_high);
+ bit = sda_in(dd, 0);
+ scl_out(dd, i2c_line_low);
+ single_byte <<= 1;
+ single_byte |= bit;
+ }
+ stop_cmd(dd);
+ }
+
+ ret = 0;
+ goto bail;
+
+failed_write:
+ stop_cmd(dd);
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+static u8 flash_csum(struct ipath_flash *ifp, int adjust)
+{
+ u8 *ip = (u8 *) ifp;
+ u8 csum = 0, len;
+
+ for (len = 0; len < ifp->if_length; len++)
+ csum += *ip++;
+ csum -= ifp->if_csum;
+ csum = ~csum;
+ if (adjust)
+ ifp->if_csum = csum;
+
+ return csum;
+}
+
+/**
+ * ipath_get_guid - get the GUID from the i2c device
+ * @dd: the infinipath device
+ *
+ * When we add the multi-chip support, we will probably have to add
+ * the ability to use the number of guids field, and get the guid from
+ * the first chip's flash, to use for all of them.
+ */
+void ipath_get_guid(struct ipath_devdata *dd)
+{
+ void *buf;
+ struct ipath_flash *ifp;
+ __be64 guid;
+ int len;
+ u8 csum, *bguid;
+ int t = dd->ipath_unit;
+ struct ipath_devdata *dd0 = ipath_lookup(0);
+
+ if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) {
+ u8 *bguid, oguid;
+ dd->ipath_guid = dd0->ipath_guid;
+ bguid = (u8 *) & dd->ipath_guid;
+
+ oguid = bguid[7];
+ bguid[7] += t;
+ if (oguid > bguid[7]) {
+ if (bguid[6] == 0xff) {
+ if (bguid[5] == 0xff) {
+ ipath_dev_err(
+ dd,
+ "Can't set %s GUID from "
+ "base, wraps to OUI!\n",
+ ipath_get_unit_name(t));
+ dd->ipath_guid = 0;
+ goto bail;
+ }
+ bguid[5]++;
+ }
+ bguid[6]++;
+ }
+ dd->ipath_nguid = 1;
+
+ ipath_dbg("nguid %u, so adding %u to device 0 guid, "
+ "for %llx\n",
+ dd0->ipath_nguid, t,
+ (unsigned long long) be64_to_cpu(dd->ipath_guid));
+ goto bail;
+ }
+
+ len = offsetof(struct ipath_flash, if_future);
+ buf = vmalloc(len);
+ if (!buf) {
+ ipath_dev_err(dd, "Couldn't allocate memory to read %u "
+ "bytes from eeprom for GUID\n", len);
+ goto bail;
+ }
+
+ if (ipath_eeprom_read(dd, 0, buf, len)) {
+ ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
+ goto done;
+ }
+ ifp = (struct ipath_flash *)buf;
+
+ csum = flash_csum(ifp, 0);
+ if (csum != ifp->if_csum) {
+ dev_info(&dd->pcidev->dev, "Bad I2C flash checksum: "
+ "0x%x, not 0x%x\n", csum, ifp->if_csum);
+ goto done;
+ }
+ if (*(__be64 *) ifp->if_guid == 0ULL ||
+ *(__be64 *) ifp->if_guid == __constant_cpu_to_be64(-1LL)) {
+ ipath_dev_err(dd, "Invalid GUID %llx from flash; "
+ "ignoring\n",
+ *(unsigned long long *) ifp->if_guid);
+ /* don't allow GUID if all 0 or all 1's */
+ goto done;
+ }
+
+ /* complain, but allow it */
+ if (*(u64 *) ifp->if_guid == 0x100007511000000ULL)
+ dev_info(&dd->pcidev->dev, "Warning, GUID %llx is "
+ "default, probably not correct!\n",
+ *(unsigned long long *) ifp->if_guid);
+
+ bguid = ifp->if_guid;
+ if (!bguid[0] && !bguid[1] && !bguid[2]) {
+ /* original incorrect GUID format in flash; fix in
+ * core copy, by shifting up 2 octets; don't need to
+ * change top octet, since both it and shifted are
+ * 0.. */
+ bguid[1] = bguid[3];
+ bguid[2] = bguid[4];
+ bguid[3] = bguid[4] = 0;
+ guid = *(__be64 *) ifp->if_guid;
+ ipath_cdbg(VERBOSE, "Old GUID format in flash, top 3 zero, "
+ "shifting 2 octets\n");
+ } else
+ guid = *(__be64 *) ifp->if_guid;
+ dd->ipath_guid = guid;
+ dd->ipath_nguid = ifp->if_numguid;
+ memcpy(dd->ipath_serial, ifp->if_serial,
+ sizeof(ifp->if_serial));
+ ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
+ (unsigned long long) be64_to_cpu(dd->ipath_guid));
+
+done:
+ vfree(buf);
+
+bail:;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
new file mode 100644
index 000000000000..c347191f02bf
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -0,0 +1,1910 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/swap.h>
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+static int ipath_open(struct inode *, struct file *);
+static int ipath_close(struct inode *, struct file *);
+static ssize_t ipath_write(struct file *, const char __user *, size_t,
+ loff_t *);
+static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
+static int ipath_mmap(struct file *, struct vm_area_struct *);
+
+static struct file_operations ipath_file_ops = {
+ .owner = THIS_MODULE,
+ .write = ipath_write,
+ .open = ipath_open,
+ .release = ipath_close,
+ .poll = ipath_poll,
+ .mmap = ipath_mmap
+};
+
+static int ipath_get_base_info(struct ipath_portdata *pd,
+ void __user *ubase, size_t ubase_size)
+{
+ int ret = 0;
+ struct ipath_base_info *kinfo = NULL;
+ struct ipath_devdata *dd = pd->port_dd;
+
+ if (ubase_size < sizeof(*kinfo)) {
+ ipath_cdbg(PROC,
+ "Base size %lu, need %lu (version mismatch?)\n",
+ (unsigned long) ubase_size,
+ (unsigned long) sizeof(*kinfo));
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ kinfo = kzalloc(sizeof(*kinfo), GFP_KERNEL);
+ if (kinfo == NULL) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ ret = dd->ipath_f_get_base_info(pd, kinfo);
+ if (ret < 0)
+ goto bail;
+
+ kinfo->spi_rcvhdr_cnt = dd->ipath_rcvhdrcnt;
+ kinfo->spi_rcvhdrent_size = dd->ipath_rcvhdrentsize;
+ kinfo->spi_tidegrcnt = dd->ipath_rcvegrcnt;
+ kinfo->spi_rcv_egrbufsize = dd->ipath_rcvegrbufsize;
+ /*
+ * have to mmap whole thing
+ */
+ kinfo->spi_rcv_egrbuftotlen =
+ pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size;
+ kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk;
+ kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen /
+ pd->port_rcvegrbuf_chunks;
+ kinfo->spi_tidcnt = dd->ipath_rcvtidcnt;
+ /*
+ * for this use, may be ipath_cfgports summed over all chips that
+ * are are configured and present
+ */
+ kinfo->spi_nports = dd->ipath_cfgports;
+ /* unit (chip/board) our port is on */
+ kinfo->spi_unit = dd->ipath_unit;
+ /* for now, only a single page */
+ kinfo->spi_tid_maxsize = PAGE_SIZE;
+
+ /*
+ * Doing this per port, and based on the skip value, etc. This has
+ * to be the actual buffer size, since the protocol code treats it
+ * as an array.
+ *
+ * These have to be set to user addresses in the user code via mmap.
+ * These values are used on return to user code for the mmap target
+ * addresses only. For 32 bit, same 44 bit address problem, so use
+ * the physical address, not virtual. Before 2.6.11, using the
+ * page_address() macro worked, but in 2.6.11, even that returns the
+ * full 64 bit address (upper bits all 1's). So far, using the
+ * physical addresses (or chip offsets, for chip mapping) works, but
+ * no doubt some future kernel release will chang that, and we'll be
+ * on to yet another method of dealing with this
+ */
+ kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys;
+ kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys;
+ kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys;
+ kinfo->spi_status = (u64) kinfo->spi_pioavailaddr +
+ (void *) dd->ipath_statusp -
+ (void *) dd->ipath_pioavailregs_dma;
+ kinfo->spi_piobufbase = (u64) pd->port_piobufs;
+ kinfo->__spi_uregbase =
+ dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+
+ kinfo->spi_pioindex = dd->ipath_pbufsport * (pd->port_port - 1);
+ kinfo->spi_piocnt = dd->ipath_pbufsport;
+ kinfo->spi_pioalign = dd->ipath_palign;
+
+ kinfo->spi_qpair = IPATH_KD_QP;
+ kinfo->spi_piosize = dd->ipath_ibmaxlen;
+ kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */
+ kinfo->spi_port = pd->port_port;
+ kinfo->spi_sw_version = IPATH_USER_SWVERSION;
+ kinfo->spi_hw_version = dd->ipath_revision;
+
+ if (copy_to_user(ubase, kinfo, sizeof(*kinfo)))
+ ret = -EFAULT;
+
+bail:
+ kfree(kinfo);
+ return ret;
+}
+
+/**
+ * ipath_tid_update - update a port TID
+ * @pd: the port
+ * @ti: the TID information
+ *
+ * The new implementation as of Oct 2004 is that the driver assigns
+ * the tid and returns it to the caller. To make it easier to
+ * catch bugs, and to reduce search time, we keep a cursor for
+ * each port, walking the shadow tid array to find one that's not
+ * in use.
+ *
+ * For now, if we can't allocate the full list, we fail, although
+ * in the long run, we'll allocate as many as we can, and the
+ * caller will deal with that by trying the remaining pages later.
+ * That means that when we fail, we have to mark the tids as not in
+ * use again, in our shadow copy.
+ *
+ * It's up to the caller to free the tids when they are done.
+ * We'll unlock the pages as they free them.
+ *
+ * Also, right now we are locking one page at a time, but since
+ * the intended use of this routine is for a single group of
+ * virtually contiguous pages, that should change to improve
+ * performance.
+ */
+static int ipath_tid_update(struct ipath_portdata *pd,
+ const struct ipath_tid_info *ti)
+{
+ int ret = 0, ntids;
+ u32 tid, porttid, cnt, i, tidcnt;
+ u16 *tidlist;
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 physaddr;
+ unsigned long vaddr;
+ u64 __iomem *tidbase;
+ unsigned long tidmap[8];
+ struct page **pagep = NULL;
+
+ if (!dd->ipath_pageshadow) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ cnt = ti->tidcnt;
+ if (!cnt) {
+ ipath_dbg("After copyin, tidcnt 0, tidlist %llx\n",
+ (unsigned long long) ti->tidlist);
+ /*
+ * Should we treat as success? likely a bug
+ */
+ ret = -EFAULT;
+ goto done;
+ }
+ tidcnt = dd->ipath_rcvtidcnt;
+ if (cnt >= tidcnt) {
+ /* make sure it all fits in port_tid_pg_list */
+ dev_info(&dd->pcidev->dev, "Process tried to allocate %u "
+ "TIDs, only trying max (%u)\n", cnt, tidcnt);
+ cnt = tidcnt;
+ }
+ pagep = (struct page **)pd->port_tid_pg_list;
+ tidlist = (u16 *) (&pagep[cnt]);
+
+ memset(tidmap, 0, sizeof(tidmap));
+ tid = pd->port_tidcursor;
+ /* before decrement; chip actual # */
+ porttid = pd->port_port * tidcnt;
+ ntids = tidcnt;
+ tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ porttid * sizeof(*tidbase));
+
+ ipath_cdbg(VERBOSE, "Port%u %u tids, cursor %u, tidbase %p\n",
+ pd->port_port, cnt, tid, tidbase);
+
+ /* virtual address of first page in transfer */
+ vaddr = ti->tidvaddr;
+ if (!access_ok(VERIFY_WRITE, (void __user *) vaddr,
+ cnt * PAGE_SIZE)) {
+ ipath_dbg("Fail vaddr %p, %u pages, !access_ok\n",
+ (void *)vaddr, cnt);
+ ret = -EFAULT;
+ goto done;
+ }
+ ret = ipath_get_user_pages(vaddr, cnt, pagep);
+ if (ret) {
+ if (ret == -EBUSY) {
+ ipath_dbg("Failed to lock addr %p, %u pages "
+ "(already locked)\n",
+ (void *) vaddr, cnt);
+ /*
+ * for now, continue, and see what happens but with
+ * the new implementation, this should never happen,
+ * unless perhaps the user has mpin'ed the pages
+ * themselves (something we need to test)
+ */
+ ret = 0;
+ } else {
+ dev_info(&dd->pcidev->dev,
+ "Failed to lock addr %p, %u pages: "
+ "errno %d\n", (void *) vaddr, cnt, -ret);
+ goto done;
+ }
+ }
+ for (i = 0; i < cnt; i++, vaddr += PAGE_SIZE) {
+ for (; ntids--; tid++) {
+ if (tid == tidcnt)
+ tid = 0;
+ if (!dd->ipath_pageshadow[porttid + tid])
+ break;
+ }
+ if (ntids < 0) {
+ /*
+ * oops, wrapped all the way through their TIDs,
+ * and didn't have enough free; see comments at
+ * start of routine
+ */
+ ipath_dbg("Not enough free TIDs for %u pages "
+ "(index %d), failing\n", cnt, i);
+ i--; /* last tidlist[i] not filled in */
+ ret = -ENOMEM;
+ break;
+ }
+ tidlist[i] = tid;
+ ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, "
+ "vaddr %lx\n", i, tid, vaddr);
+ /* we "know" system pages and TID pages are same size */
+ dd->ipath_pageshadow[porttid + tid] = pagep[i];
+ /*
+ * don't need atomic or it's overhead
+ */
+ __set_bit(tid, tidmap);
+ physaddr = page_to_phys(pagep[i]);
+ ipath_stats.sps_pagelocks++;
+ ipath_cdbg(VERBOSE,
+ "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);
+ /*
+ * don't check this tid in ipath_portshadow, since we
+ * just filled it in; start with the next one.
+ */
+ tid++;
+ }
+
+ if (ret) {
+ u32 limit;
+ cleanup:
+ /* jump here if copy out of updated info failed... */
+ ipath_dbg("After failure (ret=%d), undo %d of %d entries\n",
+ -ret, i, cnt);
+ /* same code that's in ipath_free_tid() */
+ limit = sizeof(tidmap) * BITS_PER_BYTE;
+ if (limit > tidcnt)
+ /* just in case size changes in future */
+ limit = tidcnt;
+ tid = find_first_bit((const unsigned long *)tidmap, limit);
+ for (; tid < limit; tid++) {
+ if (!test_bit(tid, tidmap))
+ continue;
+ 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_tidinvalid);
+ dd->ipath_pageshadow[porttid + tid] = NULL;
+ ipath_stats.sps_pageunlocks++;
+ }
+ }
+ ipath_release_user_pages(pagep, cnt);
+ } else {
+ /*
+ * Copy the updated array, with ipath_tid's filled in, back
+ * to user. Since we did the copy in already, this "should
+ * never fail" If it does, we have to clean up...
+ */
+ if (copy_to_user((void __user *)
+ (unsigned long) ti->tidlist,
+ tidlist, cnt * sizeof(*tidlist))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ if (copy_to_user((void __user *) (unsigned long) ti->tidmap,
+ tidmap, sizeof tidmap)) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ if (tid == tidcnt)
+ tid = 0;
+ pd->port_tidcursor = tid;
+ }
+
+done:
+ if (ret)
+ ipath_dbg("Failed to map %u TID pages, failing with %d\n",
+ ti->tidcnt, -ret);
+ return ret;
+}
+
+/**
+ * ipath_tid_free - free a port TID
+ * @pd: the port
+ * @ti: the TID info
+ *
+ * right now we are unlocking one page at a time, but since
+ * the intended use of this routine is for a single group of
+ * virtually contiguous pages, that should change to improve
+ * performance. We check that the TID is in range for this port
+ * but otherwise don't check validity; if user has an error and
+ * frees the wrong tid, it's only their own data that can thereby
+ * be corrupted. We do check that the TID was in use, for sanity
+ * We always use our idea of the saved address, not the address that
+ * they pass in to us.
+ */
+
+static int ipath_tid_free(struct ipath_portdata *pd,
+ const struct ipath_tid_info *ti)
+{
+ int ret = 0;
+ u32 tid, porttid, cnt, limit, tidcnt;
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 __iomem *tidbase;
+ unsigned long tidmap[8];
+
+ if (!dd->ipath_pageshadow) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ if (copy_from_user(tidmap, (void __user *)(unsigned long)ti->tidmap,
+ sizeof tidmap)) {
+ ret = -EFAULT;
+ goto done;
+ }
+
+ porttid = pd->port_port * dd->ipath_rcvtidcnt;
+ tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ porttid * sizeof(*tidbase));
+
+ tidcnt = dd->ipath_rcvtidcnt;
+ limit = sizeof(tidmap) * BITS_PER_BYTE;
+ if (limit > tidcnt)
+ /* just in case size changes in future */
+ limit = tidcnt;
+ tid = find_first_bit(tidmap, limit);
+ ipath_cdbg(VERBOSE, "Port%u free %u tids; first bit (max=%d) "
+ "set is %d, porttid %u\n", pd->port_port, ti->tidcnt,
+ limit, tid, porttid);
+ for (cnt = 0; tid < limit; tid++) {
+ /*
+ * small optimization; if we detect a run of 3 or so without
+ * any set, use find_first_bit again. That's mainly to
+ * accelerate the case where we wrapped, so we have some at
+ * the beginning, and some at the end, and a big gap
+ * in the middle.
+ */
+ if (!test_bit(tid, tidmap))
+ continue;
+ cnt++;
+ 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_tidinvalid);
+ ipath_release_user_pages(
+ &dd->ipath_pageshadow[porttid + tid], 1);
+ dd->ipath_pageshadow[porttid + tid] = NULL;
+ ipath_stats.sps_pageunlocks++;
+ } else
+ ipath_dbg("Unused tid %u, ignoring\n", tid);
+ }
+ if (cnt != ti->tidcnt)
+ ipath_dbg("passed in tidcnt %d, only %d bits set in map\n",
+ ti->tidcnt, cnt);
+done:
+ if (ret)
+ ipath_dbg("Failed to unmap %u TID pages, failing with %d\n",
+ ti->tidcnt, -ret);
+ return ret;
+}
+
+/**
+ * ipath_set_part_key - set a partition key
+ * @pd: the port
+ * @key: the key
+ *
+ * We can have up to 4 active at a time (other than the default, which is
+ * always allowed). This is somewhat tricky, since multiple ports may set
+ * the same key, so we reference count them, and clean up at exit. All 4
+ * partition keys are packed into a single infinipath register. It's an
+ * error for a process to set the same pkey multiple times. We provide no
+ * mechanism to de-allocate a pkey at this time, we may eventually need to
+ * do that. I've used the atomic operations, and no locking, and only make
+ * a single pass through what's available. This should be more than
+ * adequate for some time. I'll think about spinlocks or the like if and as
+ * it's necessary.
+ */
+static int ipath_set_part_key(struct ipath_portdata *pd, u16 key)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ int i, any = 0, pidx = -1;
+ u16 lkey = key & 0x7FFF;
+ int ret;
+
+ if (lkey == (IPS_DEFAULT_P_KEY & 0x7FFF)) {
+ /* nothing to do; this key always valid */
+ ret = 0;
+ goto bail;
+ }
+
+ ipath_cdbg(VERBOSE, "p%u try to set pkey %hx, current keys "
+ "%hx:%x %hx:%x %hx:%x %hx:%x\n",
+ pd->port_port, key, dd->ipath_pkeys[0],
+ atomic_read(&dd->ipath_pkeyrefs[0]), dd->ipath_pkeys[1],
+ atomic_read(&dd->ipath_pkeyrefs[1]), dd->ipath_pkeys[2],
+ atomic_read(&dd->ipath_pkeyrefs[2]), dd->ipath_pkeys[3],
+ atomic_read(&dd->ipath_pkeyrefs[3]));
+
+ if (!lkey) {
+ ipath_cdbg(PROC, "p%u tries to set key 0, not allowed\n",
+ pd->port_port);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ /*
+ * Set the full membership bit, because it has to be
+ * set in the register or the packet, and it seems
+ * cleaner to set in the register than to force all
+ * callers to set it. (see bug 4331)
+ */
+ key |= 0x8000;
+
+ for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+ if (!pd->port_pkeys[i] && pidx == -1)
+ pidx = i;
+ if (pd->port_pkeys[i] == key) {
+ ipath_cdbg(VERBOSE, "p%u tries to set same pkey "
+ "(%x) more than once\n",
+ pd->port_port, key);
+ ret = -EEXIST;
+ goto bail;
+ }
+ }
+ if (pidx == -1) {
+ ipath_dbg("All pkeys for port %u already in use, "
+ "can't set %x\n", pd->port_port, key);
+ ret = -EBUSY;
+ goto bail;
+ }
+ for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i]) {
+ any++;
+ continue;
+ }
+ if (dd->ipath_pkeys[i] == key) {
+ atomic_t *pkrefs = &dd->ipath_pkeyrefs[i];
+
+ if (atomic_inc_return(pkrefs) > 1) {
+ pd->port_pkeys[pidx] = key;
+ ipath_cdbg(VERBOSE, "p%u set key %x "
+ "matches #%d, count now %d\n",
+ pd->port_port, key, i,
+ atomic_read(pkrefs));
+ ret = 0;
+ goto bail;
+ } else {
+ /*
+ * lost race, decrement count, catch below
+ */
+ atomic_dec(pkrefs);
+ ipath_cdbg(VERBOSE, "Lost race, count was "
+ "0, after dec, it's %d\n",
+ atomic_read(pkrefs));
+ any++;
+ }
+ }
+ if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
+ /*
+ * It makes no sense to have both the limited and
+ * full membership PKEY set at the same time since
+ * the unlimited one will disable the limited one.
+ */
+ ret = -EEXIST;
+ goto bail;
+ }
+ }
+ if (!any) {
+ ipath_dbg("port %u, all pkeys already in use, "
+ "can't set %x\n", pd->port_port, key);
+ ret = -EBUSY;
+ goto bail;
+ }
+ for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i] &&
+ atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
+ u64 pkey;
+
+ /* for ipathstats, etc. */
+ ipath_stats.sps_pkeys[i] = lkey;
+ pd->port_pkeys[pidx] = dd->ipath_pkeys[i] = key;
+ pkey =
+ (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+ ipath_cdbg(PROC, "p%u set key %x in #%d, "
+ "portidx %d, new pkey reg %llx\n",
+ pd->port_port, key, i, pidx,
+ (unsigned long long) pkey);
+ ipath_write_kreg(
+ dd, dd->ipath_kregs->kr_partitionkey, pkey);
+
+ ret = 0;
+ goto bail;
+ }
+ }
+ ipath_dbg("port %u, all pkeys already in use 2nd pass, "
+ "can't set %x\n", pd->port_port, key);
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_manage_rcvq - manage a port's receive queue
+ * @pd: the port
+ * @start_stop: action to carry out
+ *
+ * start_stop == 0 disables receive on the port, for use in queue
+ * overflow conditions. start_stop==1 re-enables, to be used to
+ * re-init the software copy of the head register
+ */
+static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 tval;
+
+ ipath_cdbg(PROC, "%sabling rcv for unit %u port %u\n",
+ start_stop ? "en" : "dis", dd->ipath_unit,
+ pd->port_port);
+ /* atomically clear receive enable port. */
+ if (start_stop) {
+ /*
+ * On enable, force in-memory copy of the tail register to
+ * 0, so that protocol code doesn't have to worry about
+ * whether or not the chip has yet updated the in-memory
+ * copy or not on return from the system call. The chip
+ * always resets it's tail register back to 0 on a
+ * transition from disabled to enabled. This could cause a
+ * problem if software was broken, and did the enable w/o
+ * the disable, but eventually the in-memory copy will be
+ * updated and correct itself, even in the face of software
+ * bugs.
+ */
+ *pd->port_rcvhdrtail_kvaddr = 0;
+ set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+ &dd->ipath_rcvctrl);
+ } else
+ clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+ &dd->ipath_rcvctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+ /* now be sure chip saw it before we return */
+ tval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ if (start_stop) {
+ /*
+ * And try to be sure that tail reg update has happened too.
+ * This should in theory interlock with the RXE changes to
+ * the tail register. Don't assign it to the tail register
+ * in memory copy, since we could overwrite an update by the
+ * chip if we did.
+ */
+ tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ }
+ /* always; new head should be equal to new tail; see above */
+ return 0;
+}
+
+static void ipath_clean_part_key(struct ipath_portdata *pd,
+ struct ipath_devdata *dd)
+{
+ int i, j, pchanged = 0;
+ u64 oldpkey;
+
+ /* for debugging only */
+ oldpkey = (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+
+ for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+ if (!pd->port_pkeys[i])
+ continue;
+ ipath_cdbg(VERBOSE, "look for key[%d] %hx in pkeys\n", i,
+ pd->port_pkeys[i]);
+ for (j = 0; j < ARRAY_SIZE(dd->ipath_pkeys); j++) {
+ /* check for match independent of the global bit */
+ if ((dd->ipath_pkeys[j] & 0x7fff) !=
+ (pd->port_pkeys[i] & 0x7fff))
+ continue;
+ if (atomic_dec_and_test(&dd->ipath_pkeyrefs[j])) {
+ ipath_cdbg(VERBOSE, "p%u clear key "
+ "%x matches #%d\n",
+ pd->port_port,
+ pd->port_pkeys[i], j);
+ ipath_stats.sps_pkeys[j] =
+ dd->ipath_pkeys[j] = 0;
+ pchanged++;
+ }
+ else ipath_cdbg(
+ VERBOSE, "p%u key %x matches #%d, "
+ "but ref still %d\n", pd->port_port,
+ pd->port_pkeys[i], j,
+ atomic_read(&dd->ipath_pkeyrefs[j]));
+ break;
+ }
+ pd->port_pkeys[i] = 0;
+ }
+ if (pchanged) {
+ u64 pkey = (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+ ipath_cdbg(VERBOSE, "p%u old pkey reg %llx, "
+ "new pkey reg %llx\n", pd->port_port,
+ (unsigned long long) oldpkey,
+ (unsigned long long) pkey);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
+ pkey);
+ }
+}
+
+/**
+ * ipath_create_user_egr - allocate eager TID buffers
+ * @pd: the port to allocate TID buffers for
+ *
+ * This routine is now quite different for user and kernel, because
+ * the kernel uses skb's, for the accelerated network performance
+ * This is the user port version
+ *
+ * Allocate the eager TID buffers and program them into infinipath
+ * They are no longer completely contiguous, we do multiple allocation
+ * calls.
+ */
+static int ipath_create_user_egr(struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff;
+ size_t size;
+ int ret;
+
+ egrcnt = dd->ipath_rcvegrcnt;
+ /* TID number offset for this port */
+ egroff = pd->port_port * egrcnt;
+ egrsize = dd->ipath_rcvegrbufsize;
+ ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
+ "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
+
+ /*
+ * to avoid wasting a lot of memory, we allocate 32KB chunks of
+ * physically contiguous memory, advance through it until used up
+ * and then allocate more. Of course, we need memory to store those
+ * extra pointers, now. Started out with 256KB, but under heavy
+ * memory pressure (creating large files and then copying them over
+ * NFS while doing lots of MPI jobs), we hit some allocation
+ * failures, even though we can sleep... (2.6.10) Still get
+ * failures at 64K. 32K is the lowest we can go without waiting
+ * more memory again. It seems likely that the coalescing in
+ * free_pages, etc. still has issues (as it has had previously
+ * during 2.6.x development).
+ */
+ size = 0x8000;
+ alloced = ALIGN(egrsize * egrcnt, size);
+ egrperchunk = size / egrsize;
+ chunk = (egrcnt + egrperchunk - 1) / egrperchunk;
+ pd->port_rcvegrbuf_chunks = chunk;
+ pd->port_rcvegrbufs_perchunk = egrperchunk;
+ pd->port_rcvegrbuf_size = size;
+ pd->port_rcvegrbuf = vmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]));
+ if (!pd->port_rcvegrbuf) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ pd->port_rcvegrbuf_phys =
+ vmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]));
+ if (!pd->port_rcvegrbuf_phys) {
+ ret = -ENOMEM;
+ goto bail_rcvegrbuf;
+ }
+ for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) {
+ /*
+ * GFP_USER, but without GFP_FS, so buffer cache can be
+ * coalesced (we hope); otherwise, even at order 4,
+ * heavy filesystem activity makes these fail
+ */
+ gfp_t gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP;
+
+ pd->port_rcvegrbuf[e] = dma_alloc_coherent(
+ &dd->pcidev->dev, size, &pd->port_rcvegrbuf_phys[e],
+ gfp_flags);
+
+ if (!pd->port_rcvegrbuf[e]) {
+ ret = -ENOMEM;
+ goto bail_rcvegrbuf_phys;
+ }
+ }
+
+ pd->port_rcvegr_phys = pd->port_rcvegrbuf_phys[0];
+
+ for (e = chunk = 0; chunk < pd->port_rcvegrbuf_chunks; chunk++) {
+ dma_addr_t pa = pd->port_rcvegrbuf_phys[chunk];
+ unsigned i;
+
+ for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) {
+ dd->ipath_f_put_tid(dd, e + egroff +
+ (u64 __iomem *)
+ ((char __iomem *)
+ dd->ipath_kregbase +
+ dd->ipath_rcvegrbase), 0, pa);
+ pa += egrsize;
+ }
+ cond_resched(); /* don't hog the cpu */
+ }
+
+ ret = 0;
+ goto bail;
+
+bail_rcvegrbuf_phys:
+ for (e = 0; e < pd->port_rcvegrbuf_chunks &&
+ pd->port_rcvegrbuf[e]; e++)
+ dma_free_coherent(&dd->pcidev->dev, size,
+ pd->port_rcvegrbuf[e],
+ pd->port_rcvegrbuf_phys[e]);
+
+ vfree(pd->port_rcvegrbuf_phys);
+ pd->port_rcvegrbuf_phys = NULL;
+bail_rcvegrbuf:
+ vfree(pd->port_rcvegrbuf);
+ pd->port_rcvegrbuf = NULL;
+bail:
+ return ret;
+}
+
+static int ipath_do_user_init(struct ipath_portdata *pd,
+ const struct ipath_user_info *uinfo)
+{
+ int ret = 0;
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 physaddr, uaddr, off, atmp;
+ struct page *pagep;
+ u32 head32;
+ u64 head;
+
+ /* for now, if major version is different, bail */
+ if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+ dev_info(&dd->pcidev->dev,
+ "User major version %d not same as driver "
+ "major %d\n", uinfo->spu_userversion >> 16,
+ IPATH_USER_SWMAJOR);
+ ret = -ENODEV;
+ goto done;
+ }
+
+ if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR)
+ ipath_dbg("User minor version %d not same as driver "
+ "minor %d\n", uinfo->spu_userversion & 0xffff,
+ IPATH_USER_SWMINOR);
+
+ if (uinfo->spu_rcvhdrsize) {
+ ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize);
+ if (ret)
+ goto done;
+ }
+
+ /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */
+
+ /* set up for the rcvhdr Q tail register writeback to user memory */
+ if (!uinfo->spu_rcvhdraddr ||
+ !access_ok(VERIFY_WRITE, (u64 __user *) (unsigned long)
+ uinfo->spu_rcvhdraddr, sizeof(u64))) {
+ ipath_dbg("Port %d rcvhdrtail addr %llx not valid\n",
+ pd->port_port,
+ (unsigned long long) uinfo->spu_rcvhdraddr);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ off = offset_in_page(uinfo->spu_rcvhdraddr);
+ uaddr = PAGE_MASK & (unsigned long) uinfo->spu_rcvhdraddr;
+ ret = ipath_get_user_pages_nocopy(uaddr, &pagep);
+ if (ret) {
+ dev_info(&dd->pcidev->dev, "Failed to lookup and lock "
+ "address %llx for rcvhdrtail: errno %d\n",
+ (unsigned long long) uinfo->spu_rcvhdraddr, -ret);
+ goto done;
+ }
+ ipath_stats.sps_pagelocks++;
+ pd->port_rcvhdrtail_uaddr = uaddr;
+ pd->port_rcvhdrtail_pagep = pagep;
+ pd->port_rcvhdrtail_kvaddr =
+ page_address(pagep);
+ pd->port_rcvhdrtail_kvaddr += off;
+ physaddr = page_to_phys(pagep) + off;
+ ipath_cdbg(VERBOSE, "port %d user addr %llx hdrtailaddr, %llx "
+ "physical (off=%llx)\n",
+ pd->port_port,
+ (unsigned long long) uinfo->spu_rcvhdraddr,
+ (unsigned long long) physaddr, (unsigned long long) off);
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+ pd->port_port, physaddr);
+ atmp = ipath_read_kreg64_port(dd,
+ dd->ipath_kregs->kr_rcvhdrtailaddr,
+ pd->port_port);
+ if (physaddr != atmp) {
+ ipath_dev_err(dd,
+ "Catastrophic software error, "
+ "RcvHdrTailAddr%u written as %llx, "
+ "read back as %llx\n", pd->port_port,
+ (unsigned long long) physaddr,
+ (unsigned long long) atmp);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* for right now, kernel piobufs are at end, so port 1 is at 0 */
+ pd->port_piobufs = dd->ipath_piobufbase +
+ dd->ipath_pbufsport * (pd->port_port -
+ 1) * dd->ipath_palign;
+ ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
+ pd->port_port, pd->port_piobufs);
+
+ /*
+ * Now allocate the rcvhdr Q and eager TIDs; skip the TID
+ * array for time being. If pd->port_port > chip-supported,
+ * we need to do extra stuff here to handle by handling overflow
+ * through port 0, someday
+ */
+ ret = ipath_create_rcvhdrq(dd, pd);
+ if (!ret)
+ ret = ipath_create_user_egr(pd);
+ if (ret)
+ goto done;
+ /* enable receives now */
+ /* atomically set enable bit for this port */
+ set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+ &dd->ipath_rcvctrl);
+
+ /*
+ * set the head registers for this port to the current values
+ * of the tail pointers, since we don't know if they were
+ * updated on last use of the port.
+ */
+ head32 = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ head = (u64) head32;
+ ipath_write_ureg(dd, ur_rcvhdrhead, head, pd->port_port);
+ head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
+ ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
+ dd->ipath_lastegrheads[pd->port_port] = -1;
+ dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
+ ipath_cdbg(VERBOSE, "Wrote port%d head %llx, egrhead %x from "
+ "tail regs\n", pd->port_port,
+ (unsigned long long) head, head32);
+ pd->port_tidcursor = 0; /* start at beginning after open */
+ /*
+ * now enable the port; the tail registers will be written to memory
+ * by the chip as soon as it sees the write to
+ * dd->ipath_kregs->kr_rcvctrl. The update only happens on
+ * transition from 0 to 1, so clear it first, then set it as part of
+ * enabling the port. This will (very briefly) affect any other
+ * open ports, but it shouldn't be long enough to be an issue.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+done:
+ return ret;
+}
+
+static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd,
+ u64 ureg)
+{
+ unsigned long phys;
+ int ret;
+
+ /* it's the real hardware, so io_remap works */
+
+ if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
+ dev_info(&dd->pcidev->dev, "FAIL mmap userreg: reqlen "
+ "%lx > PAGE\n", vma->vm_end - vma->vm_start);
+ ret = -EFAULT;
+ } else {
+ phys = dd->ipath_physaddr + ureg;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+ ret = io_remap_pfn_range(vma, vma->vm_start,
+ phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ }
+ return ret;
+}
+
+static int mmap_piobufs(struct vm_area_struct *vma,
+ struct ipath_devdata *dd,
+ struct ipath_portdata *pd)
+{
+ unsigned long phys;
+ int ret;
+
+ /*
+ * When we map the PIO buffers, we want to map them as writeonly, no
+ * read possible.
+ */
+
+ if ((vma->vm_end - vma->vm_start) >
+ (dd->ipath_pbufsport * dd->ipath_palign)) {
+ dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: "
+ "reqlen %lx > PAGE\n",
+ vma->vm_end - vma->vm_start);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ phys = dd->ipath_physaddr + pd->port_piobufs;
+ /*
+ * Do *NOT* mark this as non-cached (PWT bit), or we don't get the
+ * write combining behavior we want on the PIO buffers!
+ * vma->vm_page_prot =
+ * pgprot_noncached(vma->vm_page_prot);
+ */
+
+ if (vma->vm_flags & VM_READ) {
+ dev_info(&dd->pcidev->dev,
+ "Can't map piobufs as readable (flags=%lx)\n",
+ vma->vm_flags);
+ ret = -EPERM;
+ goto bail;
+ }
+
+ /* don't allow them to later change to readable with mprotect */
+
+ vma->vm_flags &= ~VM_MAYWRITE;
+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+
+ ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+bail:
+ return ret;
+}
+
+static int mmap_rcvegrbufs(struct vm_area_struct *vma,
+ struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ unsigned long start, size;
+ size_t total_size, i;
+ dma_addr_t *phys;
+ int ret;
+
+ if (!pd->port_rcvegrbuf) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ size = pd->port_rcvegrbuf_size;
+ total_size = pd->port_rcvegrbuf_chunks * size;
+ if ((vma->vm_end - vma->vm_start) > total_size) {
+ dev_info(&dd->pcidev->dev, "FAIL on egr bufs: "
+ "reqlen %lx > actual %lx\n",
+ vma->vm_end - vma->vm_start,
+ (unsigned long) total_size);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ if (vma->vm_flags & VM_WRITE) {
+ dev_info(&dd->pcidev->dev, "Can't map eager buffers as "
+ "writable (flags=%lx)\n", vma->vm_flags);
+ ret = -EPERM;
+ goto bail;
+ }
+
+ start = vma->vm_start;
+ phys = pd->port_rcvegrbuf_phys;
+
+ /* don't allow them to later change to writeable with mprotect */
+ vma->vm_flags &= ~VM_MAYWRITE;
+
+ for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) {
+ ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+ if (ret < 0)
+ goto bail;
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int mmap_rcvhdrq(struct vm_area_struct *vma,
+ struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ size_t total_size;
+ int ret;
+
+ /*
+ * kmalloc'ed memory, physically contiguous; this is from
+ * spi_rcvhdr_base; we allow user to map read-write so they can
+ * write hdrq entries to allow protocol code to directly poll
+ * whether a hdrq entry has been written.
+ */
+ total_size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+ sizeof(u32), PAGE_SIZE);
+ if ((vma->vm_end - vma->vm_start) > total_size) {
+ dev_info(&dd->pcidev->dev,
+ "FAIL on rcvhdrq: reqlen %lx > actual %lx\n",
+ vma->vm_end - vma->vm_start,
+ (unsigned long) total_size);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ ret = remap_pfn_range(vma, vma->vm_start,
+ pd->port_rcvhdrq_phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+bail:
+ return ret;
+}
+
+static int mmap_pioavailregs(struct vm_area_struct *vma,
+ struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ int ret;
+
+ /*
+ * when we map the PIO bufferavail registers, we want to map them as
+ * readonly, no write possible.
+ *
+ * kmalloc'ed memory, physically contiguous, one page only, readonly
+ */
+
+ if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
+ dev_info(&dd->pcidev->dev, "FAIL on pioavailregs_dma: "
+ "reqlen %lx > actual %lx\n",
+ vma->vm_end - vma->vm_start,
+ (unsigned long) PAGE_SIZE);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ if (vma->vm_flags & VM_WRITE) {
+ dev_info(&dd->pcidev->dev,
+ "Can't map pioavailregs as writable (flags=%lx)\n",
+ vma->vm_flags);
+ ret = -EPERM;
+ goto bail;
+ }
+
+ /* don't allow them to later change with mprotect */
+ vma->vm_flags &= ~VM_MAYWRITE;
+
+ ret = remap_pfn_range(vma, vma->vm_start,
+ dd->ipath_pioavailregs_phys >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot);
+bail:
+ return ret;
+}
+
+/**
+ * ipath_mmap - mmap various structures into user space
+ * @fp: the file pointer
+ * @vma: the VM area
+ *
+ * We use this to have a shared buffer between the kernel and the user code
+ * for the rcvhdr queue, egr buffers, and the per-port user regs and pio
+ * buffers in the chip. We have the open and close entries so we can bump
+ * the ref count and keep the driver from being unloaded while still mapped.
+ */
+static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+ struct ipath_portdata *pd;
+ struct ipath_devdata *dd;
+ u64 pgaddr, ureg;
+ int ret;
+
+ pd = port_fp(fp);
+ dd = pd->port_dd;
+ /*
+ * This is the ipath_do_user_init() code, mapping the shared buffers
+ * into the user process. The address referred to by vm_pgoff is the
+ * virtual, not physical, address; we only do one mmap for each
+ * space mapped.
+ */
+ pgaddr = vma->vm_pgoff << PAGE_SHIFT;
+
+ /*
+ * note that ureg does *NOT* have the kregvirt as part of it, to be
+ * sure that for 32 bit programs, we don't end up trying to map a >
+ * 44 address. Has to match ipath_get_base_info() code that sets
+ * __spi_uregbase
+ */
+
+ ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+
+ ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n",
+ (unsigned long long) pgaddr, vma->vm_start,
+ vma->vm_end - vma->vm_start);
+
+ if (pgaddr == ureg)
+ ret = mmap_ureg(vma, dd, ureg);
+ else if (pgaddr == pd->port_piobufs)
+ ret = mmap_piobufs(vma, dd, pd);
+ else if (pgaddr == (u64) pd->port_rcvegr_phys)
+ ret = mmap_rcvegrbufs(vma, pd);
+ else if (pgaddr == (u64) pd->port_rcvhdrq_phys)
+ ret = mmap_rcvhdrq(vma, pd);
+ else if (pgaddr == dd->ipath_pioavailregs_phys)
+ ret = mmap_pioavailregs(vma, pd);
+ else
+ ret = -EINVAL;
+
+ vma->vm_private_data = NULL;
+
+ if (ret < 0)
+ dev_info(&dd->pcidev->dev,
+ "Failure %d on addr %lx, off %lx\n",
+ -ret, vma->vm_start, vma->vm_pgoff);
+
+ return ret;
+}
+
+static unsigned int ipath_poll(struct file *fp,
+ struct poll_table_struct *pt)
+{
+ struct ipath_portdata *pd;
+ u32 head, tail;
+ int bit;
+ struct ipath_devdata *dd;
+
+ pd = port_fp(fp);
+ dd = pd->port_dd;
+
+ bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
+ set_bit(bit, &dd->ipath_rcvctrl);
+
+ /*
+ * 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.
+ */
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
+ tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+
+ if (tail == head) {
+ set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+ poll_wait(fp, &pd->port_wait, pt);
+
+ 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 {
+ /* it's already happened; don't do wait_event overhead */
+ pd->port_rcvnowait++;
+ }
+
+ clear_bit(bit, &dd->ipath_rcvctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ return 0;
+}
+
+static int try_alloc_port(struct ipath_devdata *dd, int port,
+ struct file *fp)
+{
+ int ret;
+
+ if (!dd->ipath_pd[port]) {
+ void *p, *ptmp;
+
+ p = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL);
+
+ /*
+ * Allocate memory for use in ipath_tid_update() just once
+ * at open, not per call. Reduces cost of expected send
+ * setup.
+ */
+ ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) +
+ dd->ipath_rcvtidcnt * sizeof(struct page **),
+ GFP_KERNEL);
+ if (!p || !ptmp) {
+ ipath_dev_err(dd, "Unable to allocate portdata "
+ "memory, failing open\n");
+ ret = -ENOMEM;
+ kfree(p);
+ kfree(ptmp);
+ goto bail;
+ }
+ dd->ipath_pd[port] = p;
+ dd->ipath_pd[port]->port_port = port;
+ dd->ipath_pd[port]->port_dd = dd;
+ dd->ipath_pd[port]->port_tid_pg_list = ptmp;
+ init_waitqueue_head(&dd->ipath_pd[port]->port_wait);
+ }
+ if (!dd->ipath_pd[port]->port_cnt) {
+ dd->ipath_pd[port]->port_cnt = 1;
+ fp->private_data = (void *) dd->ipath_pd[port];
+ ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n",
+ current->comm, current->pid, dd->ipath_unit,
+ port);
+ dd->ipath_pd[port]->port_pid = current->pid;
+ strncpy(dd->ipath_pd[port]->port_comm, current->comm,
+ sizeof(dd->ipath_pd[port]->port_comm));
+ ipath_stats.sps_ports++;
+ ret = 0;
+ goto bail;
+ }
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+static inline int usable(struct ipath_devdata *dd)
+{
+ return dd &&
+ (dd->ipath_flags & IPATH_PRESENT) &&
+ dd->ipath_kregbase &&
+ dd->ipath_lid &&
+ !(dd->ipath_flags & (IPATH_LINKDOWN | IPATH_DISABLED
+ | IPATH_LINKUNK));
+}
+
+static int find_free_port(int unit, struct file *fp)
+{
+ struct ipath_devdata *dd = ipath_lookup(unit);
+ int ret, i;
+
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (!usable(dd)) {
+ ret = -ENETDOWN;
+ goto bail;
+ }
+
+ for (i = 0; i < dd->ipath_cfgports; i++) {
+ ret = try_alloc_port(dd, i, fp);
+ if (ret != -EBUSY)
+ goto bail;
+ }
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+static int find_best_unit(struct file *fp)
+{
+ int ret = 0, i, prefunit = -1, devmax;
+ int maxofallports, npresent, nup;
+ int ndev;
+
+ (void) ipath_count_units(&npresent, &nup, &maxofallports);
+
+ /*
+ * This code is present to allow a knowledgeable person to
+ * specify the layout of processes to processors before opening
+ * this driver, and then we'll assign the process to the "closest"
+ * HT-400 to that processor (we assume reasonable connectivity,
+ * for now). This code assumes that if affinity has been set
+ * before this point, that at most one cpu is set; for now this
+ * is reasonable. I check for both cpus_empty() and cpus_full(),
+ * in case some kernel variant sets none of the bits when no
+ * affinity is set. 2.6.11 and 12 kernels have all present
+ * cpus set. Some day we'll have to fix it up further to handle
+ * a cpu subset. This algorithm fails for two HT-400's connected
+ * in tunnel fashion. Eventually this needs real topology
+ * information. There may be some issues with dual core numbering
+ * as well. This needs more work prior to release.
+ */
+ if (!cpus_empty(current->cpus_allowed) &&
+ !cpus_full(current->cpus_allowed)) {
+ int ncpus = num_online_cpus(), curcpu = -1;
+ for (i = 0; i < ncpus; i++)
+ if (cpu_isset(i, current->cpus_allowed)) {
+ ipath_cdbg(PROC, "%s[%u] affinity set for "
+ "cpu %d\n", current->comm,
+ current->pid, i);
+ curcpu = i;
+ }
+ if (curcpu != -1) {
+ if (npresent) {
+ prefunit = curcpu / (ncpus / npresent);
+ ipath_dbg("%s[%u] %d chips, %d cpus, "
+ "%d cpus/chip, select unit %d\n",
+ current->comm, current->pid,
+ npresent, ncpus, ncpus / npresent,
+ prefunit);
+ }
+ }
+ }
+
+ /*
+ * user ports start at 1, kernel port is 0
+ * For now, we do round-robin access across all chips
+ */
+
+ if (prefunit != -1)
+ devmax = prefunit + 1;
+ else
+ devmax = ipath_count_units(NULL, NULL, NULL);
+recheck:
+ for (i = 1; i < maxofallports; i++) {
+ for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax;
+ ndev++) {
+ struct ipath_devdata *dd = ipath_lookup(ndev);
+
+ if (!usable(dd))
+ continue; /* can't use this unit */
+ if (i >= dd->ipath_cfgports)
+ /*
+ * Maxed out on users of this unit. Try
+ * next.
+ */
+ continue;
+ ret = try_alloc_port(dd, i, fp);
+ if (!ret)
+ goto done;
+ }
+ }
+
+ if (npresent) {
+ if (nup == 0) {
+ ret = -ENETDOWN;
+ ipath_dbg("No ports available (none initialized "
+ "and ready)\n");
+ } else {
+ if (prefunit > 0) {
+ /* if started above 0, retry from 0 */
+ ipath_cdbg(PROC,
+ "%s[%u] no ports on prefunit "
+ "%d, clear and re-check\n",
+ current->comm, current->pid,
+ prefunit);
+ devmax = ipath_count_units(NULL, NULL,
+ NULL);
+ prefunit = -1;
+ goto recheck;
+ }
+ ret = -EBUSY;
+ ipath_dbg("No ports available\n");
+ }
+ } else {
+ ret = -ENXIO;
+ ipath_dbg("No boards found\n");
+ }
+
+done:
+ return ret;
+}
+
+static int ipath_open(struct inode *in, struct file *fp)
+{
+ int ret, minor;
+
+ mutex_lock(&ipath_mutex);
+
+ minor = iminor(in);
+ ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
+ (long)in->i_rdev, minor);
+
+ if (minor)
+ ret = find_free_port(minor - 1, fp);
+ else
+ ret = find_best_unit(fp);
+
+ mutex_unlock(&ipath_mutex);
+ return ret;
+}
+
+/**
+ * unlock_exptid - unlock any expected TID entries port still had in use
+ * @pd: port
+ *
+ * We don't actually update the chip here, because we do a bulk update
+ * below, using ipath_f_clear_tids.
+ */
+static void unlock_expected_tids(struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ int port_tidbase = pd->port_port * dd->ipath_rcvtidcnt;
+ int i, cnt = 0, maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+
+ ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n",
+ pd->port_port);
+ for (i = port_tidbase; i < maxtid; i++) {
+ if (!dd->ipath_pageshadow[i])
+ continue;
+
+ ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
+ 1);
+ dd->ipath_pageshadow[i] = NULL;
+ cnt++;
+ ipath_stats.sps_pageunlocks++;
+ }
+ if (cnt)
+ ipath_cdbg(VERBOSE, "Port %u locked %u expTID entries\n",
+ pd->port_port, cnt);
+
+ if (ipath_stats.sps_pagelocks || ipath_stats.sps_pageunlocks)
+ ipath_cdbg(VERBOSE, "%llu pages locked, %llu unlocked\n",
+ (unsigned long long) ipath_stats.sps_pagelocks,
+ (unsigned long long)
+ ipath_stats.sps_pageunlocks);
+}
+
+static int ipath_close(struct inode *in, struct file *fp)
+{
+ int ret = 0;
+ struct ipath_portdata *pd;
+ struct ipath_devdata *dd;
+ unsigned port;
+
+ ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n",
+ (long)in->i_rdev, fp->private_data);
+
+ mutex_lock(&ipath_mutex);
+
+ pd = port_fp(fp);
+ port = pd->port_port;
+ fp->private_data = NULL;
+ dd = pd->port_dd;
+
+ if (pd->port_hdrqfull) {
+ ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
+ "during run\n", pd->port_comm, pd->port_pid,
+ pd->port_hdrqfull);
+ pd->port_hdrqfull = 0;
+ }
+
+ if (pd->port_rcvwait_to || pd->port_piowait_to
+ || pd->port_rcvnowait || pd->port_pionowait) {
+ ipath_cdbg(VERBOSE, "port%u, %u rcv, %u pio wait timeo; "
+ "%u rcv %u, pio already\n",
+ pd->port_port, pd->port_rcvwait_to,
+ pd->port_piowait_to, pd->port_rcvnowait,
+ pd->port_pionowait);
+ pd->port_rcvwait_to = pd->port_piowait_to =
+ pd->port_rcvnowait = pd->port_pionowait = 0;
+ }
+ if (pd->port_flag) {
+ ipath_dbg("port %u port_flag still set to 0x%lx\n",
+ pd->port_port, pd->port_flag);
+ pd->port_flag = 0;
+ }
+
+ if (dd->ipath_kregbase) {
+ if (pd->port_rcvhdrtail_uaddr) {
+ pd->port_rcvhdrtail_uaddr = 0;
+ pd->port_rcvhdrtail_kvaddr = NULL;
+ ipath_release_user_pages_on_close(
+ &pd->port_rcvhdrtail_pagep, 1);
+ pd->port_rcvhdrtail_pagep = NULL;
+ ipath_stats.sps_pageunlocks++;
+ }
+ ipath_write_kreg_port(
+ dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+ port, 0ULL);
+ ipath_write_kreg_port(
+ dd, dd->ipath_kregs->kr_rcvhdraddr,
+ pd->port_port, 0);
+
+ /* clean up the pkeys for this port user */
+ ipath_clean_part_key(pd, dd);
+
+ if (port < dd->ipath_cfgports) {
+ int i = dd->ipath_pbufsport * (port - 1);
+ ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
+
+ /* atomically clear receive enable port. */
+ clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
+ &dd->ipath_rcvctrl);
+ ipath_write_kreg(
+ dd,
+ dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ if (dd->ipath_pageshadow)
+ unlock_expected_tids(pd);
+ ipath_stats.sps_ports--;
+ ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
+ pd->port_comm, pd->port_pid,
+ dd->ipath_unit, port);
+ }
+ }
+
+ pd->port_cnt = 0;
+ pd->port_pid = 0;
+
+ dd->ipath_f_clear_tids(dd, pd->port_port);
+
+ ipath_free_pddata(dd, pd->port_port, 0);
+
+ mutex_unlock(&ipath_mutex);
+
+ return ret;
+}
+
+static int ipath_port_info(struct ipath_portdata *pd,
+ struct ipath_port_info __user *uinfo)
+{
+ struct ipath_port_info info;
+ int nup;
+ int ret;
+
+ (void) ipath_count_units(NULL, &nup, NULL);
+ info.num_active = nup;
+ info.unit = pd->port_dd->ipath_unit;
+ info.port = pd->port_port;
+
+ if (copy_to_user(uinfo, &info, sizeof(info))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static ssize_t ipath_write(struct file *fp, const char __user *data,
+ size_t count, loff_t *off)
+{
+ const struct ipath_cmd __user *ucmd;
+ struct ipath_portdata *pd;
+ const void __user *src;
+ size_t consumed, copy;
+ struct ipath_cmd cmd;
+ ssize_t ret = 0;
+ void *dest;
+
+ if (count < sizeof(cmd.type)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ucmd = (const struct ipath_cmd __user *) data;
+
+ if (copy_from_user(&cmd.type, &ucmd->type, sizeof(cmd.type))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ consumed = sizeof(cmd.type);
+
+ switch (cmd.type) {
+ case IPATH_CMD_USER_INIT:
+ copy = sizeof(cmd.cmd.user_info);
+ dest = &cmd.cmd.user_info;
+ src = &ucmd->cmd.user_info;
+ break;
+ case IPATH_CMD_RECV_CTRL:
+ copy = sizeof(cmd.cmd.recv_ctrl);
+ dest = &cmd.cmd.recv_ctrl;
+ src = &ucmd->cmd.recv_ctrl;
+ break;
+ case IPATH_CMD_PORT_INFO:
+ copy = sizeof(cmd.cmd.port_info);
+ dest = &cmd.cmd.port_info;
+ src = &ucmd->cmd.port_info;
+ break;
+ case IPATH_CMD_TID_UPDATE:
+ case IPATH_CMD_TID_FREE:
+ copy = sizeof(cmd.cmd.tid_info);
+ dest = &cmd.cmd.tid_info;
+ src = &ucmd->cmd.tid_info;
+ break;
+ case IPATH_CMD_SET_PART_KEY:
+ copy = sizeof(cmd.cmd.part_key);
+ dest = &cmd.cmd.part_key;
+ src = &ucmd->cmd.part_key;
+ break;
+ default:
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if ((count - consumed) < copy) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (copy_from_user(dest, src, copy)) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ consumed += copy;
+ pd = port_fp(fp);
+
+ switch (cmd.type) {
+ case IPATH_CMD_USER_INIT:
+ ret = ipath_do_user_init(pd, &cmd.cmd.user_info);
+ if (ret < 0)
+ goto bail;
+ ret = ipath_get_base_info(
+ pd, (void __user *) (unsigned long)
+ cmd.cmd.user_info.spu_base_info,
+ cmd.cmd.user_info.spu_base_info_size);
+ break;
+ case IPATH_CMD_RECV_CTRL:
+ ret = ipath_manage_rcvq(pd, cmd.cmd.recv_ctrl);
+ break;
+ case IPATH_CMD_PORT_INFO:
+ ret = ipath_port_info(pd,
+ (struct ipath_port_info __user *)
+ (unsigned long) cmd.cmd.port_info);
+ break;
+ case IPATH_CMD_TID_UPDATE:
+ ret = ipath_tid_update(pd, &cmd.cmd.tid_info);
+ break;
+ case IPATH_CMD_TID_FREE:
+ ret = ipath_tid_free(pd, &cmd.cmd.tid_info);
+ break;
+ case IPATH_CMD_SET_PART_KEY:
+ ret = ipath_set_part_key(pd, cmd.cmd.part_key);
+ break;
+ }
+
+ if (ret >= 0)
+ ret = consumed;
+
+bail:
+ return ret;
+}
+
+static struct class *ipath_class;
+
+static int init_cdev(int minor, char *name, struct file_operations *fops,
+ struct cdev **cdevp, struct class_device **class_devp)
+{
+ const dev_t dev = MKDEV(IPATH_MAJOR, minor);
+ struct cdev *cdev = NULL;
+ struct class_device *class_dev = NULL;
+ int ret;
+
+ cdev = cdev_alloc();
+ if (!cdev) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate cdev for minor %d, %s\n",
+ minor, name);
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ cdev->owner = THIS_MODULE;
+ cdev->ops = fops;
+ kobject_set_name(&cdev->kobj, name);
+
+ ret = cdev_add(cdev, dev, 1);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not add cdev for minor %d, %s (err %d)\n",
+ minor, name, -ret);
+ goto err_cdev;
+ }
+
+ class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
+
+ if (IS_ERR(class_dev)) {
+ ret = PTR_ERR(class_dev);
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+ "class_dev for minor %d, %s (err %d)\n",
+ minor, name, -ret);
+ goto err_cdev;
+ }
+
+ goto done;
+
+err_cdev:
+ cdev_del(cdev);
+ cdev = NULL;
+
+done:
+ if (ret >= 0) {
+ *cdevp = cdev;
+ *class_devp = class_dev;
+ } else {
+ *cdevp = NULL;
+ *class_devp = NULL;
+ }
+
+ return ret;
+}
+
+int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+ struct cdev **cdevp, struct class_device **class_devp)
+{
+ return init_cdev(minor, name, fops, cdevp, class_devp);
+}
+
+static void cleanup_cdev(struct cdev **cdevp,
+ struct class_device **class_devp)
+{
+ struct class_device *class_dev = *class_devp;
+
+ if (class_dev) {
+ class_device_unregister(class_dev);
+ *class_devp = NULL;
+ }
+
+ if (*cdevp) {
+ cdev_del(*cdevp);
+ *cdevp = NULL;
+ }
+}
+
+void ipath_cdev_cleanup(struct cdev **cdevp,
+ struct class_device **class_devp)
+{
+ cleanup_cdev(cdevp, class_devp);
+}
+
+static struct cdev *wildcard_cdev;
+static struct class_device *wildcard_class_dev;
+
+static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
+
+static int user_init(void)
+{
+ int ret;
+
+ ret = register_chrdev_region(dev, IPATH_NMINORS, IPATH_DRV_NAME);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not register "
+ "chrdev region (err %d)\n", -ret);
+ goto done;
+ }
+
+ ipath_class = class_create(THIS_MODULE, IPATH_DRV_NAME);
+
+ if (IS_ERR(ipath_class)) {
+ ret = PTR_ERR(ipath_class);
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+ "device class (err %d)\n", -ret);
+ goto bail;
+ }
+
+ goto done;
+bail:
+ unregister_chrdev_region(dev, IPATH_NMINORS);
+done:
+ return ret;
+}
+
+static void user_cleanup(void)
+{
+ if (ipath_class) {
+ class_destroy(ipath_class);
+ ipath_class = NULL;
+ }
+
+ unregister_chrdev_region(dev, IPATH_NMINORS);
+}
+
+static atomic_t user_count = ATOMIC_INIT(0);
+static atomic_t user_setup = ATOMIC_INIT(0);
+
+int ipath_user_add(struct ipath_devdata *dd)
+{
+ char name[10];
+ int ret;
+
+ if (atomic_inc_return(&user_count) == 1) {
+ ret = user_init();
+ if (ret < 0) {
+ ipath_dev_err(dd, "Unable to set up user support: "
+ "error %d\n", -ret);
+ goto bail;
+ }
+ ret = ipath_diag_init();
+ if (ret < 0) {
+ ipath_dev_err(dd, "Unable to set up diag support: "
+ "error %d\n", -ret);
+ goto bail_sma;
+ }
+
+ ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
+ &wildcard_class_dev);
+ if (ret < 0) {
+ ipath_dev_err(dd, "Could not create wildcard "
+ "minor: error %d\n", -ret);
+ goto bail_diag;
+ }
+
+ atomic_set(&user_setup, 1);
+ }
+
+ snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
+
+ ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
+ &dd->cdev, &dd->class_dev);
+ if (ret < 0)
+ ipath_dev_err(dd, "Could not create user minor %d, %s\n",
+ dd->ipath_unit + 1, name);
+
+ goto bail;
+
+bail_diag:
+ ipath_diag_cleanup();
+bail_sma:
+ user_cleanup();
+bail:
+ return ret;
+}
+
+void ipath_user_del(struct ipath_devdata *dd)
+{
+ cleanup_cdev(&dd->cdev, &dd->class_dev);
+
+ if (atomic_dec_return(&user_count) == 0) {
+ if (atomic_read(&user_setup) == 0)
+ goto bail;
+
+ cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
+ ipath_diag_cleanup();
+ user_cleanup();
+
+ atomic_set(&user_setup, 0);
+ }
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
new file mode 100644
index 000000000000..e274120567e1
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+
+#define IPATHFS_MAGIC 0x726a77
+
+static struct super_block *ipath_super;
+
+static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
+ int mode, struct file_operations *fops,
+ void *data)
+{
+ int error;
+ struct inode *inode = new_inode(dir->i_sb);
+
+ if (!inode) {
+ error = -EPERM;
+ goto bail;
+ }
+
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->u.generic_ip = data;
+ if ((mode & S_IFMT) == S_IFDIR) {
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_nlink++;
+ dir->i_nlink++;
+ }
+
+ inode->i_fop = fops;
+
+ d_instantiate(dentry, inode);
+ error = 0;
+
+bail:
+ return error;
+}
+
+static int create_file(const char *name, mode_t mode,
+ struct dentry *parent, struct dentry **dentry,
+ struct file_operations *fops, void *data)
+{
+ int error;
+
+ *dentry = NULL;
+ mutex_lock(&parent->d_inode->i_mutex);
+ *dentry = lookup_one_len(name, parent, strlen(name));
+ if (!IS_ERR(dentry))
+ error = ipathfs_mknod(parent->d_inode, *dentry,
+ mode, fops, data);
+ else
+ error = PTR_ERR(dentry);
+ mutex_unlock(&parent->d_inode->i_mutex);
+
+ return error;
+}
+
+static ssize_t atomic_stats_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return simple_read_from_buffer(buf, count, ppos, &ipath_stats,
+ sizeof ipath_stats);
+}
+
+static struct file_operations atomic_stats_ops = {
+ .read = atomic_stats_read,
+};
+
+#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64)
+
+static ssize_t atomic_counters_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u64 counters[NUM_COUNTERS];
+ u16 i;
+ struct ipath_devdata *dd;
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+
+ for (i = 0; i < NUM_COUNTERS; i++)
+ counters[i] = ipath_snap_cntr(dd, i);
+
+ return simple_read_from_buffer(buf, count, ppos, counters,
+ sizeof counters);
+}
+
+static struct file_operations atomic_counters_ops = {
+ .read = atomic_counters_read,
+};
+
+static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u32 nodeinfo[10];
+ struct ipath_devdata *dd;
+ u64 guid;
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+
+ guid = be64_to_cpu(dd->ipath_guid);
+
+ nodeinfo[0] = /* BaseVersion is SMA */
+ /* ClassVersion is SMA */
+ (1 << 8) /* NodeType */
+ | (1 << 0); /* NumPorts */
+ nodeinfo[1] = (u32) (guid >> 32);
+ nodeinfo[2] = (u32) (guid & 0xffffffff);
+ /* PortGUID == SystemImageGUID for us */
+ nodeinfo[3] = nodeinfo[1];
+ /* PortGUID == SystemImageGUID for us */
+ nodeinfo[4] = nodeinfo[2];
+ /* PortGUID == NodeGUID for us */
+ nodeinfo[5] = nodeinfo[3];
+ /* PortGUID == NodeGUID for us */
+ nodeinfo[6] = nodeinfo[4];
+ nodeinfo[7] = (4 << 16) /* we support 4 pkeys */
+ | (dd->ipath_deviceid << 0);
+ /* our chip version as 16 bits major, 16 bits minor */
+ nodeinfo[8] = dd->ipath_minrev | (dd->ipath_majrev << 16);
+ nodeinfo[9] = (dd->ipath_unit << 24) | (dd->ipath_vendorid << 0);
+
+ return simple_read_from_buffer(buf, count, ppos, nodeinfo,
+ sizeof nodeinfo);
+}
+
+static struct file_operations atomic_node_info_ops = {
+ .read = atomic_node_info_read,
+};
+
+static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u32 portinfo[13];
+ u32 tmp, tmp2;
+ struct ipath_devdata *dd;
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+
+ /* so we only initialize non-zero fields. */
+ memset(portinfo, 0, sizeof portinfo);
+
+ /*
+ * Notimpl yet M_Key (64)
+ * Notimpl yet GID (64)
+ */
+
+ portinfo[4] = (dd->ipath_lid << 16);
+
+ /*
+ * Notimpl yet SMLID (should we store this in the driver, in case
+ * SMA dies?) CapabilityMask is 0, we don't support any of these
+ * DiagCode is 0; we don't store any diag info for now Notimpl yet
+ * M_KeyLeasePeriod (we don't support M_Key)
+ */
+
+ /* LocalPortNum is whichever port number they ask for */
+ portinfo[7] = (dd->ipath_unit << 24)
+ /* LinkWidthEnabled */
+ | (2 << 16)
+ /* LinkWidthSupported (really 2, but not IB valid) */
+ | (3 << 8)
+ /* LinkWidthActive */
+ | (2 << 0);
+ tmp = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+ tmp2 = 5;
+ if (tmp == IPATH_IBSTATE_INIT)
+ tmp = 2;
+ else if (tmp == IPATH_IBSTATE_ARM)
+ tmp = 3;
+ else if (tmp == IPATH_IBSTATE_ACTIVE)
+ tmp = 4;
+ else {
+ tmp = 0; /* down */
+ tmp2 = tmp & 0xf;
+ }
+
+ portinfo[8] = (1 << 28) /* LinkSpeedSupported */
+ | (tmp << 24) /* PortState */
+ | (tmp2 << 20) /* PortPhysicalState */
+ | (2 << 16)
+
+ /* LinkDownDefaultState */
+ /* M_KeyProtectBits == 0 */
+ /* NotImpl yet LMC == 0 (we can support all values) */
+ | (1 << 4) /* LinkSpeedActive */
+ | (1 << 0); /* LinkSpeedEnabled */
+ switch (dd->ipath_ibmtu) {
+ case 4096:
+ tmp = 5;
+ break;
+ case 2048:
+ tmp = 4;
+ break;
+ case 1024:
+ tmp = 3;
+ break;
+ case 512:
+ tmp = 2;
+ break;
+ case 256:
+ tmp = 1;
+ break;
+ default: /* oops, something is wrong */
+ ipath_dbg("Problem, ipath_ibmtu 0x%x not a valid IB MTU, "
+ "treat as 2048\n", dd->ipath_ibmtu);
+ tmp = 4;
+ break;
+ }
+ portinfo[9] = (tmp << 28)
+ /* NeighborMTU */
+ /* Notimpl MasterSMSL */
+ | (1 << 20)
+
+ /* VLCap */
+ /* Notimpl InitType (actually, an SMA decision) */
+ /* VLHighLimit is 0 (only one VL) */
+ ; /* VLArbitrationHighCap is 0 (only one VL) */
+ portinfo[10] = /* VLArbitrationLowCap is 0 (only one VL) */
+ /* InitTypeReply is SMA decision */
+ (5 << 16) /* MTUCap 4096 */
+ | (7 << 13) /* VLStallCount */
+ | (0x1f << 8) /* HOQLife */
+ | (1 << 4)
+
+ /* OperationalVLs 0 */
+ /* PartitionEnforcementInbound */
+ /* PartitionEnforcementOutbound not enforced */
+ /* FilterRawinbound not enforced */
+ ; /* FilterRawOutbound not enforced */
+ /* M_KeyViolations are not counted by hardware, SMA can count */
+ tmp = ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);
+ /* P_KeyViolations are counted by hardware. */
+ portinfo[11] = ((tmp & 0xffff) << 0);
+ portinfo[12] =
+ /* Q_KeyViolations are not counted by hardware */
+ (1 << 8)
+
+ /* GUIDCap */
+ /* SubnetTimeOut handled by SMA */
+ /* RespTimeValue handled by SMA */
+ ;
+ /* LocalPhyErrors are programmed to max */
+ portinfo[12] |= (0xf << 20)
+ | (0xf << 16) /* OverRunErrors are programmed to max */
+ ;
+
+ return simple_read_from_buffer(buf, count, ppos, portinfo,
+ sizeof portinfo);
+}
+
+static struct file_operations atomic_port_info_ops = {
+ .read = atomic_port_info_read,
+};
+
+static ssize_t flash_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ipath_devdata *dd;
+ ssize_t ret;
+ loff_t pos;
+ char *tmp;
+
+ pos = *ppos;
+
+ if ( pos < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (pos >= sizeof(struct ipath_flash)) {
+ ret = 0;
+ goto bail;
+ }
+
+ if (count > sizeof(struct ipath_flash) - pos)
+ count = sizeof(struct ipath_flash) - pos;
+
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+ if (ipath_eeprom_read(dd, pos, tmp, count)) {
+ ipath_dev_err(dd, "failed to read from flash\n");
+ ret = -ENXIO;
+ goto bail_tmp;
+ }
+
+ if (copy_to_user(buf, tmp, count)) {
+ ret = -EFAULT;
+ goto bail_tmp;
+ }
+
+ *ppos = pos + count;
+ ret = count;
+
+bail_tmp:
+ kfree(tmp);
+
+bail:
+ return ret;
+}
+
+static ssize_t flash_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ipath_devdata *dd;
+ ssize_t ret;
+ loff_t pos;
+ char *tmp;
+
+ pos = *ppos;
+
+ if ( pos < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (pos >= sizeof(struct ipath_flash)) {
+ ret = 0;
+ goto bail;
+ }
+
+ if (count > sizeof(struct ipath_flash) - pos)
+ count = sizeof(struct ipath_flash) - pos;
+
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ if (copy_from_user(tmp, buf, count)) {
+ ret = -EFAULT;
+ goto bail_tmp;
+ }
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+ if (ipath_eeprom_write(dd, pos, tmp, count)) {
+ ret = -ENXIO;
+ ipath_dev_err(dd, "failed to write to flash\n");
+ goto bail_tmp;
+ }
+
+ *ppos = pos + count;
+ ret = count;
+
+bail_tmp:
+ kfree(tmp);
+
+bail:
+ return ret;
+}
+
+static struct file_operations flash_ops = {
+ .read = flash_read,
+ .write = flash_write,
+};
+
+static int create_device_files(struct super_block *sb,
+ struct ipath_devdata *dd)
+{
+ struct dentry *dir, *tmp;
+ char unit[10];
+ int ret;
+
+ snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+ ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
+ (struct file_operations *) &simple_dir_operations,
+ dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("atomic_counters", S_IFREG|S_IRUGO, dir, &tmp,
+ &atomic_counters_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/atomic_counters) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("node_info", S_IFREG|S_IRUGO, dir, &tmp,
+ &atomic_node_info_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/node_info) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("port_info", S_IFREG|S_IRUGO, dir, &tmp,
+ &atomic_port_info_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/port_info) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp,
+ &flash_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/flash) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+static void remove_file(struct dentry *parent, char *name)
+{
+ struct dentry *tmp;
+
+ tmp = lookup_one_len(name, parent, strlen(name));
+
+ spin_lock(&dcache_lock);
+ spin_lock(&tmp->d_lock);
+ if (!(d_unhashed(tmp) && tmp->d_inode)) {
+ dget_locked(tmp);
+ __d_drop(tmp);
+ spin_unlock(&tmp->d_lock);
+ spin_unlock(&dcache_lock);
+ simple_unlink(parent->d_inode, tmp);
+ } else {
+ spin_unlock(&tmp->d_lock);
+ spin_unlock(&dcache_lock);
+ }
+}
+
+static int remove_device_files(struct super_block *sb,
+ struct ipath_devdata *dd)
+{
+ struct dentry *dir, *root;
+ char unit[10];
+ int ret;
+
+ root = dget(sb->s_root);
+ mutex_lock(&root->d_inode->i_mutex);
+ snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+ dir = lookup_one_len(unit, root, strlen(unit));
+
+ if (IS_ERR(dir)) {
+ ret = PTR_ERR(dir);
+ printk(KERN_ERR "Lookup of %s failed\n", unit);
+ goto bail;
+ }
+
+ remove_file(dir, "flash");
+ remove_file(dir, "port_info");
+ remove_file(dir, "node_info");
+ remove_file(dir, "atomic_counters");
+ d_delete(dir);
+ ret = simple_rmdir(root->d_inode, dir);
+
+bail:
+ mutex_unlock(&root->d_inode->i_mutex);
+ dput(root);
+ return ret;
+}
+
+static int ipathfs_fill_super(struct super_block *sb, void *data,
+ int silent)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+ int ret;
+
+ static struct tree_descr files[] = {
+ [1] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
+ {""},
+ };
+
+ ret = simple_fill_super(sb, IPATHFS_MAGIC, files);
+ if (ret) {
+ printk(KERN_ERR "simple_fill_super failed: %d\n", ret);
+ goto bail;
+ }
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ ret = create_device_files(sb, dd);
+ if (ret) {
+ deactivate_super(sb);
+ goto bail;
+ }
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+bail:
+ return ret;
+}
+
+static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
+{
+ ipath_super = get_sb_single(fs_type, flags, data,
+ ipathfs_fill_super);
+ return ipath_super;
+}
+
+static void ipathfs_kill_super(struct super_block *s)
+{
+ kill_litter_super(s);
+ ipath_super = NULL;
+}
+
+int ipathfs_add_device(struct ipath_devdata *dd)
+{
+ int ret;
+
+ if (ipath_super == NULL) {
+ ret = 0;
+ goto bail;
+ }
+
+ ret = create_device_files(ipath_super, dd);
+
+bail:
+ return ret;
+}
+
+int ipathfs_remove_device(struct ipath_devdata *dd)
+{
+ int ret;
+
+ if (ipath_super == NULL) {
+ ret = 0;
+ goto bail;
+ }
+
+ ret = remove_device_files(ipath_super, dd);
+
+bail:
+ return ret;
+}
+
+static struct file_system_type ipathfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "ipathfs",
+ .get_sb = ipathfs_get_sb,
+ .kill_sb = ipathfs_kill_super,
+};
+
+int __init ipath_init_ipathfs(void)
+{
+ return register_filesystem(&ipathfs_fs_type);
+}
+
+void __exit ipath_exit_ipathfs(void)
+{
+ unregister_filesystem(&ipathfs_fs_type);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c
new file mode 100644
index 000000000000..4652435998f3
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ht400.c
@@ -0,0 +1,1586 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contains all of the code that is specific to the InfiniPath
+ * HT-400 chip.
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "ipath_kernel.h"
+#include "ipath_registers.h"
+
+/*
+ * This lists the InfiniPath HT400 registers, in the actual chip layout.
+ * This structure should never be directly accessed.
+ *
+ * The names are in InterCap form because they're taken straight from
+ * the chip specification. Since they're only used in this file, they
+ * don't pollute the rest of the source.
+*/
+
+struct _infinipath_do_not_use_kernel_regs {
+ unsigned long long Revision;
+ unsigned long long Control;
+ unsigned long long PageAlign;
+ unsigned long long PortCnt;
+ unsigned long long DebugPortSelect;
+ unsigned long long DebugPort;
+ unsigned long long SendRegBase;
+ unsigned long long UserRegBase;
+ unsigned long long CounterRegBase;
+ unsigned long long Scratch;
+ unsigned long long ReservedMisc1;
+ unsigned long long InterruptConfig;
+ unsigned long long IntBlocked;
+ unsigned long long IntMask;
+ unsigned long long IntStatus;
+ unsigned long long IntClear;
+ unsigned long long ErrorMask;
+ unsigned long long ErrorStatus;
+ unsigned long long ErrorClear;
+ unsigned long long HwErrMask;
+ unsigned long long HwErrStatus;
+ unsigned long long HwErrClear;
+ unsigned long long HwDiagCtrl;
+ unsigned long long MDIO;
+ unsigned long long IBCStatus;
+ unsigned long long IBCCtrl;
+ unsigned long long ExtStatus;
+ unsigned long long ExtCtrl;
+ unsigned long long GPIOOut;
+ unsigned long long GPIOMask;
+ unsigned long long GPIOStatus;
+ unsigned long long GPIOClear;
+ unsigned long long RcvCtrl;
+ unsigned long long RcvBTHQP;
+ unsigned long long RcvHdrSize;
+ unsigned long long RcvHdrCnt;
+ unsigned long long RcvHdrEntSize;
+ unsigned long long RcvTIDBase;
+ unsigned long long RcvTIDCnt;
+ unsigned long long RcvEgrBase;
+ unsigned long long RcvEgrCnt;
+ unsigned long long RcvBufBase;
+ unsigned long long RcvBufSize;
+ unsigned long long RxIntMemBase;
+ unsigned long long RxIntMemSize;
+ unsigned long long RcvPartitionKey;
+ unsigned long long ReservedRcv[10];
+ unsigned long long SendCtrl;
+ unsigned long long SendPIOBufBase;
+ unsigned long long SendPIOSize;
+ unsigned long long SendPIOBufCnt;
+ unsigned long long SendPIOAvailAddr;
+ unsigned long long TxIntMemBase;
+ unsigned long long TxIntMemSize;
+ unsigned long long ReservedSend[9];
+ unsigned long long SendBufferError;
+ unsigned long long SendBufferErrorCONT1;
+ unsigned long long SendBufferErrorCONT2;
+ unsigned long long SendBufferErrorCONT3;
+ unsigned long long ReservedSBE[4];
+ unsigned long long RcvHdrAddr0;
+ unsigned long long RcvHdrAddr1;
+ unsigned long long RcvHdrAddr2;
+ unsigned long long RcvHdrAddr3;
+ unsigned long long RcvHdrAddr4;
+ unsigned long long RcvHdrAddr5;
+ unsigned long long RcvHdrAddr6;
+ unsigned long long RcvHdrAddr7;
+ unsigned long long RcvHdrAddr8;
+ unsigned long long ReservedRHA[7];
+ unsigned long long RcvHdrTailAddr0;
+ unsigned long long RcvHdrTailAddr1;
+ unsigned long long RcvHdrTailAddr2;
+ unsigned long long RcvHdrTailAddr3;
+ unsigned long long RcvHdrTailAddr4;
+ unsigned long long RcvHdrTailAddr5;
+ unsigned long long RcvHdrTailAddr6;
+ unsigned long long RcvHdrTailAddr7;
+ unsigned long long RcvHdrTailAddr8;
+ unsigned long long ReservedRHTA[7];
+ unsigned long long Sync; /* Software only */
+ unsigned long long Dump; /* Software only */
+ unsigned long long SimVer; /* Software only */
+ unsigned long long ReservedSW[5];
+ unsigned long long SerdesConfig0;
+ unsigned long long SerdesConfig1;
+ unsigned long long SerdesStatus;
+ unsigned long long XGXSConfig;
+ unsigned long long ReservedSW2[4];
+};
+
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+ _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_CREG_OFFSET(field) (offsetof( \
+ struct infinipath_counters, field) / sizeof(u64))
+
+static const struct ipath_kregs ipath_ht_kregs = {
+ .kr_control = IPATH_KREG_OFFSET(Control),
+ .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
+ .kr_debugport = IPATH_KREG_OFFSET(DebugPort),
+ .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
+ .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
+ .kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
+ .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
+ .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
+ .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
+ .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
+ .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
+ .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
+ .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
+ .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
+ .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
+ .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
+ .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
+ .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
+ .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
+ .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
+ .kr_intclear = IPATH_KREG_OFFSET(IntClear),
+ .kr_interruptconfig = IPATH_KREG_OFFSET(InterruptConfig),
+ .kr_intmask = IPATH_KREG_OFFSET(IntMask),
+ .kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
+ .kr_mdio = IPATH_KREG_OFFSET(MDIO),
+ .kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
+ .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
+ .kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
+ .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
+ .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
+ .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
+ .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
+ .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
+ .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
+ .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
+ .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
+ .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
+ .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
+ .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
+ .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
+ .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
+ .kr_revision = IPATH_KREG_OFFSET(Revision),
+ .kr_scratch = IPATH_KREG_OFFSET(Scratch),
+ .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
+ .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
+ .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),
+ .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),
+ .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),
+ .kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),
+ .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
+ .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
+ .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
+ .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
+ .kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),
+ .kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),
+ .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),
+ .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
+ /*
+ * These should not be used directly via ipath_read_kreg64(),
+ * use them with ipath_read_kreg64_port(),
+ */
+ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
+ .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0)
+};
+
+static const struct ipath_cregs ipath_ht_cregs = {
+ .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
+ .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
+ .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
+ .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
+ .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
+ .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
+ .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
+ .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
+ .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
+ .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
+ .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
+ .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
+ /* calc from Reg_CounterRegBase + offset */
+ .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
+ .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
+ .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
+ .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
+ .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
+ .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
+ .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
+ .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
+ .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
+ .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
+ .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
+ .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
+ .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
+ .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
+ .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
+ .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
+ .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
+ .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
+ .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
+ .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
+ .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+};
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_MASK 0x1FF
+#define INFINIPATH_I_RCVAVAIL_MASK 0x1FF
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+#define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
+#define INFINIPATH_HWE_HTCMEMPARITYERR_MASK 0x3FFFFFULL
+#define INFINIPATH_HWE_HTCLNKABYTE0CRCERR 0x0000000000800000ULL
+#define INFINIPATH_HWE_HTCLNKABYTE1CRCERR 0x0000000001000000ULL
+#define INFINIPATH_HWE_HTCLNKBBYTE0CRCERR 0x0000000002000000ULL
+#define INFINIPATH_HWE_HTCLNKBBYTE1CRCERR 0x0000000004000000ULL
+#define INFINIPATH_HWE_HTCMISCERR4 0x0000000008000000ULL
+#define INFINIPATH_HWE_HTCMISCERR5 0x0000000010000000ULL
+#define INFINIPATH_HWE_HTCMISCERR6 0x0000000020000000ULL
+#define INFINIPATH_HWE_HTCMISCERR7 0x0000000040000000ULL
+#define INFINIPATH_HWE_HTCBUSTREQPARITYERR 0x0000000080000000ULL
+#define INFINIPATH_HWE_HTCBUSTRESPPARITYERR 0x0000000100000000ULL
+#define INFINIPATH_HWE_HTCBUSIREQPARITYERR 0x0000000200000000ULL
+#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL
+#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL
+#define INFINIPATH_HWE_HTBPLL_FBSLIP 0x0200000000000000ULL
+#define INFINIPATH_HWE_HTBPLL_RFSLIP 0x0400000000000000ULL
+#define INFINIPATH_HWE_HTAPLL_FBSLIP 0x0800000000000000ULL
+#define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL
+#define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_FREQSEL 0x2
+#define INFINIPATH_EXTS_SERDESSEL 0x4
+#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
+#define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000
+
+/*
+ * masks and bits that are different in different chips, or present only
+ * in one
+ */
+static const ipath_err_t infinipath_hwe_htcmemparityerr_mask =
+ INFINIPATH_HWE_HTCMEMPARITYERR_MASK;
+static const ipath_err_t infinipath_hwe_htcmemparityerr_shift =
+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT;
+
+static const ipath_err_t infinipath_hwe_htclnkabyte0crcerr =
+ INFINIPATH_HWE_HTCLNKABYTE0CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkabyte1crcerr =
+ INFINIPATH_HWE_HTCLNKABYTE1CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkbbyte0crcerr =
+ INFINIPATH_HWE_HTCLNKBBYTE0CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkbbyte1crcerr =
+ INFINIPATH_HWE_HTCLNKBBYTE1CRCERR;
+
+#define _IPATH_GPIO_SDA_NUM 1
+#define _IPATH_GPIO_SCL_NUM 0
+
+#define IPATH_GPIO_SDA \
+ (1ULL << (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+#define IPATH_GPIO_SCL \
+ (1ULL << (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
+/* keep the code below somewhat more readonable; not used elsewhere */
+#define _IPATH_HTLINK0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \
+ infinipath_hwe_htclnkabyte1crcerr)
+#define _IPATH_HTLINK1_CRCBITS (infinipath_hwe_htclnkbbyte0crcerr | \
+ infinipath_hwe_htclnkbbyte1crcerr)
+#define _IPATH_HTLANE0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \
+ infinipath_hwe_htclnkbbyte0crcerr)
+#define _IPATH_HTLANE1_CRCBITS (infinipath_hwe_htclnkabyte1crcerr | \
+ infinipath_hwe_htclnkbbyte1crcerr)
+
+static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs,
+ char *msg, size_t msgl)
+{
+ char bitsmsg[64];
+ ipath_err_t crcbits = hwerrs &
+ (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS);
+ /* don't check if 8bit HT */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT0)
+ crcbits &= ~infinipath_hwe_htclnkabyte1crcerr;
+ /* don't check if 8bit HT */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT1)
+ crcbits &= ~infinipath_hwe_htclnkbbyte1crcerr;
+ /*
+ * we'll want to ignore link errors on link that is
+ * not in use, if any. For now, complain about both
+ */
+ if (crcbits) {
+ u16 ctrl0, ctrl1;
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[HT%s lane %s CRC (%llx); ignore till reload]",
+ !(crcbits & _IPATH_HTLINK1_CRCBITS) ?
+ "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS)
+ ? "1 (B)" : "0+1 (A+B)"),
+ !(crcbits & _IPATH_HTLANE1_CRCBITS) ? "0"
+ : (!(crcbits & _IPATH_HTLANE0_CRCBITS) ? "1" :
+ "0+1"), (unsigned long long) crcbits);
+ strlcat(msg, bitsmsg, msgl);
+
+ /*
+ * print extra info for debugging. slave/primary
+ * config word 4, 8 (link control 0, 1)
+ */
+
+ if (pci_read_config_word(dd->pcidev,
+ dd->ipath_ht_slave_off + 0x4,
+ &ctrl0))
+ dev_info(&dd->pcidev->dev, "Couldn't read "
+ "linkctrl0 of slave/primary "
+ "config block\n");
+ else if (!(ctrl0 & 1 << 6))
+ /* not if EOC bit set */
+ ipath_dbg("HT linkctrl0 0x%x%s%s\n", ctrl0,
+ ((ctrl0 >> 8) & 7) ? " CRC" : "",
+ ((ctrl0 >> 4) & 1) ? "linkfail" :
+ "");
+ if (pci_read_config_word(dd->pcidev,
+ dd->ipath_ht_slave_off + 0x8,
+ &ctrl1))
+ dev_info(&dd->pcidev->dev, "Couldn't read "
+ "linkctrl1 of slave/primary "
+ "config block\n");
+ else if (!(ctrl1 & 1 << 6))
+ /* not if EOC bit set */
+ ipath_dbg("HT linkctrl1 0x%x%s%s\n", ctrl1,
+ ((ctrl1 >> 8) & 7) ? " CRC" : "",
+ ((ctrl1 >> 4) & 1) ? "linkfail" :
+ "");
+
+ /* disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~crcbits;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ ipath_dbg("HT crc errs: %s\n", msg);
+ } else
+ ipath_dbg("ignoring HT crc errors 0x%llx, "
+ "not in use\n", (unsigned long long)
+ (hwerrs & (_IPATH_HTLINK0_CRCBITS |
+ _IPATH_HTLINK1_CRCBITS)));
+}
+
+/**
+ * ipath_ht_handle_hwerrors - display hardware errors
+ * @dd: the infinipath device
+ * @msg: the output buffer
+ * @msgl: the size of the output buffer
+ *
+ * Use same msg buffer as regular errors to avoid
+ * excessive stack use. Most hardware errors are catastrophic, but for
+ * right now, we'll print them and continue.
+ * We reuse the same message buffer as ipath_handle_errors() to avoid
+ * excessive stack usage.
+ */
+static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ size_t msgl)
+{
+ ipath_err_t hwerrs;
+ u32 bits, ctrl;
+ int isfatal = 0;
+ char bitsmsg[64];
+
+ hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+
+ if (!hwerrs) {
+ ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
+ /*
+ * better than printing cofusing messages
+ * This seems to be related to clearing the crc error, or
+ * the pll error during init.
+ */
+ goto bail;
+ } else if (hwerrs == -1LL) {
+ ipath_dev_err(dd, "Read of hardware error status failed "
+ "(all bits set); ignoring\n");
+ goto bail;
+ }
+ ipath_stats.sps_hwerrs++;
+
+ /* Always clear the error status register, except MEMBISTFAIL,
+ * regardless of whether we continue or stop using the chip.
+ * We want that set so we know it failed, even across driver reload.
+ * We'll still ignore it in the hwerrmask. We do this partly for
+ * diagnostics, but also for support */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
+
+ hwerrs &= dd->ipath_hwerrmask;
+
+ /*
+ * make sure we get this much out, unless told to be quiet,
+ * or it's occurred within the last 5 seconds
+ */
+ if ((hwerrs & ~dd->ipath_lasthwerror) ||
+ (ipath_debug & __IPATH_VERBDBG))
+ dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+ "(cleared)\n", (unsigned long long) hwerrs);
+ dd->ipath_lasthwerror |= hwerrs;
+
+ if (hwerrs & ~infinipath_hwe_bitsextant)
+ ipath_dev_err(dd, "hwerror interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+ (hwerrs & ~infinipath_hwe_bitsextant));
+
+ ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+ if (ctrl & INFINIPATH_C_FREEZEMODE) {
+ if (hwerrs) {
+ /*
+ * if any set that we aren't ignoring; only
+ * make the complaint once, in case it's stuck
+ * or recurring, and we get here multiple
+ * times.
+ */
+ if (dd->ipath_flags & IPATH_INITTED) {
+ ipath_dev_err(dd, "Fatal Error (freeze "
+ "mode), no longer usable\n");
+ isfatal = 1;
+ }
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ /* mark as having had error */
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ /*
+ * mark as not usable, at a minimum until driver
+ * is reloaded, probably until reboot, since no
+ * other reset is possible.
+ */
+ dd->ipath_flags &= ~IPATH_INITTED;
+ } else {
+ ipath_dbg("Clearing freezemode on ignored hardware "
+ "error\n");
+ ctrl &= ~INFINIPATH_C_FREEZEMODE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ ctrl);
+ }
+ }
+
+ *msg = '\0';
+
+ /*
+ * may someday want to decode into which bits are which
+ * functional area for parity errors, etc.
+ */
+ if (hwerrs & (infinipath_hwe_htcmemparityerr_mask
+ << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_HTCMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
+ strlcat(msg, "[IB2IPATH Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
+ strlcat(msg, "[IPATH2IB Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCBUSIREQPARITYERR)
+ strlcat(msg, "[HTC Ireq Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCBUSTREQPARITYERR)
+ strlcat(msg, "[HTC Treq Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCBUSTRESPPARITYERR)
+ strlcat(msg, "[HTC Tresp Parity]", msgl);
+
+ if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS))
+ hwerr_crcbits(dd, hwerrs, msg, msgl);
+
+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR5)
+ strlcat(msg, "[HT core Misc5]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR6)
+ strlcat(msg, "[HT core Misc6]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR7)
+ strlcat(msg, "[HT core Misc7]", msgl);
+ if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
+ strlcat(msg, "[Memory BIST test failed, HT-400 unusable]",
+ msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \
+ INFINIPATH_HWE_COREPLL_RFSLIP | \
+ INFINIPATH_HWE_HTBPLL_FBSLIP | \
+ INFINIPATH_HWE_HTBPLL_RFSLIP | \
+ INFINIPATH_HWE_HTAPLL_FBSLIP | \
+ INFINIPATH_HWE_HTAPLL_RFSLIP)
+
+ if (hwerrs & _IPATH_PLL_FAIL) {
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[PLL failed (%llx), HT-400 unusable]",
+ (unsigned long long) (hwerrs & _IPATH_PLL_FAIL));
+ strlcat(msg, bitsmsg, msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+ /*
+ * If it occurs, it is left masked since the eternal
+ * interface is unused
+ */
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
+ strlcat(msg, "[Rx Dsync]", msgl);
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
+ strlcat(msg, "[SerDes PLL]", msgl);
+
+ ipath_dev_err(dd, "%s hardware error\n", msg);
+ if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)
+ /*
+ * for status file; if no trailing brace is copied,
+ * we'll know it was truncated.
+ */
+ snprintf(dd->ipath_freezemsg,
+ dd->ipath_freezelen, "{%s}", msg);
+
+bail:;
+}
+
+/**
+ * ipath_ht_boardname - fill in the board name
+ * @dd: the infinipath device
+ * @name: the output buffer
+ * @namelen: the size of the output buffer
+ *
+ * fill in the board name, based on the board revision register
+ */
+static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen)
+{
+ char *n = NULL;
+ u8 boardrev = dd->ipath_boardrev;
+ int ret;
+
+ switch (boardrev) {
+ case 4: /* Ponderosa is one of the bringup boards */
+ n = "Ponderosa";
+ break;
+ case 5: /* HT-460 original production board */
+ n = "InfiniPath_HT-460";
+ break;
+ case 6:
+ n = "OEM_Board_3";
+ break;
+ case 7:
+ /* HT-460 small form factor production board */
+ n = "InfiniPath_HT-465";
+ break;
+ case 8:
+ n = "LS/X-1";
+ break;
+ case 9: /* Comstock bringup test board */
+ n = "Comstock";
+ break;
+ case 10:
+ n = "OEM_Board_2";
+ break;
+ case 11:
+ n = "InfiniPath_HT-470";
+ break;
+ case 12:
+ n = "OEM_Board_4";
+ break;
+ default: /* don't know, just print the number */
+ ipath_dev_err(dd, "Don't yet know about board "
+ "with ID %u\n", boardrev);
+ snprintf(name, namelen, "Unknown_InfiniPath_HT-4xx_%u",
+ boardrev);
+ break;
+ }
+ if (n)
+ snprintf(name, namelen, "%s", n);
+
+ if (dd->ipath_majrev != 3 || dd->ipath_minrev != 2) {
+ /*
+ * This version of the driver only supports the HT-400
+ * Rev 3.2
+ */
+ ipath_dev_err(dd,
+ "Unsupported HT-400 revision %u.%u!\n",
+ dd->ipath_majrev, dd->ipath_minrev);
+ ret = 1;
+ goto bail;
+ }
+ /*
+ * pkt/word counters are 32 bit, and therefore wrap fast enough
+ * that we snapshot them from a timer, and maintain 64 bit shadow
+ * copies
+ */
+ dd->ipath_flags |= IPATH_32BITCOUNTERS;
+ 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:
+ return ret;
+}
+
+static void ipath_check_htlink(struct ipath_devdata *dd)
+{
+ u8 linkerr, link_off, i;
+
+ for (i = 0; i < 2; i++) {
+ link_off = dd->ipath_ht_slave_off + i * 4 + 0xd;
+ if (pci_read_config_byte(dd->pcidev, link_off, &linkerr))
+ dev_info(&dd->pcidev->dev, "Couldn't read "
+ "linkerror%d of HT slave/primary block\n",
+ i);
+ else if (linkerr & 0xf0) {
+ ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "
+ "clearing\n", linkerr >> 4, i);
+ /*
+ * writing the linkerr bits that are set should
+ * clear them
+ */
+ if (pci_write_config_byte(dd->pcidev, link_off,
+ linkerr))
+ ipath_dbg("Failed write to clear HT "
+ "linkerror%d\n", i);
+ if (pci_read_config_byte(dd->pcidev, link_off,
+ &linkerr))
+ dev_info(&dd->pcidev->dev,
+ "Couldn't reread linkerror%d of "
+ "HT slave/primary block\n", i);
+ else if (linkerr & 0xf0)
+ dev_info(&dd->pcidev->dev,
+ "HT linkerror%d bits 0x%x "
+ "couldn't be cleared\n",
+ i, linkerr >> 4);
+ }
+ }
+}
+
+static int ipath_setup_ht_reset(struct ipath_devdata *dd)
+{
+ ipath_dbg("No reset possible for HT-400\n");
+ return 0;
+}
+
+#define HT_CAPABILITY_ID 0x08 /* HT capabilities not defined in kernel */
+#define HT_INTR_DISC_CONFIG 0x80 /* HT interrupt and discovery cap */
+#define HT_INTR_REG_INDEX 2 /* intconfig requires indirect accesses */
+
+/*
+ * Bits 13-15 of command==0 is slave/primary block. Clear any HT CRC
+ * errors. We only bother to do this at load time, because it's OK if
+ * it happened before we were loaded (first time after boot/reset),
+ * but any time after that, it's fatal anyway. Also need to not check
+ * for for upper byte errors if we are in 8 bit mode, so figure out
+ * our width. For now, at least, also complain if it's 8 bit.
+ */
+static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ int pos, u8 cap_type)
+{
+ u8 linkwidth = 0, linkerr, link_a_b_off, link_off;
+ u16 linkctrl = 0;
+ int i;
+
+ dd->ipath_ht_slave_off = pos;
+ /* command word, master_host bit */
+ /* master host || slave */
+ if ((cap_type >> 2) & 1)
+ link_a_b_off = 4;
+ else
+ link_a_b_off = 0;
+ ipath_cdbg(VERBOSE, "HT%u (Link %c) connected to processor\n",
+ link_a_b_off ? 1 : 0,
+ link_a_b_off ? 'B' : 'A');
+
+ link_a_b_off += pos;
+
+ /*
+ * check both link control registers; clear both HT CRC sets if
+ * necessary.
+ */
+ for (i = 0; i < 2; i++) {
+ link_off = pos + i * 4 + 0x4;
+ if (pci_read_config_word(pdev, link_off, &linkctrl))
+ ipath_dev_err(dd, "Couldn't read HT link control%d "
+ "register\n", i);
+ else if (linkctrl & (0xf << 8)) {
+ ipath_cdbg(VERBOSE, "Clear linkctrl%d CRC Error "
+ "bits %x\n", i, linkctrl & (0xf << 8));
+ /*
+ * now write them back to clear the error.
+ */
+ pci_write_config_byte(pdev, link_off,
+ linkctrl & (0xf << 8));
+ }
+ }
+
+ /*
+ * As with HT CRC bits, same for protocol errors that might occur
+ * during boot.
+ */
+ for (i = 0; i < 2; i++) {
+ link_off = pos + i * 4 + 0xd;
+ if (pci_read_config_byte(pdev, link_off, &linkerr))
+ dev_info(&pdev->dev, "Couldn't read linkerror%d "
+ "of HT slave/primary block\n", i);
+ else if (linkerr & 0xf0) {
+ ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "
+ "clearing\n", linkerr >> 4, i);
+ /*
+ * writing the linkerr bits that are set will clear
+ * them
+ */
+ if (pci_write_config_byte
+ (pdev, link_off, linkerr))
+ ipath_dbg("Failed write to clear HT "
+ "linkerror%d\n", i);
+ if (pci_read_config_byte(pdev, link_off, &linkerr))
+ dev_info(&pdev->dev, "Couldn't reread "
+ "linkerror%d of HT slave/primary "
+ "block\n", i);
+ else if (linkerr & 0xf0)
+ dev_info(&pdev->dev, "HT linkerror%d bits "
+ "0x%x couldn't be cleared\n",
+ i, linkerr >> 4);
+ }
+ }
+
+ /*
+ * this is just for our link to the host, not devices connected
+ * through tunnel.
+ */
+
+ if (pci_read_config_byte(pdev, link_a_b_off + 7, &linkwidth))
+ ipath_dev_err(dd, "Couldn't read HT link width "
+ "config register\n");
+ else {
+ u32 width;
+ switch (linkwidth & 7) {
+ case 5:
+ width = 4;
+ break;
+ case 4:
+ width = 2;
+ break;
+ case 3:
+ width = 32;
+ break;
+ case 1:
+ width = 16;
+ break;
+ case 0:
+ default: /* if wrong, assume 8 bit */
+ width = 8;
+ break;
+ }
+
+ dd->ipath_htwidth = width;
+
+ if (linkwidth != 0x11) {
+ ipath_dev_err(dd, "Not configured for 16 bit HT "
+ "(%x)\n", linkwidth);
+ if (!(linkwidth & 0xf)) {
+ ipath_dbg("Will ignore HT lane1 errors\n");
+ dd->ipath_flags |= IPATH_8BIT_IN_HT0;
+ }
+ }
+ }
+
+ /*
+ * this is just for our link to the host, not devices connected
+ * through tunnel.
+ */
+ if (pci_read_config_byte(pdev, link_a_b_off + 0xd, &linkwidth))
+ ipath_dev_err(dd, "Couldn't read HT link frequency "
+ "config register\n");
+ else {
+ u32 speed;
+ switch (linkwidth & 0xf) {
+ case 6:
+ speed = 1000;
+ break;
+ case 5:
+ speed = 800;
+ break;
+ case 4:
+ speed = 600;
+ break;
+ case 3:
+ speed = 500;
+ break;
+ case 2:
+ speed = 400;
+ break;
+ case 1:
+ speed = 300;
+ break;
+ default:
+ /*
+ * assume reserved and vendor-specific are 200...
+ */
+ case 0:
+ speed = 200;
+ break;
+ }
+ dd->ipath_htspeed = speed;
+ }
+}
+
+static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev,
+ int pos)
+{
+ u32 int_handler_addr_lower;
+ u32 int_handler_addr_upper;
+ u64 ihandler;
+ u32 intvec;
+
+ /* use indirection register to get the intr handler */
+ pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x10);
+ pci_read_config_dword(pdev, pos + 4, &int_handler_addr_lower);
+ pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x11);
+ pci_read_config_dword(pdev, pos + 4, &int_handler_addr_upper);
+
+ ihandler = (u64) int_handler_addr_lower |
+ ((u64) int_handler_addr_upper << 32);
+
+ /*
+ * kernels with CONFIG_PCI_MSI set the vector in the irq field of
+ * struct pci_device, so we use that to program the HT-400 internal
+ * interrupt register (not config space) with that value. The BIOS
+ * must still have done the basic MSI setup.
+ */
+ intvec = pdev->irq;
+ /*
+ * clear any vector bits there; normally not set but we'll overload
+ * this for some debug purposes (setting the HTC debug register
+ * value from software, rather than GPIOs), so it might be set on a
+ * driver reload.
+ */
+ ihandler &= ~0xff0000;
+ /* x86 vector goes in intrinfo[23:16] */
+ ihandler |= intvec << 16;
+ ipath_cdbg(VERBOSE, "ihandler lower %x, upper %x, intvec %x, "
+ "interruptconfig %llx\n", int_handler_addr_lower,
+ int_handler_addr_upper, intvec,
+ (unsigned long long) ihandler);
+
+ /* can't program yet, so save for interrupt setup */
+ dd->ipath_intconfig = ihandler;
+ /* keep going, so we find link control stuff also */
+
+ return ihandler != 0;
+}
+
+/**
+ * ipath_setup_ht_config - setup the interruptconfig register
+ * @dd: the infinipath device
+ * @pdev: the PCI device
+ *
+ * setup the interruptconfig register from the HT config info.
+ * Also clear CRC errors in HT linkcontrol, if necessary.
+ * This is done only for the real hardware. It is done before
+ * chip address space is initted, so can't touch infinipath registers
+ */
+static int ipath_setup_ht_config(struct ipath_devdata *dd,
+ struct pci_dev *pdev)
+{
+ int pos, ret = 0;
+ int ihandler = 0;
+
+ /*
+ * Read the capability info to find the interrupt info, and also
+ * handle clearing CRC errors in linkctrl register if necessary. We
+ * do this early, before we ever enable errors or hardware errors,
+ * mostly to avoid causing the chip to enter freeze mode.
+ */
+ pos = pci_find_capability(pdev, HT_CAPABILITY_ID);
+ if (!pos) {
+ ipath_dev_err(dd, "Couldn't find HyperTransport "
+ "capability; no interrupts\n");
+ ret = -ENODEV;
+ goto bail;
+ }
+ do {
+ u8 cap_type;
+
+ /* the HT capability type byte is 3 bytes after the
+ * capability byte.
+ */
+ if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {
+ dev_info(&pdev->dev, "Couldn't read config "
+ "command @ %d\n", pos);
+ continue;
+ }
+ if (!(cap_type & 0xE0))
+ slave_or_pri_blk(dd, pdev, pos, cap_type);
+ else if (cap_type == HT_INTR_DISC_CONFIG)
+ ihandler = set_int_handler(dd, pdev, pos);
+ } while ((pos = pci_find_next_capability(pdev, pos,
+ HT_CAPABILITY_ID)));
+
+ if (!ihandler) {
+ ipath_dev_err(dd, "Couldn't find interrupt handler in "
+ "config space\n");
+ ret = -ENODEV;
+ }
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_setup_ht_cleanup - clean up any per-chip chip-specific stuff
+ * @dd: the infinipath device
+ *
+ * Called during driver unload.
+ * This is currently a nop for the HT-400, not for all chips
+ */
+static void ipath_setup_ht_cleanup(struct ipath_devdata *dd)
+{
+}
+
+/**
+ * ipath_setup_ht_setextled - set the state of the two external LEDs
+ * @dd: the infinipath device
+ * @lst: the L state
+ * @ltst: the LT state
+ *
+ * Set the state of the two external LEDs, to indicate physical and
+ * logical state of IB link. For this chip (at least with recommended
+ * board pinouts), LED1 is Green (physical state), and LED2 is Yellow
+ * (logical state)
+ *
+ * Note: We try to match the Mellanox HCA LED behavior as best
+ * we can. Green indicates physical link state is OK (something is
+ * plugged in, and we can train).
+ * Amber indicates the link is logically up (ACTIVE).
+ * Mellanox further blinks the amber LED to indicate data packet
+ * activity, but we have no hardware support for that, so it would
+ * require waking up every 10-20 msecs and checking the counters
+ * on the chip, and then turning the LED off if appropriate. That's
+ * visible overhead, so not something we will do.
+ *
+ */
+static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
+ u64 lst, u64 ltst)
+{
+ u64 extctl;
+
+ /* 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;
+
+ /*
+ * start by setting both LED control bits to off, then turn
+ * on the appropriate bit(s).
+ */
+ if (dd->ipath_boardrev == 8) { /* LS/X-1 uses different pins */
+ /*
+ * major difference is that INFINIPATH_EXTC_LEDGBLERR_OFF
+ * is inverted, because it is normally used to indicate
+ * a hardware fault at reset, if there were errors
+ */
+ extctl = (dd->ipath_extctrl & ~INFINIPATH_EXTC_LEDGBLOK_ON)
+ | INFINIPATH_EXTC_LEDGBLERR_OFF;
+ if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl &= ~INFINIPATH_EXTC_LEDGBLERR_OFF;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LEDGBLOK_ON;
+ }
+ else {
+ extctl = dd->ipath_extctrl &
+ ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+ INFINIPATH_EXTC_LED2PRIPORT_ON);
+ if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+ }
+ dd->ipath_extctrl = extctl;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+}
+
+static void ipath_init_ht_variables(void)
+{
+ ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+ ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+ ipath_gpio_sda = IPATH_GPIO_SDA;
+ ipath_gpio_scl = IPATH_GPIO_SCL;
+
+ infinipath_i_bitsextant =
+ (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+ (INFINIPATH_I_RCVAVAIL_MASK <<
+ INFINIPATH_I_RCVAVAIL_SHIFT) |
+ INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
+ INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
+
+ infinipath_e_bitsextant =
+ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
+ INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
+ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
+ INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
+ INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
+ INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
+ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+ INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
+ INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |
+ INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |
+ INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
+ INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
+ INFINIPATH_E_HARDWARE;
+
+ infinipath_hwe_bitsextant =
+ (INFINIPATH_HWE_HTCMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) |
+ (INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |
+ (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+ INFINIPATH_HWE_HTCLNKABYTE0CRCERR |
+ INFINIPATH_HWE_HTCLNKABYTE1CRCERR |
+ INFINIPATH_HWE_HTCLNKBBYTE0CRCERR |
+ INFINIPATH_HWE_HTCLNKBBYTE1CRCERR |
+ INFINIPATH_HWE_HTCMISCERR4 |
+ INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 |
+ INFINIPATH_HWE_HTCMISCERR7 |
+ INFINIPATH_HWE_HTCBUSTREQPARITYERR |
+ INFINIPATH_HWE_HTCBUSTRESPPARITYERR |
+ INFINIPATH_HWE_HTCBUSIREQPARITYERR |
+ INFINIPATH_HWE_RXDSYNCMEMPARITYERR |
+ INFINIPATH_HWE_MEMBISTFAILED |
+ INFINIPATH_HWE_COREPLL_FBSLIP |
+ INFINIPATH_HWE_COREPLL_RFSLIP |
+ INFINIPATH_HWE_HTBPLL_FBSLIP |
+ INFINIPATH_HWE_HTBPLL_RFSLIP |
+ INFINIPATH_HWE_HTAPLL_FBSLIP |
+ INFINIPATH_HWE_HTAPLL_RFSLIP |
+ INFINIPATH_HWE_SERDESPLLFAILED |
+ INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
+ INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
+
+ infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+ infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+}
+
+/**
+ * ipath_ht_init_hwerrors - enable hardware errors
+ * @dd: the infinipath device
+ *
+ * now that we have finished initializing everything that might reasonably
+ * cause a hardware error, and cleared those errors bits as they occur,
+ * we can enable hardware errors in the mask (potentially enabling
+ * freeze mode), and enable hardware errors as errors (along with
+ * everything else) in errormask
+ */
+static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
+{
+ ipath_err_t val;
+ u64 extsval;
+
+ extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+ if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))
+ ipath_dev_err(dd, "MemBIST did not complete!\n");
+
+ ipath_check_htlink(dd);
+
+ /* barring bugs, all hwerrors become interrupts, which can */
+ val = -1LL;
+ /* don't look at crc lane1 if 8 bit */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT0)
+ val &= ~infinipath_hwe_htclnkabyte1crcerr;
+ /* don't look at crc lane1 if 8 bit */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT1)
+ val &= ~infinipath_hwe_htclnkbbyte1crcerr;
+
+ /*
+ * disable RXDSYNCMEMPARITY because external serdes is unused,
+ * and therefore the logic will never be used or initialized,
+ * and uninitialized state will normally result in this error
+ * being asserted. Similarly for the external serdess pll
+ * lock signal.
+ */
+ val &= ~(INFINIPATH_HWE_SERDESPLLFAILED |
+ INFINIPATH_HWE_RXDSYNCMEMPARITYERR);
+
+ /*
+ * Disable MISCERR4 because of an inversion in the HT core
+ * logic checking for errors that cause this bit to be set.
+ * The errata can also cause the protocol error bit to be set
+ * in the HT config space linkerror register(s).
+ */
+ val &= ~INFINIPATH_HWE_HTCMISCERR4;
+
+ /*
+ * PLL ignored because MDIO interface has a logic problem
+ * for reads, on Comstock and Ponderosa. BRINGUP
+ */
+ if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)
+ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ dd->ipath_hwerrmask = val;
+}
+
+/**
+ * ipath_ht_bringup_serdes - bring up the serdes
+ * @dd: the infinipath device
+ */
+static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
+{
+ u64 val, config1;
+ int ret = 0, change = 0;
+
+ ipath_dbg("Trying to bringup serdes\n");
+
+ if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
+ INFINIPATH_HWE_SERDESPLLFAILED)
+ {
+ ipath_dbg("At start, serdes PLL failed bit set in "
+ "hwerrstatus, clearing and continuing\n");
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ INFINIPATH_HWE_SERDESPLLFAILED);
+ }
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+ config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
+
+ ipath_cdbg(VERBOSE, "Initial serdes status is config0=%llx "
+ "config1=%llx, sstatus=%llx xgxs %llx\n",
+ (unsigned long long) val, (unsigned long long) config1,
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ /* force reset on */
+ val |= INFINIPATH_SERDC0_RESET_PLL
+ /* | INFINIPATH_SERDC0_RESET_MASK */
+ ;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ udelay(15); /* need pll reset set at least for a bit */
+
+ if (val & INFINIPATH_SERDC0_RESET_PLL) {
+ u64 val2 = val &= ~INFINIPATH_SERDC0_RESET_PLL;
+ /* set lane resets, and tx idle, during pll reset */
+ val2 |= INFINIPATH_SERDC0_RESET_MASK |
+ INFINIPATH_SERDC0_TXIDLE;
+ ipath_cdbg(VERBOSE, "Clearing serdes PLL reset (writing "
+ "%llx)\n", (unsigned long long) val2);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0,
+ val2);
+ /*
+ * be sure chip saw it
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ /*
+ * need pll reset clear at least 11 usec before lane
+ * resets cleared; give it a few more
+ */
+ udelay(15);
+ val = val2; /* for check below */
+ }
+
+ if (val & (INFINIPATH_SERDC0_RESET_PLL |
+ INFINIPATH_SERDC0_RESET_MASK |
+ INFINIPATH_SERDC0_TXIDLE)) {
+ val &= ~(INFINIPATH_SERDC0_RESET_PLL |
+ INFINIPATH_SERDC0_RESET_MASK |
+ INFINIPATH_SERDC0_TXIDLE);
+ /* clear them */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0,
+ val);
+ }
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+ val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+ INFINIPATH_XGXS_MDIOADDR_SHIFT);
+ /*
+ * we use address 3
+ */
+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+ change = 1;
+ }
+ if (val & INFINIPATH_XGXS_RESET) {
+ /* normally true after boot */
+ val &= ~INFINIPATH_XGXS_RESET;
+ change = 1;
+ }
+ if (change)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ /* clear current and de-emphasis bits */
+ config1 &= ~0x0ffffffff00ULL;
+ /* set current to 20ma */
+ config1 |= 0x00000000000ULL;
+ /* set de-emphasis to -5.68dB */
+ config1 |= 0x0cccc000000ULL;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);
+
+ ipath_cdbg(VERBOSE, "After setup: serdes status is config0=%llx "
+ "config1=%llx, sstatus=%llx xgxs %llx\n",
+ (unsigned long long) val, (unsigned long long) config1,
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ if (!ipath_waitfor_mdio_cmdready(dd)) {
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio,
+ ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+ IPATH_MDIO_CTRL_XGXS_REG_8,
+ 0));
+ if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+ IPATH_MDIO_DATAVALID, &val))
+ ipath_dbg("Never got MDIO data for XGXS status "
+ "read\n");
+ else
+ ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+ "'bank' 31 %x\n", (u32) val);
+ } else
+ ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
+ return ret; /* for now, say we always succeeded */
+}
+
+/**
+ * ipath_ht_quiet_serdes - set serdes to txidle
+ * @dd: the infinipath device
+ * driver is being unloaded
+ */
+static void ipath_ht_quiet_serdes(struct ipath_devdata *dd)
+{
+ u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ val |= INFINIPATH_SERDC0_TXIDLE;
+ ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
+ (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+}
+
+static int ipath_ht_intconfig(struct ipath_devdata *dd)
+{
+ int ret;
+
+ if (!dd->ipath_intconfig) {
+ ipath_dev_err(dd, "No interrupts enabled, couldn't setup "
+ "interrupt address\n");
+ ret = 1;
+ goto bail;
+ }
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig,
+ dd->ipath_intconfig); /* interrupt address */
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * 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
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for special locking etc.
+ * It's used for both the full cleanup on exit, as well as the normal
+ * setup and teardown.
+ */
+static void ipath_ht_put_tid(struct ipath_devdata *dd,
+ u64 __iomem *tidptr, u32 type,
+ unsigned long pa)
+{
+ if (pa != dd->ipath_tidinvalid) {
+ if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) {
+ dev_info(&dd->pcidev->dev,
+ "physaddr %lx has more than "
+ "40 bits, using only 40!!!\n", pa);
+ pa &= INFINIPATH_RT_ADDR_MASK;
+ }
+ if (type == 0)
+ pa |= dd->ipath_tidtemplate;
+ else {
+ /* in words (fixed, full page). */
+ u64 lenvalid = PAGE_SIZE >> 2;
+ lenvalid <<= INFINIPATH_RT_BUFSIZE_SHIFT;
+ pa |= lenvalid | INFINIPATH_RT_VALID;
+ }
+ }
+ if (dd->ipath_kregbase)
+ writeq(pa, tidptr);
+}
+
+/**
+ * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager
+ * @dd: the infinipath device
+ * @port: the port
+ *
+ * Used from ipath_close(), and at chip initialization.
+ */
+static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
+{
+ u64 __iomem *tidbase;
+ int i;
+
+ if (!dd->ipath_kregbase)
+ return;
+
+ ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
+
+ /*
+ * need to invalidate all of the expected TID entries for this
+ * port, so we don't have valid entries that might somehow get
+ * used (early in next use of this port, or through some bug)
+ */
+ tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ 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);
+
+ tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvegrbase +
+ port * dd->ipath_rcvegrcnt *
+ sizeof(*tidbase));
+
+ for (i = 0; i < dd->ipath_rcvegrcnt; i++)
+ ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid);
+}
+
+/**
+ * ipath_ht_tidtemplate - setup constants for TID updates
+ * @dd: the infinipath device
+ *
+ * We setup stuff that we use a lot, to avoid calculating each time
+ */
+static void ipath_ht_tidtemplate(struct ipath_devdata *dd)
+{
+ dd->ipath_tidtemplate = dd->ipath_ibmaxlen >> 2;
+ dd->ipath_tidtemplate <<= INFINIPATH_RT_BUFSIZE_SHIFT;
+ dd->ipath_tidtemplate |= INFINIPATH_RT_VALID;
+
+ /*
+ * work around chip errata bug 7358, by marking invalid tids
+ * as having max length
+ */
+ dd->ipath_tidinvalid = (-1LL & INFINIPATH_RT_BUFSIZE_MASK) <<
+ INFINIPATH_RT_BUFSIZE_SHIFT;
+}
+
+static int ipath_ht_early_init(struct ipath_devdata *dd)
+{
+ u32 __iomem *piobuf;
+ u32 pioincr, val32, egrsize;
+ int i;
+
+ /*
+ * one cache line; long IB headers will spill over into received
+ * buffer
+ */
+ dd->ipath_rcvhdrentsize = 16;
+ dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+
+ /*
+ * For HT-400, we allocate a somewhat overly large eager buffer,
+ * such that we can guarantee that we can receive the largest
+ * packet that we can send out. To truly support a 4KB MTU,
+ * we need to bump this to a large value. To date, other than
+ * testing, we have never encountered an HCA that can really
+ * send 4KB MTU packets, so we do not handle that (we'll get
+ * errors interrupts if we ever see one).
+ */
+ dd->ipath_rcvegrbufsize = dd->ipath_piosize2k;
+ egrsize = dd->ipath_rcvegrbufsize;
+
+ /*
+ * the min() check here is currently a nop, but it may not
+ * always be, depending on just how we do ipath_rcvegrbufsize
+ */
+ dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
+ dd->ipath_rcvegrbufsize);
+ dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+ ipath_ht_tidtemplate(dd);
+
+ /*
+ * zero all the TID entries at startup. We do this for sanity,
+ * in case of a previous driver crash of some kind, and also
+ * because the chip powers up with these memories in an unknown
+ * state. Use portcnt, not cfgports, since this is for the
+ * full chip, not for current (possibly different) configuration
+ * value.
+ * Chip Errata bug 6447
+ */
+ for (val32 = 0; val32 < dd->ipath_portcnt; val32++)
+ ipath_ht_clear_tids(dd, val32);
+
+ /*
+ * write the pbc of each buffer, to be sure it's initialized, then
+ * cancel all the buffers, and also abort any packets that might
+ * have been in flight for some reason (the latter is for driver
+ * unload/reload, but isn't a bad idea at first init). PIO send
+ * isn't enabled at this point, so there is no danger of sending
+ * these out on the wire.
+ * Chip Errata bug 6610
+ */
+ piobuf = (u32 __iomem *) (((char __iomem *)(dd->ipath_kregbase)) +
+ dd->ipath_piobufbase);
+ pioincr = dd->ipath_palign / sizeof(*piobuf);
+ for (i = 0; i < dd->ipath_piobcnt2k; i++) {
+ /*
+ * reasonable word count, just to init pbc
+ */
+ writel(16, piobuf);
+ piobuf += pioincr;
+ }
+ /*
+ * self-clearing
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_ABORT);
+ return 0;
+}
+
+/**
+ * ipath_init_ht_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+ * @kbase: ipath_base_info pointer
+ *
+ * We set the PCIE flag because the lower bandwidth on PCIe vs
+ * HyperTransport can affect some user packet algorithims.
+ */
+static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase)
+{
+ struct ipath_base_info *kinfo = kbase;
+
+ kinfo->spi_runtime_flags |= IPATH_RUNTIME_HT |
+ IPATH_RUNTIME_RCVHDR_COPY;
+
+ return 0;
+}
+
+/**
+ * ipath_init_ht400_funcs - set up the chip-specific function pointers
+ * @dd: the infinipath device
+ *
+ * This is global, and is called directly at init to set up the
+ * chip-specific function pointers for later use.
+ */
+void ipath_init_ht400_funcs(struct ipath_devdata *dd)
+{
+ dd->ipath_f_intrsetup = ipath_ht_intconfig;
+ dd->ipath_f_bus = ipath_setup_ht_config;
+ dd->ipath_f_reset = ipath_setup_ht_reset;
+ dd->ipath_f_get_boardname = ipath_ht_boardname;
+ dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors;
+ dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors;
+ dd->ipath_f_early_init = ipath_ht_early_init;
+ dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors;
+ dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes;
+ dd->ipath_f_bringup_serdes = ipath_ht_bringup_serdes;
+ dd->ipath_f_clear_tids = ipath_ht_clear_tids;
+ dd->ipath_f_put_tid = ipath_ht_put_tid;
+ dd->ipath_f_cleanup = ipath_setup_ht_cleanup;
+ dd->ipath_f_setextled = ipath_setup_ht_setextled;
+ dd->ipath_f_get_base_info = ipath_ht_get_base_info;
+
+ /*
+ * initialize chip-specific variables
+ */
+ dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
+
+ /*
+ * setup the register offsets, since they are different for each
+ * chip
+ */
+ dd->ipath_kregs = &ipath_ht_kregs;
+ dd->ipath_cregs = &ipath_ht_cregs;
+
+ /*
+ * do very early init that is needed before ipath_f_bus is
+ * called
+ */
+ ipath_init_ht_variables();
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
new file mode 100644
index 000000000000..2823ff9c0c62
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -0,0 +1,951 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+
+/*
+ * min buffers we want to have per port, after driver
+ */
+#define IPATH_MIN_USER_PORT_BUFCNT 8
+
+/*
+ * Number of ports we are configured to use (to allow for more pio
+ * buffers per port, etc.) Zero means use chip value.
+ */
+static ushort ipath_cfgports;
+
+module_param_named(cfgports, ipath_cfgports, ushort, S_IRUGO);
+MODULE_PARM_DESC(cfgports, "Set max number of ports to use");
+
+/*
+ * Number of buffers reserved for driver (layered drivers and SMA
+ * send). Reserved at end of buffer list.
+ */
+static ushort ipath_kpiobufs = 32;
+
+static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp);
+
+module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_uint,
+ &ipath_kpiobufs, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver");
+
+/**
+ * create_port0_egr - allocate the eager TID buffers
+ * @dd: the infinipath device
+ *
+ * This code is now quite different for user and kernel, because
+ * the kernel uses skb's, for the accelerated network performance.
+ * This is the kernel (port0) version.
+ *
+ * Allocate the eager TID buffers and program them into infinipath.
+ * We use the network layer alloc_skb() allocator to allocate the
+ * memory, and either use the buffers as is for things like SMA
+ * packets, or pass the buffers up to the ipath layered driver and
+ * thence the network layer, replacing them as we do so (see
+ * ipath_rcv_layer()).
+ */
+static int create_port0_egr(struct ipath_devdata *dd)
+{
+ unsigned e, egrcnt;
+ struct sk_buff **skbs;
+ int ret;
+
+ egrcnt = dd->ipath_rcvegrcnt;
+
+ skbs = vmalloc(sizeof(*dd->ipath_port0_skbs) * egrcnt);
+ if (skbs == NULL) {
+ ipath_dev_err(dd, "allocation error for eager TID "
+ "skb array\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+ for (e = 0; e < egrcnt; e++) {
+ /*
+ * This is a bit tricky in that we allocate extra
+ * space for 2 bytes of the 14 byte ethernet header.
+ * These two bytes are passed in the ipath header so
+ * the rest of the data is word aligned. We allocate
+ * 4 bytes so that the data buffer stays word aligned.
+ * See ipath_kreceive() for more details.
+ */
+ skbs[e] = ipath_alloc_skb(dd, GFP_KERNEL);
+ if (!skbs[e]) {
+ ipath_dev_err(dd, "SKB allocation error for "
+ "eager TID %u\n", e);
+ while (e != 0)
+ dev_kfree_skb(skbs[--e]);
+ ret = -ENOMEM;
+ goto bail;
+ }
+ }
+ /*
+ * After loop above, so we can test non-NULL to see if ready
+ * to use at receive, etc.
+ */
+ dd->ipath_port0_skbs = skbs;
+
+ for (e = 0; e < egrcnt; e++) {
+ unsigned long phys =
+ virt_to_phys(dd->ipath_port0_skbs[e]->data);
+ dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
+ ((char __iomem *) dd->ipath_kregbase +
+ dd->ipath_rcvegrbase), 0, phys);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int bringup_link(struct ipath_devdata *dd)
+{
+ u64 val, ibc;
+ int ret = 0;
+
+ /* hold IBC in reset */
+ dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+
+ /*
+ * Note that prior to try 14 or 15 of IB, the credit scaling
+ * wasn't working, because it was swapped for writes with the
+ * 1 bit default linkstate field
+ */
+
+ /* ignore pbc and align word */
+ val = dd->ipath_piosize2k - 2 * sizeof(u32);
+ /*
+ * for ICRC, which we only send in diag test pkt mode, and we
+ * don't need to worry about that for mtu
+ */
+ val += 1;
+ /*
+ * Set the IBC maxpktlength to the size of our pio buffers the
+ * maxpktlength is in words. This is *not* the IB data MTU.
+ */
+ ibc = (val / sizeof(u32)) << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+ /* in KB */
+ ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT;
+ /*
+ * How often flowctrl sent. More or less in usecs; balance against
+ * watermark value, so that in theory senders always get a flow
+ * control update in time to not let the IB link go idle.
+ */
+ ibc |= 0x3ULL << INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT;
+ /* max error tolerance */
+ ibc |= 0xfULL << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
+ /* use "real" buffer space for */
+ ibc |= 4ULL << INFINIPATH_IBCC_CREDITSCALE_SHIFT;
+ /* IB credit flow control. */
+ ibc |= 0xfULL << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
+ /* initially come up waiting for TS1, without sending anything. */
+ dd->ipath_ibcctrl = ibc;
+ /*
+ * Want to start out with both LINKCMD and LINKINITCMD in NOP
+ * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that
+ * to stay a NOP
+ */
+ ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT;
+ ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n",
+ (unsigned long long) ibc);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc);
+
+ // be sure chip saw it
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+
+ ret = dd->ipath_f_bringup_serdes(dd);
+
+ if (ret)
+ dev_info(&dd->pcidev->dev, "Could not initialize SerDes, "
+ "not usable\n");
+ else {
+ /* enable IBC */
+ dd->ipath_control |= INFINIPATH_C_LINKENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+ }
+
+ return ret;
+}
+
+static int init_chip_first(struct ipath_devdata *dd,
+ struct ipath_portdata **pdp)
+{
+ struct ipath_portdata *pd = NULL;
+ int ret = 0;
+ u64 val;
+
+ /*
+ * skip cfgports stuff because we are not allocating memory,
+ * and we don't want problems if the portcnt changed due to
+ * cfgports. We do still check and report a difference, if
+ * not same (should be impossible).
+ */
+ dd->ipath_portcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+ if (!ipath_cfgports)
+ dd->ipath_cfgports = dd->ipath_portcnt;
+ else if (ipath_cfgports <= dd->ipath_portcnt) {
+ dd->ipath_cfgports = ipath_cfgports;
+ ipath_dbg("Configured to use %u ports out of %u in chip\n",
+ dd->ipath_cfgports, dd->ipath_portcnt);
+ } else {
+ dd->ipath_cfgports = dd->ipath_portcnt;
+ ipath_dbg("Tried to configured to use %u ports; chip "
+ "only supports %u\n", ipath_cfgports,
+ dd->ipath_portcnt);
+ }
+ dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_cfgports,
+ GFP_KERNEL);
+
+ if (!dd->ipath_pd) {
+ ipath_dev_err(dd, "Unable to allocate portdata array, "
+ "failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads)
+ * dd->ipath_cfgports,
+ GFP_KERNEL);
+ dd->ipath_lastrcvhdrqtails =
+ kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails)
+ * dd->ipath_cfgports, GFP_KERNEL);
+
+ if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) {
+ ipath_dev_err(dd, "Unable to allocate head arrays, "
+ "failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ dd->ipath_pd[0] = kzalloc(sizeof(*pd), GFP_KERNEL);
+
+ if (!dd->ipath_pd[0]) {
+ ipath_dev_err(dd, "Unable to allocate portdata for port "
+ "0, failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+ pd = dd->ipath_pd[0];
+ pd->port_dd = dd;
+ pd->port_port = 0;
+ pd->port_cnt = 1;
+ /* The port 0 pkey table is used by the layer interface. */
+ pd->port_pkeys[0] = IPS_DEFAULT_P_KEY;
+ dd->ipath_rcvtidcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+ dd->ipath_rcvtidbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase);
+ dd->ipath_rcvegrcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
+ dd->ipath_rcvegrbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase);
+ dd->ipath_palign =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
+ dd->ipath_piobufbase =
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufbase);
+ 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 */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
+ dd->ipath_piobcnt2k = val & ~0U;
+ dd->ipath_piobcnt4k = val >> 32;
+ dd->ipath_pio2kbase =
+ (u32 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
+ (dd->ipath_piobufbase & 0xffffffff));
+ if (dd->ipath_piobcnt4k) {
+ dd->ipath_pio4kbase = (u32 __iomem *)
+ (((char __iomem *) dd->ipath_kregbase) +
+ (dd->ipath_piobufbase >> 32));
+ /*
+ * 4K buffers take 2 pages; we use roundup just to be
+ * paranoid; we calculate it once here, rather than on
+ * ever buf allocate
+ */
+ dd->ipath_4kalign = ALIGN(dd->ipath_piosize4k,
+ dd->ipath_palign);
+ ipath_dbg("%u 2k(%x) piobufs @ %p, %u 4k(%x) @ %p "
+ "(%x aligned)\n",
+ dd->ipath_piobcnt2k, dd->ipath_piosize2k,
+ dd->ipath_pio2kbase, dd->ipath_piobcnt4k,
+ dd->ipath_piosize4k, dd->ipath_pio4kbase,
+ dd->ipath_4kalign);
+ }
+ else ipath_dbg("%u 2k piobufs @ %p\n",
+ dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
+
+ spin_lock_init(&dd->ipath_tid_lock);
+
+done:
+ *pdp = pd;
+ return ret;
+}
+
+/**
+ * init_chip_reset - re-initialize after a reset, or enable
+ * @dd: the infinipath device
+ * @pdp: output for port data
+ *
+ * sanity check at least some of the values after reset, and
+ * ensure no receive or transmit (explictly, in case reset
+ * failed
+ */
+static int init_chip_reset(struct ipath_devdata *dd,
+ struct ipath_portdata **pdp)
+{
+ struct ipath_portdata *pd;
+ u32 rtmp;
+
+ *pdp = pd = dd->ipath_pd[0];
+ /* ensure chip does no sends or receives while we re-initialize */
+ dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0);
+
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+ if (dd->ipath_portcnt != rtmp)
+ dev_info(&dd->pcidev->dev, "portcnt was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_portcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+ if (rtmp != dd->ipath_rcvtidcnt)
+ dev_info(&dd->pcidev->dev, "tidcnt was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvtidcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase);
+ if (rtmp != dd->ipath_rcvtidbase)
+ dev_info(&dd->pcidev->dev, "tidbase was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvtidbase, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
+ if (rtmp != dd->ipath_rcvegrcnt)
+ dev_info(&dd->pcidev->dev, "egrcnt was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvegrcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase);
+ if (rtmp != dd->ipath_rcvegrbase)
+ dev_info(&dd->pcidev->dev, "egrbase was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvegrbase, rtmp);
+
+ return 0;
+}
+
+static int init_pioavailregs(struct ipath_devdata *dd)
+{
+ int ret;
+
+ dd->ipath_pioavailregs_dma = dma_alloc_coherent(
+ &dd->pcidev->dev, PAGE_SIZE, &dd->ipath_pioavailregs_phys,
+ GFP_KERNEL);
+ if (!dd->ipath_pioavailregs_dma) {
+ ipath_dev_err(dd, "failed to allocate PIOavail reg area "
+ "in memory\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ /*
+ * we really want L2 cache aligned, but for current CPUs of
+ * interest, they are the same.
+ */
+ dd->ipath_statusp = (u64 *)
+ ((char *)dd->ipath_pioavailregs_dma +
+ ((2 * L1_CACHE_BYTES +
+ dd->ipath_pioavregs * sizeof(u64)) & ~L1_CACHE_BYTES));
+ /* copy the current value now that it's really allocated */
+ *dd->ipath_statusp = dd->_ipath_status;
+ /*
+ * setup buffer to hold freeze msg, accessible to apps,
+ * following statusp
+ */
+ dd->ipath_freezemsg = (char *)&dd->ipath_statusp[1];
+ /* and its length */
+ dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]);
+
+ if (dd->ipath_unit * 64 > (IPATH_PORT0_RCVHDRTAIL_SIZE - 64)) {
+ ipath_dev_err(dd, "unit %u too large for port 0 "
+ "rcvhdrtail buffer size\n", dd->ipath_unit);
+ ret = -ENODEV;
+ }
+ else
+ ret = 0;
+
+ /* so we can get current tail in ipath_kreceive(), per chip */
+ dd->ipath_hdrqtailptr = &ipath_port0_rcvhdrtail[
+ dd->ipath_unit * (64 / sizeof(*ipath_port0_rcvhdrtail))];
+done:
+ return ret;
+}
+
+/**
+ * init_shadow_tids - allocate the shadow TID array
+ * @dd: the infinipath device
+ *
+ * allocate the shadow TID array, so we can ipath_munlock previous
+ * entries. It may make more sense to move the pageshadow to the
+ * port data structure, so we only allocate memory for ports actually
+ * in use, since we at 8k per port, now.
+ */
+static void init_shadow_tids(struct ipath_devdata *dd)
+{
+ dd->ipath_pageshadow = (struct page **)
+ vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+ sizeof(struct page *));
+ if (!dd->ipath_pageshadow)
+ ipath_dev_err(dd, "failed to allocate shadow page * "
+ "array, no expected sends!\n");
+ else
+ memset(dd->ipath_pageshadow, 0,
+ dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+ sizeof(struct page *));
+}
+
+static void enable_chip(struct ipath_devdata *dd,
+ struct ipath_portdata *pd, int reinit)
+{
+ u32 val;
+ int i;
+
+ if (!reinit) {
+ init_waitqueue_head(&ipath_sma_state_wait);
+ }
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ /* Enable PIO send, and update of PIOavail regs to memory. */
+ dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
+ INFINIPATH_S_PIOBUFAVAILUPD;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ /*
+ * enable port 0 receive, and receive interrupt. other ports
+ * done as user opens and inits them.
+ */
+ dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD |
+ (1ULL << INFINIPATH_R_PORTENABLE_SHIFT) |
+ (1ULL << INFINIPATH_R_INTRAVAIL_SHIFT);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ /*
+ * now ready for use. this should be cleared whenever we
+ * detect a reset, or initiate one.
+ */
+ dd->ipath_flags |= IPATH_INITTED;
+
+ /*
+ * init our shadow copies of head from tail values, and write
+ * head values to match.
+ */
+ val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
+ (void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+ dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0);
+
+ /* Initialize so we interrupt on next packet received */
+ (void)ipath_write_ureg(dd, ur_rcvhdrhead,
+ dd->ipath_rhdrhead_intr_off |
+ dd->ipath_port0head, 0);
+
+ /*
+ * by now pioavail updates to memory should have occurred, so
+ * copy them into our working/shadow registers; this is in
+ * case something went wrong with abort, but mostly to get the
+ * initial values of the generation bit correct.
+ */
+ for (i = 0; i < dd->ipath_pioavregs; i++) {
+ __le64 val;
+
+ /*
+ * Chip Errata bug 6641; even and odd qwords>3 are swapped.
+ */
+ if (i > 3) {
+ if (i & 1)
+ val = dd->ipath_pioavailregs_dma[i - 1];
+ else
+ val = dd->ipath_pioavailregs_dma[i + 1];
+ }
+ else
+ val = dd->ipath_pioavailregs_dma[i];
+ dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
+ }
+ /* can get counters, stats, etc. */
+ dd->ipath_flags |= IPATH_PRESENT;
+}
+
+static int init_housekeeping(struct ipath_devdata *dd,
+ struct ipath_portdata **pdp, int reinit)
+{
+ char boardn[32];
+ int ret = 0;
+
+ /*
+ * have to clear shadow copies of registers at init that are
+ * not otherwise set here, or all kinds of bizarre things
+ * happen with driver on chip reset
+ */
+ dd->ipath_rcvhdrsize = 0;
+
+ /*
+ * Don't clear ipath_flags as 8bit mode was set before
+ * entering this func. However, we do set the linkstate to
+ * unknown, so we can watch for a transition.
+ */
+ dd->ipath_flags |= IPATH_LINKUNK;
+ dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED |
+ IPATH_LINKDOWN | IPATH_LINKINIT);
+
+ ipath_cdbg(VERBOSE, "Try to read spc chip revision\n");
+ dd->ipath_revision =
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+
+ /*
+ * set up fundamental info we need to use the chip; we assume
+ * if the revision reg and these regs are OK, we don't need to
+ * special case the rest
+ */
+ dd->ipath_sregbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_sendregbase);
+ dd->ipath_cregbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_counterregbase);
+ dd->ipath_uregbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_userregbase);
+ ipath_cdbg(VERBOSE, "ipath_kregbase %p, sendbase %x usrbase %x, "
+ "cntrbase %x\n", dd->ipath_kregbase, dd->ipath_sregbase,
+ dd->ipath_uregbase, dd->ipath_cregbase);
+ if ((dd->ipath_revision & 0xffffffff) == 0xffffffff
+ || (dd->ipath_sregbase & 0xffffffff) == 0xffffffff
+ || (dd->ipath_cregbase & 0xffffffff) == 0xffffffff
+ || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) {
+ ipath_dev_err(dd, "Register read failures from chip, "
+ "giving up initialization\n");
+ ret = -ENODEV;
+ goto done;
+ }
+
+ /* clear the initial reset flag, in case first driver load */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+ INFINIPATH_E_RESET);
+
+ if (reinit)
+ ret = init_chip_reset(dd, pdp);
+ else
+ ret = init_chip_first(dd, pdp);
+
+ if (ret)
+ goto done;
+
+ ipath_cdbg(VERBOSE, "Revision %llx (PCI %x), %u ports, %u tids, "
+ "%u egrtids\n", (unsigned long long) dd->ipath_revision,
+ dd->ipath_pcirev, dd->ipath_portcnt, dd->ipath_rcvtidcnt,
+ dd->ipath_rcvegrcnt);
+
+ if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) {
+ ipath_dev_err(dd, "Driver only handles version %d, "
+ "chip swversion is %d (%llx), failng\n",
+ IPATH_CHIP_SWVERSION,
+ (int)(dd->ipath_revision >>
+ INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK,
+ (unsigned long long) dd->ipath_revision);
+ ret = -ENOSYS;
+ goto done;
+ }
+ dd->ipath_majrev = (u8) ((dd->ipath_revision >>
+ INFINIPATH_R_CHIPREVMAJOR_SHIFT) &
+ INFINIPATH_R_CHIPREVMAJOR_MASK);
+ dd->ipath_minrev = (u8) ((dd->ipath_revision >>
+ INFINIPATH_R_CHIPREVMINOR_SHIFT) &
+ INFINIPATH_R_CHIPREVMINOR_MASK);
+ dd->ipath_boardrev = (u8) ((dd->ipath_revision >>
+ INFINIPATH_R_BOARDID_SHIFT) &
+ INFINIPATH_R_BOARDID_MASK);
+
+ 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, "
+ "SW Compat %u\n",
+ IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
+ (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
+ INFINIPATH_R_ARCH_MASK,
+ dd->ipath_majrev, dd->ipath_minrev, dd->ipath_pcirev,
+ (unsigned)(dd->ipath_revision >>
+ INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK);
+
+ ipath_dbg("%s", dd->ipath_boardversion);
+
+done:
+ return ret;
+}
+
+
+/**
+ * ipath_init_chip - do the actual initialization sequence on the chip
+ * @dd: the infinipath device
+ * @reinit: reinitializing, so don't allocate new memory
+ *
+ * Do the actual initialization sequence on the chip. This is done
+ * both from the init routine called from the PCI infrastructure, and
+ * when we reset the chip, or detect that it was reset internally,
+ * or it's administratively re-enabled.
+ *
+ * Memory allocation here and in called routines is only done in
+ * the first case (reinit == 0). We have to be careful, because even
+ * without memory allocation, we need to re-write all the chip registers
+ * TIDs, etc. after the reset or enable has completed.
+ */
+int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+{
+ int ret = 0, i;
+ u32 val32, kpiobufs;
+ u64 val, atmp;
+ struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
+
+ ret = init_housekeeping(dd, &pd, reinit);
+ if (ret)
+ goto done;
+
+ /*
+ * we ignore most issues after reporting them, but have to specially
+ * handle hardware-disabled chips.
+ */
+ if (ret == 2) {
+ /* unique error, known to ipath_init_one */
+ ret = -EPERM;
+ goto done;
+ }
+
+ /*
+ * We could bump this to allow for full rcvegrcnt + rcvtidcnt,
+ * but then it no longer nicely fits power of two, and since
+ * we now use routines that backend onto __get_free_pages, the
+ * rest would be wasted.
+ */
+ dd->ipath_rcvhdrcnt = dd->ipath_rcvegrcnt;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt,
+ dd->ipath_rcvhdrcnt);
+
+ /*
+ * Set up the shadow copies of the piobufavail registers,
+ * which we compare against the chip registers for now, and
+ * the in memory DMA'ed copies of the registers. This has to
+ * be done early, before we calculate lastport, etc.
+ */
+ val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+ /*
+ * calc number of pioavail registers, and save it; we have 2
+ * bits per buffer.
+ */
+ dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2)
+ / (sizeof(u64) * BITS_PER_BYTE / 2);
+ if (!ipath_kpiobufs) /* have to have at least 1, for SMA */
+ kpiobufs = ipath_kpiobufs = 1;
+ else if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) <
+ (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT)) {
+ dev_info(&dd->pcidev->dev, "Too few PIO buffers (%u) "
+ "for %u ports to have %u each!\n",
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
+ dd->ipath_cfgports, IPATH_MIN_USER_PORT_BUFCNT);
+ kpiobufs = 1; /* reserve just the minimum for SMA/ether */
+ } else
+ kpiobufs = ipath_kpiobufs;
+
+ if (kpiobufs >
+ (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+ (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT))) {
+ i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+ (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT);
+ if (i < 0)
+ i = 0;
+ dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs for "
+ "kernel leaves too few for %d user ports "
+ "(%d each); using %u\n", kpiobufs,
+ dd->ipath_cfgports - 1,
+ IPATH_MIN_USER_PORT_BUFCNT, i);
+ /*
+ * shouldn't change ipath_kpiobufs, because could be
+ * different for different devices...
+ */
+ kpiobufs = i;
+ }
+ dd->ipath_lastport_piobuf =
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs;
+ dd->ipath_pbufsport = dd->ipath_cfgports > 1
+ ? dd->ipath_lastport_piobuf / (dd->ipath_cfgports - 1)
+ : 0;
+ val32 = dd->ipath_lastport_piobuf -
+ (dd->ipath_pbufsport * (dd->ipath_cfgports - 1));
+ if (val32 > 0) {
+ ipath_dbg("allocating %u pbufs/port leaves %u unused, "
+ "add to kernel\n", dd->ipath_pbufsport, val32);
+ dd->ipath_lastport_piobuf -= val32;
+ ipath_dbg("%u pbufs/port leaves %u unused, add to kernel\n",
+ dd->ipath_pbufsport, val32);
+ }
+ dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;
+ ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u "
+ "each for %u user ports\n", kpiobufs,
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
+ dd->ipath_pbufsport, dd->ipath_cfgports - 1);
+
+ dd->ipath_f_early_init(dd);
+
+ /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
+ * done after early_init */
+ dd->ipath_hdrqlast =
+ dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize,
+ dd->ipath_rcvhdrentsize);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize,
+ dd->ipath_rcvhdrsize);
+
+ if (!reinit) {
+ ret = init_pioavailregs(dd);
+ init_shadow_tids(dd);
+ if (ret)
+ goto done;
+ }
+
+ (void)ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
+ dd->ipath_pioavailregs_phys);
+ /*
+ * this is to detect s/w errors, which the h/w works around by
+ * ignoring the low 6 bits of address, if it wasn't aligned.
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpioavailaddr);
+ if (val != dd->ipath_pioavailregs_phys) {
+ ipath_dev_err(dd, "Catastrophic software error, "
+ "SendPIOAvailAddr written as %lx, "
+ "read back as %llx\n",
+ (unsigned long) dd->ipath_pioavailregs_phys,
+ (unsigned long long) val);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ val = ipath_port0_rcvhdrtail_dma + dd->ipath_unit * 64;
+
+ /* verify that the alignment requirement was met */
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+ 0, val);
+ atmp = ipath_read_kreg64_port(
+ dd, dd->ipath_kregs->kr_rcvhdrtailaddr, 0);
+ if (val != atmp) {
+ ipath_dev_err(dd, "Catastrophic software error, "
+ "RcvHdrTailAddr0 written as %llx, "
+ "read back as %llx from %x\n",
+ (unsigned long long) val,
+ (unsigned long long) atmp,
+ dd->ipath_kregs->kr_rcvhdrtailaddr);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP);
+
+ /*
+ * make sure we are not in freeze, and PIO send enabled, so
+ * writes to pbc happen
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, 0ULL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_PIOENABLE);
+
+ /*
+ * before error clears, since we expect serdes pll errors during
+ * this, the first time after reset
+ */
+ if (bringup_link(dd)) {
+ dev_info(&dd->pcidev->dev, "Failed to bringup IB link\n");
+ ret = -ENETDOWN;
+ goto done;
+ }
+
+ /*
+ * clear any "expected" hwerrs from reset and/or initialization
+ * clear any that aren't enabled (at least this once), and then
+ * set the enable mask
+ */
+ dd->ipath_f_init_hwerrors(dd);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+
+ dd->ipath_maskederrs = dd->ipath_ignorederrs;
+ /* clear all */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
+ /* enable errors that are masked, at least this first time. */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ /* clear any interrups up to this point (ints still not enabled) */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
+ ipath_stats.sps_lid[dd->ipath_unit] = dd->ipath_lid;
+
+ /*
+ * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing
+ * re-init, the simplest way to handle this is to free
+ * existing, and re-allocate.
+ */
+ if (reinit)
+ ipath_free_pddata(dd, 0, 0);
+ dd->ipath_f_tidtemplate(dd);
+ ret = ipath_create_rcvhdrq(dd, pd);
+ if (!ret)
+ ret = create_port0_egr(dd);
+ if (ret)
+ ipath_dev_err(dd, "failed to allocate port 0 (kernel) "
+ "rcvhdrq and/or egr bufs\n");
+ else
+ enable_chip(dd, pd, reinit);
+
+ /*
+ * cause retrigger of pending interrupts ignored during init,
+ * even if we had errors
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+
+ if(!dd->ipath_stats_timer_active) {
+ /*
+ * first init, or after an admin disable/enable
+ * set up stats retrieval timer, even if we had errors
+ * in last portion of setup
+ */
+ init_timer(&dd->ipath_stats_timer);
+ dd->ipath_stats_timer.function = ipath_get_faststats;
+ dd->ipath_stats_timer.data = (unsigned long) dd;
+ /* every 5 seconds; */
+ dd->ipath_stats_timer.expires = jiffies + 5 * HZ;
+ /* takes ~16 seconds to overflow at full IB 4x bandwdith */
+ add_timer(&dd->ipath_stats_timer);
+ dd->ipath_stats_timer_active = 1;
+ }
+
+done:
+ if (!ret) {
+ ipath_get_guid(dd);
+ *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
+ if (!dd->ipath_f_intrsetup(dd)) {
+ /* now we can enable all interrupts from the chip */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask,
+ -1LL);
+ /* force re-interrupt of any pending interrupts. */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear,
+ 0ULL);
+ /* chip is usable; mark it as initialized */
+ *dd->ipath_statusp |= IPATH_STATUS_INITTED;
+ } else
+ ipath_dev_err(dd, "No interrupts enabled, couldn't "
+ "setup interrupt address\n");
+
+ if (dd->ipath_cfgports > ipath_stats.sps_nports)
+ /*
+ * sps_nports is a global, so, we set it to
+ * the highest number of ports of any of the
+ * chips we find; we never decrement it, at
+ * least for now. Since this might have changed
+ * over disable/enable or prior to reset, always
+ * do the check and potentially adjust.
+ */
+ ipath_stats.sps_nports = dd->ipath_cfgports;
+ } else
+ ipath_dbg("Failed (%d) to initialize chip\n", ret);
+
+ /* if ret is non-zero, we probably should do some cleanup
+ here... */
+ return ret;
+}
+
+static int ipath_set_kpiobufs(const char *str, struct kernel_param *kp)
+{
+ struct ipath_devdata *dd;
+ unsigned long flags;
+ unsigned short val;
+ int ret;
+
+ ret = ipath_parse_ushort(str, &val);
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ if (ret < 0)
+ goto bail;
+
+ if (val == 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+ if (dd->ipath_kregbase)
+ continue;
+ if (val > (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+ (dd->ipath_cfgports *
+ IPATH_MIN_USER_PORT_BUFCNT)))
+ {
+ ipath_dev_err(
+ dd,
+ "Allocating %d PIO bufs for kernel leaves "
+ "too few for %d user ports (%d each)\n",
+ val, dd->ipath_cfgports - 1,
+ IPATH_MIN_USER_PORT_BUFCNT);
+ ret = -EINVAL;
+ goto bail;
+ }
+ dd->ipath_lastport_piobuf =
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - val;
+ }
+
+ ret = 0;
+bail:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
new file mode 100644
index 000000000000..0bcb428041f3
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+#define E_SUM_PKTERRS \
+ (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \
+ INFINIPATH_E_RBADVERSION | INFINIPATH_E_RHDR | \
+ INFINIPATH_E_RLONGPKTLEN | INFINIPATH_E_RSHORTPKTLEN | \
+ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RMINPKTLEN | \
+ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RUNSUPVL | \
+ INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_REBP)
+
+#define E_SUM_ERRS \
+ (INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | \
+ INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
+ INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SUNSUPVL | \
+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \
+ INFINIPATH_E_INVALIDADDR)
+
+static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs)
+{
+ unsigned long sbuf[4];
+ u64 ignore_this_time = 0;
+ u32 piobcnt;
+
+ /* if possible that sendbuffererror could be valid */
+ piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+ /* read these before writing errorclear */
+ sbuf[0] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror);
+ sbuf[1] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 1);
+ if (piobcnt > 128) {
+ sbuf[2] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 2);
+ sbuf[3] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 3);
+ }
+
+ if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+ int i;
+
+ ipath_cdbg(PKT, "SendbufErrs %lx %lx ", sbuf[0], sbuf[1]);
+ if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128)
+ printk("%lx %lx ", sbuf[2], sbuf[3]);
+ for (i = 0; i < piobcnt; i++) {
+ if (test_bit(i, sbuf)) {
+ u32 __iomem *piobuf;
+ if (i < dd->ipath_piobcnt2k)
+ piobuf = (u32 __iomem *)
+ (dd->ipath_pio2kbase +
+ i * dd->ipath_palign);
+ else
+ piobuf = (u32 __iomem *)
+ (dd->ipath_pio4kbase +
+ (i - dd->ipath_piobcnt2k) *
+ dd->ipath_4kalign);
+
+ ipath_cdbg(PKT,
+ "PIObuf[%u] @%p pbc is %x; ",
+ i, piobuf, readl(piobuf));
+
+ ipath_disarm_piobufs(dd, i, 1);
+ }
+ }
+ if (ipath_debug & __IPATH_PKTDBG)
+ printk("\n");
+ }
+ if ((errs & (INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SDROPPEDSMPPKT |
+ INFINIPATH_E_SMINPKTLEN)) &&
+ !(dd->ipath_flags & IPATH_LINKACTIVE)) {
+ /*
+ * This can happen when SMA is trying to bring the link
+ * up, but the IB link changes state at the "wrong" time.
+ * The IB logic then complains that the packet isn't
+ * valid. We don't want to confuse people, so we just
+ * don't print them, except at debug
+ */
+ ipath_dbg("Ignoring pktsend errors %llx, because not "
+ "yet active\n", (unsigned long long) errs);
+ ignore_this_time = INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SDROPPEDSMPPKT |
+ INFINIPATH_E_SMINPKTLEN;
+ }
+
+ return ignore_this_time;
+}
+
+/* return the strings for the most common link states */
+static char *ib_linkstate(u32 linkstate)
+{
+ char *ret;
+
+ switch (linkstate) {
+ case IPATH_IBSTATE_INIT:
+ ret = "Init";
+ break;
+ case IPATH_IBSTATE_ARM:
+ ret = "Arm";
+ break;
+ case IPATH_IBSTATE_ACTIVE:
+ ret = "Active";
+ break;
+ default:
+ ret = "Down";
+ }
+
+ return ret;
+}
+
+static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+ ipath_err_t errs, int noprint)
+{
+ u64 val;
+ u32 ltstate, lstate;
+
+ /*
+ * even if diags are enabled, we want to notice LINKINIT, etc.
+ * We just don't want to change the LED state, or
+ * dd->ipath_kregs->kr_ibcctrl
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ lstate = val & IPATH_IBSTATE_MASK;
+ if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
+ lstate == IPATH_IBSTATE_ACTIVE) {
+ /*
+ * only print at SMA if there is a change, debug if not
+ * (sometimes we want to know that, usually not).
+ */
+ if (lstate == ((unsigned) dd->ipath_lastibcstat
+ & IPATH_IBSTATE_MASK)) {
+ ipath_dbg("Status change intr but no change (%s)\n",
+ ib_linkstate(lstate));
+ }
+ else
+ ipath_cdbg(SMA, "Unit %u link state %s, last "
+ "was %s\n", dd->ipath_unit,
+ ib_linkstate(lstate),
+ ib_linkstate((unsigned)
+ dd->ipath_lastibcstat
+ & IPATH_IBSTATE_MASK));
+ }
+ else {
+ lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+ if (lstate == IPATH_IBSTATE_INIT ||
+ lstate == IPATH_IBSTATE_ARM ||
+ lstate == IPATH_IBSTATE_ACTIVE)
+ ipath_cdbg(SMA, "Unit %u link state down"
+ " (state 0x%x), from %s\n",
+ dd->ipath_unit,
+ (u32)val & IPATH_IBSTATE_MASK,
+ ib_linkstate(lstate));
+ else
+ ipath_cdbg(VERBOSE, "Unit %u link state changed "
+ "to 0x%x from down (%x)\n",
+ dd->ipath_unit, (u32) val, lstate);
+ }
+ ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+ lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKSTATE_MASK;
+
+ if (ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
+ ltstate == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+ u32 last_ltstate;
+
+ /*
+ * Ignore cycling back and forth from Polling.Active
+ * to Polling.Quiet while waiting for the other end of
+ * the link to come up. We will cycle back and forth
+ * between them if no cable is plugged in,
+ * the other device is powered off or disabled, etc.
+ */
+ last_ltstate = (dd->ipath_lastibcstat >>
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT)
+ & INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+ if (last_ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE
+ || last_ltstate ==
+ INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+ if (dd->ipath_ibpollcnt > 40) {
+ dd->ipath_flags |= IPATH_NOCABLE;
+ *dd->ipath_statusp |=
+ IPATH_STATUS_IB_NOCABLE;
+ } else
+ dd->ipath_ibpollcnt++;
+ goto skip_ibchange;
+ }
+ }
+ dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */
+ ipath_stats.sps_iblink++;
+ if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
+ dd->ipath_flags |= IPATH_LINKDOWN;
+ dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+ | IPATH_LINKACTIVE |
+ IPATH_LINKARMED);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ if (!noprint) {
+ if (((dd->ipath_lastibcstat >>
+ INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKSTATE_MASK)
+ == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ /* if from up to down be more vocal */
+ ipath_cdbg(SMA,
+ "Unit %u link now down (%s)\n",
+ dd->ipath_unit,
+ ipath_ibcstatus_str[ltstate]);
+ else
+ ipath_cdbg(VERBOSE, "Unit %u link is "
+ "down (%s)\n", dd->ipath_unit,
+ ipath_ibcstatus_str[ltstate]);
+ }
+
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ACTIVE) {
+ dd->ipath_flags |= IPATH_LINKACTIVE;
+ dd->ipath_flags &=
+ ~(IPATH_LINKUNK | IPATH_LINKINIT | IPATH_LINKDOWN |
+ IPATH_LINKARMED | IPATH_NOCABLE);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
+ *dd->ipath_statusp |=
+ IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+
+ __ipath_layer_intr(dd, IPATH_LAYER_INT_IF_UP);
+ } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+ /*
+ * set INIT and DOWN. Down is checked by most of the other
+ * code, but INIT is useful to know in a few places.
+ */
+ dd->ipath_flags |= IPATH_LINKINIT | IPATH_LINKDOWN;
+ dd->ipath_flags &=
+ ~(IPATH_LINKUNK | IPATH_LINKACTIVE | IPATH_LINKARMED
+ | IPATH_NOCABLE);
+ *dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+ | IPATH_STATUS_IB_READY);
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+ dd->ipath_flags |= IPATH_LINKARMED;
+ dd->ipath_flags &=
+ ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
+ IPATH_LINKACTIVE | IPATH_NOCABLE);
+ *dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+ | IPATH_STATUS_IB_READY);
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ } else {
+ if (!noprint)
+ ipath_dbg("IBstatuschange unit %u: %s (%x)\n",
+ dd->ipath_unit,
+ ipath_ibcstatus_str[ltstate], ltstate);
+ }
+skip_ibchange:
+ dd->ipath_lastibcstat = val;
+}
+
+static void handle_supp_msgs(struct ipath_devdata *dd,
+ unsigned supp_msgs, char msg[512])
+{
+ /*
+ * Print the message unless it's ibc status change only, which
+ * happens so often we never want to count it.
+ */
+ if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
+ ipath_decode_err(msg, sizeof msg, dd->ipath_lasterror &
+ ~INFINIPATH_E_IBSTATUSCHANGED);
+ if (dd->ipath_lasterror &
+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+ ipath_dev_err(dd, "Suppressed %u messages for "
+ "fast-repeating errors (%s) (%llx)\n",
+ supp_msgs, msg,
+ (unsigned long long)
+ dd->ipath_lasterror);
+ else {
+ /*
+ * rcvegrfull and rcvhdrqfull are "normal", for some
+ * types of processes (mostly benchmarks) that send
+ * huge numbers of messages, while not processing
+ * them. So only complain about these at debug
+ * level.
+ */
+ ipath_dbg("Suppressed %u messages for %s\n",
+ supp_msgs, msg);
+ }
+ }
+}
+
+static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+ ipath_err_t errs, char msg[512],
+ int *noprint)
+{
+ unsigned long nc;
+ static unsigned long nextmsg_time;
+ static unsigned nmsgs, supp_msgs;
+
+ /*
+ * Throttle back "fast" messages to no more than 10 per 5 seconds.
+ * This isn't perfect, but it's a reasonable heuristic. If we get
+ * more than 10, give a 6x longer delay.
+ */
+ nc = jiffies;
+ if (nmsgs > 10) {
+ if (time_before(nc, nextmsg_time)) {
+ *noprint = 1;
+ if (!supp_msgs++)
+ nextmsg_time = nc + HZ * 3;
+ }
+ else if (supp_msgs) {
+ handle_supp_msgs(dd, supp_msgs, msg);
+ supp_msgs = 0;
+ nmsgs = 0;
+ }
+ }
+ else if (!nmsgs++ || time_after(nc, nextmsg_time))
+ nextmsg_time = nc + HZ / 2;
+
+ return supp_msgs;
+}
+
+static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+{
+ char msg[512];
+ u64 ignore_this_time = 0;
+ int i;
+ int chkerrpkts = 0, noprint = 0;
+ unsigned supp_msgs;
+
+ supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
+
+ /*
+ * don't report errors that are masked (includes those always
+ * ignored)
+ */
+ errs &= ~dd->ipath_maskederrs;
+
+ /* do these first, they are most important */
+ if (errs & INFINIPATH_E_HARDWARE) {
+ /* reuse same msg buf */
+ dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
+ }
+
+ if (!noprint && (errs & ~infinipath_e_bitsextant))
+ ipath_dev_err(dd, "error interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+ (errs & ~infinipath_e_bitsextant));
+
+ if (errs & E_SUM_ERRS)
+ ignore_this_time = handle_e_sum_errs(dd, errs);
+
+ if (supp_msgs == 250000) {
+ /*
+ * It's not entirely reasonable assuming that the errors set
+ * in the last clear period are all responsible for the
+ * problem, but the alternative is to assume it's the only
+ * ones on this particular interrupt, which also isn't great
+ */
+ dd->ipath_maskederrs |= dd->ipath_lasterror | errs;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ ipath_decode_err(msg, sizeof msg,
+ (dd->ipath_maskederrs & ~dd->
+ ipath_ignorederrs));
+
+ if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+ ipath_dev_err(dd, "Disabling error(s) %llx because "
+ "occuring too frequently (%s)\n",
+ (unsigned long long)
+ (dd->ipath_maskederrs &
+ ~dd->ipath_ignorederrs), msg);
+ else {
+ /*
+ * rcvegrfull and rcvhdrqfull are "normal",
+ * for some types of processes (mostly benchmarks)
+ * that send huge numbers of messages, while not
+ * processing them. So only complain about
+ * these at debug level.
+ */
+ ipath_dbg("Disabling frequent queue full errors "
+ "(%s)\n", msg);
+ }
+
+ /*
+ * Re-enable the masked errors after around 3 minutes. in
+ * ipath_get_faststats(). If we have a series of fast
+ * repeating but different errors, the interval will keep
+ * stretching out, but that's OK, as that's pretty
+ * catastrophic.
+ */
+ dd->ipath_unmasktime = jiffies + HZ * 180;
+ }
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, errs);
+ if (ignore_this_time)
+ errs &= ~ignore_this_time;
+ if (errs & ~dd->ipath_lasterror) {
+ errs &= ~dd->ipath_lasterror;
+ /* never suppress duplicate hwerrors or ibstatuschange */
+ dd->ipath_lasterror |= errs &
+ ~(INFINIPATH_E_HARDWARE |
+ INFINIPATH_E_IBSTATUSCHANGED);
+ }
+ if (!errs)
+ return;
+
+ if (!noprint)
+ /*
+ * the ones we mask off are handled specially below or above
+ */
+ ipath_decode_err(msg, sizeof msg,
+ errs & ~(INFINIPATH_E_IBSTATUSCHANGED |
+ INFINIPATH_E_RRCVEGRFULL |
+ INFINIPATH_E_RRCVHDRFULL |
+ INFINIPATH_E_HARDWARE));
+ else
+ /* so we don't need if (!noprint) at strlcat's below */
+ *msg = 0;
+
+ if (errs & E_SUM_PKTERRS) {
+ ipath_stats.sps_pkterrs++;
+ chkerrpkts = 1;
+ }
+ if (errs & E_SUM_ERRS)
+ ipath_stats.sps_errs++;
+
+ if (errs & (INFINIPATH_E_RICRC | INFINIPATH_E_RVCRC)) {
+ ipath_stats.sps_crcerrs++;
+ chkerrpkts = 1;
+ }
+
+ /*
+ * We don't want to print these two as they happen, or we can make
+ * the situation even worse, because it takes so long to print
+ * messages to serial consoles. Kernel ports get printed from
+ * fast_stats, no more than every 5 seconds, user ports get printed
+ * on close
+ */
+ if (errs & INFINIPATH_E_RRCVHDRFULL) {
+ int any;
+ u32 hd, tl;
+ ipath_stats.sps_hdrqfull++;
+ for (any = i = 0; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+ if (i == 0) {
+ hd = dd->ipath_port0head;
+ tl = (u32) le64_to_cpu(
+ *dd->ipath_hdrqtailptr);
+ } else if (pd && pd->port_cnt &&
+ pd->port_rcvhdrtail_kvaddr) {
+ /*
+ * don't report same point multiple times,
+ * except kernel
+ */
+ tl = (u32) * pd->port_rcvhdrtail_kvaddr;
+ if (tl == dd->ipath_lastrcvhdrqtails[i])
+ continue;
+ hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
+ i);
+ } else
+ continue;
+ if (hd == (tl + 1) ||
+ (!hd && tl == dd->ipath_hdrqlast)) {
+ dd->ipath_lastrcvhdrqtails[i] = tl;
+ pd->port_hdrqfull++;
+ if (i == 0)
+ chkerrpkts = 1;
+ }
+ }
+ }
+ if (errs & INFINIPATH_E_RRCVEGRFULL) {
+ /*
+ * since this is of less importance and not likely to
+ * happen without also getting hdrfull, only count
+ * occurrences; don't check each port (or even the kernel
+ * vs user)
+ */
+ ipath_stats.sps_etidfull++;
+ if (dd->ipath_port0head !=
+ (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
+ chkerrpkts = 1;
+ }
+
+ /*
+ * do this before IBSTATUSCHANGED, in case both bits set in a single
+ * interrupt; we want the STATUSCHANGE to "win", so we do our
+ * internal copy of state machine correctly
+ */
+ if (errs & INFINIPATH_E_RIBLOSTLINK) {
+ /*
+ * force through block below
+ */
+ errs |= INFINIPATH_E_IBSTATUSCHANGED;
+ ipath_stats.sps_iblink++;
+ dd->ipath_flags |= IPATH_LINKDOWN;
+ dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+ | IPATH_LINKARMED | IPATH_LINKACTIVE);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ if (!noprint) {
+ u64 st = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_ibcstatus);
+
+ ipath_dbg("Lost link, link now down (%s)\n",
+ ipath_ibcstatus_str[st & 0xf]);
+ }
+ }
+ if (errs & INFINIPATH_E_IBSTATUSCHANGED)
+ handle_e_ibstatuschanged(dd, errs, noprint);
+
+ if (errs & INFINIPATH_E_RESET) {
+ if (!noprint)
+ ipath_dev_err(dd, "Got reset, requires re-init "
+ "(unload and reload driver)\n");
+ dd->ipath_flags &= ~IPATH_INITTED; /* needs re-init */
+ /* mark as having had error */
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_CONF;
+ }
+
+ if (!noprint && *msg)
+ ipath_dev_err(dd, "%s error\n", msg);
+ if (dd->ipath_sma_state_wanted & dd->ipath_flags) {
+ ipath_cdbg(VERBOSE, "sma wanted state %x, iflags now %x, "
+ "waking\n", dd->ipath_sma_state_wanted,
+ dd->ipath_flags);
+ wake_up_interruptible(&ipath_sma_state_wait);
+ }
+
+ if (chkerrpkts)
+ /* process possible error packets in hdrq */
+ ipath_kreceive(dd);
+}
+
+/* this is separate to allow for better optimization of ipath_intr() */
+
+static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
+{
+ /*
+ * sometimes happen during driver init and unload, don't want
+ * to process any interrupts at that point
+ */
+
+ /* this is just a bandaid, not a fix, if something goes badly
+ * wrong */
+ if (++*unexpectp > 100) {
+ if (++*unexpectp > 105) {
+ /*
+ * ok, we must be taking somebody else's interrupts,
+ * due to a messed up mptable and/or PIRQ table, so
+ * unregister the interrupt. We've seen this during
+ * linuxbios development work, and it may happen in
+ * the future again.
+ */
+ if (dd->pcidev && dd->pcidev->irq) {
+ ipath_dev_err(dd, "Now %u unexpected "
+ "interrupts, unregistering "
+ "interrupt handler\n",
+ *unexpectp);
+ ipath_dbg("free_irq of irq %x\n",
+ dd->pcidev->irq);
+ free_irq(dd->pcidev->irq, dd);
+ }
+ }
+ if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
+ ipath_dev_err(dd, "%u unexpected interrupts, "
+ "disabling interrupts completely\n",
+ *unexpectp);
+ /*
+ * disable all interrupts, something is very wrong
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask,
+ 0ULL);
+ }
+ } else if (*unexpectp > 1)
+ ipath_dbg("Interrupt when not ready, should not happen, "
+ "ignoring\n");
+}
+
+static void ipath_bad_regread(struct ipath_devdata *dd)
+{
+ static int allbits;
+
+ /* separate routine, for better optimization of ipath_intr() */
+
+ /*
+ * We print the message and disable interrupts, in hope of
+ * having a better chance of debugging the problem.
+ */
+ ipath_dev_err(dd,
+ "Read of interrupt status failed (all bits set)\n");
+ if (allbits++) {
+ /* disable all interrupts, something is very wrong */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+ if (allbits == 2) {
+ ipath_dev_err(dd, "Still bad interrupt status, "
+ "unregistering interrupt\n");
+ free_irq(dd->pcidev->irq, dd);
+ } else if (allbits > 2) {
+ if ((allbits % 10000) == 0)
+ printk(".");
+ } else
+ ipath_dev_err(dd, "Disabling interrupts, "
+ "multiple errors\n");
+ }
+}
+
+static void handle_port_pioavail(struct ipath_devdata *dd)
+{
+ u32 i;
+ /*
+ * start from port 1, since for now port 0 is never using
+ * wait_event for PIO
+ */
+ for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+
+ if (pd && pd->port_cnt &&
+ dd->ipath_portpiowait & (1U << i)) {
+ clear_bit(i, &dd->ipath_portpiowait);
+ if (test_bit(IPATH_PORT_WAITING_PIO,
+ &pd->port_flag)) {
+ clear_bit(IPATH_PORT_WAITING_PIO,
+ &pd->port_flag);
+ wake_up_interruptible(&pd->port_wait);
+ }
+ }
+ }
+}
+
+static void handle_layer_pioavail(struct ipath_devdata *dd)
+{
+ int ret;
+
+ ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
+ if (ret > 0)
+ goto clear;
+
+ ret = __ipath_verbs_piobufavail(dd);
+ if (ret > 0)
+ goto clear;
+
+ return;
+clear:
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+}
+
+static void handle_rcv(struct ipath_devdata *dd, u32 istat)
+{
+ u64 portr;
+ int i;
+ int rcvdint = 0;
+
+ portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+ infinipath_i_rcvavail_mask)
+ | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
+ infinipath_i_rcvurg_mask);
+ for (i = 0; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+ if (portr & (1 << i) && pd &&
+ pd->port_cnt) {
+ if (i == 0)
+ ipath_kreceive(dd);
+ else if (test_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag)) {
+ int rcbit;
+ clear_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag);
+ rcbit = i + INFINIPATH_R_INTRAVAIL_SHIFT;
+ clear_bit(1UL << rcbit, &dd->ipath_rcvctrl);
+ wake_up_interruptible(&pd->port_wait);
+ rcvdint = 1;
+ }
+ }
+ }
+ if (rcvdint) {
+ /* only want to take one interrupt, so turn off the rcv
+ * interrupt for all the ports that we did the wakeup on
+ * (but never for kernel port)
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+ }
+}
+
+irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
+{
+ struct ipath_devdata *dd = data;
+ u32 istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
+ ipath_err_t estat = 0;
+ static unsigned unexpected = 0;
+ irqreturn_t ret;
+
+ if (unlikely(!istat)) {
+ ipath_stats.sps_nullintr++;
+ ret = IRQ_NONE; /* not our interrupt, or already handled */
+ goto bail;
+ }
+ if (unlikely(istat == -1)) {
+ ipath_bad_regread(dd);
+ /* don't know if it was our interrupt or not */
+ ret = IRQ_NONE;
+ goto bail;
+ }
+
+ ipath_stats.sps_ints++;
+
+ /*
+ * this needs to be flags&initted, not statusp, so we keep
+ * taking interrupts even after link goes down, etc.
+ * Also, we *must* clear the interrupt at some point, or we won't
+ * take it again, which can be real bad for errors, etc...
+ */
+
+ if (!(dd->ipath_flags & IPATH_INITTED)) {
+ ipath_bad_intr(dd, &unexpected);
+ ret = IRQ_NONE;
+ goto bail;
+ }
+ if (unexpected)
+ unexpected = 0;
+
+ ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
+
+ if (istat & ~infinipath_i_bitsextant)
+ ipath_dev_err(dd,
+ "interrupt with unknown interrupts %x set\n",
+ istat & (u32) ~ infinipath_i_bitsextant);
+
+ if (istat & INFINIPATH_I_ERROR) {
+ ipath_stats.sps_errints++;
+ estat = ipath_read_kreg64(dd,
+ dd->ipath_kregs->kr_errorstatus);
+ if (!estat)
+ dev_info(&dd->pcidev->dev, "error interrupt (%x), "
+ "but no error bits set!\n", istat);
+ else if (estat == -1LL)
+ /*
+ * should we try clearing all, or hope next read
+ * works?
+ */
+ ipath_dev_err(dd, "Read of error status failed "
+ "(all bits set); ignoring\n");
+ else
+ handle_errors(dd, estat);
+ }
+
+ if (istat & INFINIPATH_I_GPIO) {
+ if (unlikely(!(dd->ipath_flags & IPATH_GPIO_INTR))) {
+ u32 gpiostatus;
+ gpiostatus = ipath_read_kreg32(
+ dd, dd->ipath_kregs->kr_gpio_status);
+ ipath_dbg("Unexpected GPIO interrupt bits %x\n",
+ gpiostatus);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+ gpiostatus);
+ }
+ else {
+ /* Clear GPIO status bit 2 */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+ (u64) (1 << 2));
+
+ /*
+ * Packets are available in the port 0 rcv queue.
+ * Eventually this needs to be generalized to check
+ * IPATH_GPIO_INTR, and the specific GPIO bit, if
+ * GPIO interrupts are used for anything else.
+ */
+ ipath_kreceive(dd);
+ }
+ }
+
+ /*
+ * clear the ones we will deal with on this round
+ * We clear it early, mostly for receive interrupts, so we
+ * know the chip will have seen this by the time we process
+ * the queue, and will re-interrupt if necessary. The processor
+ * itself won't take the interrupt again until we return.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat);
+
+ if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+ clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ if (dd->ipath_portpiowait)
+ handle_port_pioavail(dd);
+
+ handle_layer_pioavail(dd);
+ }
+
+ /*
+ * we check for both transition from empty to non-empty, and urgent
+ * packets (those with the interrupt bit set in the header)
+ */
+
+ if (istat & ((infinipath_i_rcvavail_mask <<
+ INFINIPATH_I_RCVAVAIL_SHIFT)
+ | (infinipath_i_rcvurg_mask <<
+ INFINIPATH_I_RCVURG_SHIFT)))
+ handle_rcv(dd, istat);
+
+ ret = IRQ_HANDLED;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
new file mode 100644
index 000000000000..0ce5f19c9d62
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -0,0 +1,883 @@
+#ifndef _IPATH_KERNEL_H
+#define _IPATH_KERNEL_H
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This header file is the base header file for infinipath kernel code
+ * ipath_user.h serves a similar purpose for user code.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "ipath_common.h"
+#include "ipath_debug.h"
+#include "ipath_registers.h"
+
+/* only s/w major version of InfiniPath we can handle */
+#define IPATH_CHIP_VERS_MAJ 2U
+
+/* don't care about this except printing */
+#define IPATH_CHIP_VERS_MIN 0U
+
+/* temporary, maybe always */
+extern struct infinipath_stats ipath_stats;
+
+#define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+
+struct ipath_portdata {
+ void **port_rcvegrbuf;
+ dma_addr_t *port_rcvegrbuf_phys;
+ /* rcvhdrq base, needs mmap before useful */
+ void *port_rcvhdrq;
+ /* kernel virtual address where hdrqtail is updated */
+ u64 *port_rcvhdrtail_kvaddr;
+ /* page * used for uaddr */
+ struct page *port_rcvhdrtail_pagep;
+ /*
+ * temp buffer for expected send setup, allocated at open, instead
+ * of each setup call
+ */
+ void *port_tid_pg_list;
+ /* when waiting for rcv or pioavail */
+ wait_queue_head_t port_wait;
+ /*
+ * rcvegr bufs base, physical, must fit
+ * in 44 bits so 32 bit programs mmap64 44 bit works)
+ */
+ dma_addr_t port_rcvegr_phys;
+ /* mmap of hdrq, must fit in 44 bits */
+ dma_addr_t port_rcvhdrq_phys;
+ /*
+ * the actual user address that we ipath_mlock'ed, so we can
+ * ipath_munlock it at close
+ */
+ unsigned long port_rcvhdrtail_uaddr;
+ /*
+ * number of opens on this instance (0 or 1; ignoring forks, dup,
+ * etc. for now)
+ */
+ int port_cnt;
+ /*
+ * how much space to leave at start of eager TID entries for
+ * protocol use, on each TID
+ */
+ /* instead of calculating it */
+ unsigned port_port;
+ /* chip offset of PIO buffers for this port */
+ u32 port_piobufs;
+ /* how many alloc_pages() chunks in port_rcvegrbuf_pages */
+ u32 port_rcvegrbuf_chunks;
+ /* how many egrbufs per chunk */
+ u32 port_rcvegrbufs_perchunk;
+ /* order for port_rcvegrbuf_pages */
+ size_t port_rcvegrbuf_size;
+ /* rcvhdrq size (for freeing) */
+ size_t port_rcvhdrq_size;
+ /* next expected TID to check when looking for free */
+ u32 port_tidcursor;
+ /* next expected TID to check */
+ unsigned long port_flag;
+ /* WAIT_RCV that timed out, no interrupt */
+ u32 port_rcvwait_to;
+ /* WAIT_PIO that timed out, no interrupt */
+ u32 port_piowait_to;
+ /* WAIT_RCV already happened, no wait */
+ u32 port_rcvnowait;
+ /* WAIT_PIO already happened, no wait */
+ u32 port_pionowait;
+ /* total number of rcvhdrqfull errors */
+ u32 port_hdrqfull;
+ /* pid of process using this port */
+ pid_t port_pid;
+ /* same size as task_struct .comm[] */
+ char port_comm[16];
+ /* pkeys set by this use of this port */
+ u16 port_pkeys[4];
+ /* so file ops can get at unit */
+ struct ipath_devdata *port_dd;
+};
+
+struct sk_buff;
+
+/*
+ * control information for layered drivers
+ */
+struct _ipath_layer {
+ void *l_arg;
+};
+
+/* Verbs layer interface */
+struct _verbs_layer {
+ void *l_arg;
+ struct timer_list l_timer;
+};
+
+struct ipath_devdata {
+ struct list_head ipath_list;
+
+ struct ipath_kregs const *ipath_kregs;
+ struct ipath_cregs const *ipath_cregs;
+
+ /* mem-mapped pointer to base of chip regs */
+ u64 __iomem *ipath_kregbase;
+ /* end of mem-mapped chip space; range checking */
+ u64 __iomem *ipath_kregend;
+ /* physical address of chip for io_remap, etc. */
+ unsigned long ipath_physaddr;
+ /* base of memory alloced for ipath_kregbase, for free */
+ u64 *ipath_kregalloc;
+ /*
+ * version of kregbase that doesn't have high bits set (for 32 bit
+ * programs, so mmap64 44 bit works)
+ */
+ u64 __iomem *ipath_kregvirt;
+ /*
+ * virtual address where port0 rcvhdrqtail updated for this unit.
+ * only written to by the chip, not the driver.
+ */
+ volatile __le64 *ipath_hdrqtailptr;
+ dma_addr_t ipath_dma_addr;
+ /* ipath_cfgports pointers */
+ struct ipath_portdata **ipath_pd;
+ /* sk_buffs used by port 0 eager receive queue */
+ struct sk_buff **ipath_port0_skbs;
+ /* kvirt address of 1st 2k pio buffer */
+ void __iomem *ipath_pio2kbase;
+ /* kvirt address of 1st 4k pio buffer */
+ void __iomem *ipath_pio4kbase;
+ /*
+ * points to area where PIOavail registers will be DMA'ed.
+ * Has to be on a page of it's own, because the page will be
+ * mapped into user program space. This copy is *ONLY* ever
+ * written by DMA, not by the driver! Need a copy per device
+ * when we get to multiple devices
+ */
+ volatile __le64 *ipath_pioavailregs_dma;
+ /* physical address where updates occur */
+ dma_addr_t ipath_pioavailregs_phys;
+ struct _ipath_layer ipath_layer;
+ /* setup intr */
+ int (*ipath_f_intrsetup)(struct ipath_devdata *);
+ /* setup on-chip bus config */
+ int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
+ /* hard reset chip */
+ int (*ipath_f_reset)(struct ipath_devdata *);
+ int (*ipath_f_get_boardname)(struct ipath_devdata *, char *,
+ size_t);
+ void (*ipath_f_init_hwerrors)(struct ipath_devdata *);
+ void (*ipath_f_handle_hwerrors)(struct ipath_devdata *, char *,
+ size_t);
+ void (*ipath_f_quiet_serdes)(struct ipath_devdata *);
+ int (*ipath_f_bringup_serdes)(struct ipath_devdata *);
+ int (*ipath_f_early_init)(struct ipath_devdata *);
+ void (*ipath_f_clear_tids)(struct ipath_devdata *, unsigned);
+ void (*ipath_f_put_tid)(struct ipath_devdata *, u64 __iomem*,
+ u32, unsigned long);
+ void (*ipath_f_tidtemplate)(struct ipath_devdata *);
+ void (*ipath_f_cleanup)(struct ipath_devdata *);
+ void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64);
+ /* fill out chip-specific fields */
+ int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
+ struct _verbs_layer verbs_layer;
+ /* total dwords sent (summed from counter) */
+ u64 ipath_sword;
+ /* total dwords rcvd (summed from counter) */
+ u64 ipath_rword;
+ /* total packets sent (summed from counter) */
+ u64 ipath_spkts;
+ /* total packets rcvd (summed from counter) */
+ u64 ipath_rpkts;
+ /* ipath_statusp initially points to this. */
+ u64 _ipath_status;
+ /* GUID for this interface, in network order */
+ __be64 ipath_guid;
+ /*
+ * aggregrate of error bits reported since last cleared, for
+ * limiting of error reporting
+ */
+ ipath_err_t ipath_lasterror;
+ /*
+ * aggregrate of error bits reported since last cleared, for
+ * limiting of hwerror reporting
+ */
+ ipath_err_t ipath_lasthwerror;
+ /*
+ * errors masked because they occur too fast, also includes errors
+ * that are always ignored (ipath_ignorederrs)
+ */
+ ipath_err_t ipath_maskederrs;
+ /* time in jiffies at which to re-enable maskederrs */
+ unsigned long ipath_unmasktime;
+ /*
+ * errors always ignored (masked), at least for a given
+ * chip/device, because they are wrong or not useful
+ */
+ ipath_err_t ipath_ignorederrs;
+ /* count of egrfull errors, combined for all ports */
+ u64 ipath_last_tidfull;
+ /* for ipath_qcheck() */
+ u64 ipath_lastport0rcv_cnt;
+ /* template for writing TIDs */
+ u64 ipath_tidtemplate;
+ /* value to write to free TIDs */
+ u64 ipath_tidinvalid;
+ /* PE-800 rcv interrupt setup */
+ u64 ipath_rhdrhead_intr_off;
+
+ /* size of memory at ipath_kregbase */
+ u32 ipath_kregsize;
+ /* number of registers used for pioavail */
+ u32 ipath_pioavregs;
+ /* IPATH_POLL, etc. */
+ u32 ipath_flags;
+ /* ipath_flags sma is waiting for */
+ u32 ipath_sma_state_wanted;
+ /* last buffer for user use, first buf for kernel use is this
+ * index. */
+ u32 ipath_lastport_piobuf;
+ /* is a stats timer active */
+ u32 ipath_stats_timer_active;
+ /* dwords sent read from counter */
+ u32 ipath_lastsword;
+ /* dwords received read from counter */
+ u32 ipath_lastrword;
+ /* sent packets read from counter */
+ u32 ipath_lastspkts;
+ /* received packets read from counter */
+ u32 ipath_lastrpkts;
+ /* pio bufs allocated per port */
+ u32 ipath_pbufsport;
+ /*
+ * number of ports configured as max; zero is set to number chip
+ * supports, less gives more pio bufs/port, etc.
+ */
+ u32 ipath_cfgports;
+ /* port0 rcvhdrq head offset */
+ u32 ipath_port0head;
+ /* count of port 0 hdrqfull errors */
+ u32 ipath_p0_hdrqfull;
+
+ /*
+ * (*cfgports) used to suppress multiple instances of same
+ * port staying stuck at same point
+ */
+ u32 *ipath_lastrcvhdrqtails;
+ /*
+ * (*cfgports) used to suppress multiple instances of same
+ * port staying stuck at same point
+ */
+ u32 *ipath_lastegrheads;
+ /*
+ * index of last piobuffer we used. Speeds up searching, by
+ * starting at this point. Doesn't matter if multiple cpu's use and
+ * update, last updater is only write that matters. Whenever it
+ * wraps, we update shadow copies. Need a copy per device when we
+ * get to multiple devices
+ */
+ u32 ipath_lastpioindex;
+ /* max length of freezemsg */
+ u32 ipath_freezelen;
+ /*
+ * consecutive times we wanted a PIO buffer but were unable to
+ * get one
+ */
+ u32 ipath_consec_nopiobuf;
+ /*
+ * hint that we should update ipath_pioavailshadow before
+ * looking for a PIO buffer
+ */
+ u32 ipath_upd_pio_shadow;
+ /* so we can rewrite it after a chip reset */
+ u32 ipath_pcibar0;
+ /* so we can rewrite it after a chip reset */
+ u32 ipath_pcibar1;
+ /* sequential tries for SMA send and no bufs */
+ u32 ipath_nosma_bufs;
+ /* duration (seconds) ipath_nosma_bufs set */
+ u32 ipath_nosma_secs;
+
+ /* HT/PCI Vendor ID (here for NodeInfo) */
+ u16 ipath_vendorid;
+ /* HT/PCI Device ID (here for NodeInfo) */
+ u16 ipath_deviceid;
+ /* offset in HT config space of slave/primary interface block */
+ u8 ipath_ht_slave_off;
+ /* for write combining settings */
+ unsigned long ipath_wc_cookie;
+ /* ref count for each pkey */
+ atomic_t ipath_pkeyrefs[4];
+ /* shadow copy of all exptids physaddr; used only by funcsim */
+ u64 *ipath_tidsimshadow;
+ /* shadow copy of struct page *'s for exp tid pages */
+ struct page **ipath_pageshadow;
+ /* lock to workaround chip bug 9437 */
+ spinlock_t ipath_tid_lock;
+
+ /*
+ * IPATH_STATUS_*,
+ * this address is mapped readonly into user processes so they can
+ * get status cheaply, whenever they want.
+ */
+ u64 *ipath_statusp;
+ /* freeze msg if hw error put chip in freeze */
+ char *ipath_freezemsg;
+ /* pci access data structure */
+ struct pci_dev *pcidev;
+ struct cdev *cdev;
+ struct class_device *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;
+
+ /*
+ * Shadow copies of registers; size indicates read access size.
+ * Most of them are readonly, but some are write-only register,
+ * where we manipulate the bits in the shadow copy, and then write
+ * the shadow copy to infinipath.
+ *
+ * We deliberately make most of these 32 bits, since they have
+ * restricted range. For any that we read, we won't to generate 32
+ * bit accesses, since Opteron will generate 2 separate 32 bit HT
+ * transactions for a 64 bit read, and we want to avoid unnecessary
+ * HT transactions.
+ */
+
+ /* This is the 64 bit group */
+
+ /*
+ * shadow of pioavail, check to be sure it's large enough at
+ * init time.
+ */
+ unsigned long ipath_pioavailshadow[8];
+ /* shadow of kr_gpio_out, for rmw ops */
+ u64 ipath_gpio_out;
+ /* kr_revision shadow */
+ u64 ipath_revision;
+ /*
+ * shadow of ibcctrl, for interrupt handling of link changes,
+ * etc.
+ */
+ u64 ipath_ibcctrl;
+ /*
+ * last ibcstatus, to suppress "duplicate" status change messages,
+ * mostly from 2 to 3
+ */
+ u64 ipath_lastibcstat;
+ /* hwerrmask shadow */
+ ipath_err_t ipath_hwerrmask;
+ /* interrupt config reg shadow */
+ u64 ipath_intconfig;
+ /* kr_sendpiobufbase value */
+ u64 ipath_piobufbase;
+
+ /* these are the "32 bit" regs */
+
+ /*
+ * number of GUIDs in the flash for this interface; may need some
+ * rethinking for setting on other ifaces
+ */
+ u32 ipath_nguid;
+ /*
+ * the following two are 32-bit bitmasks, but {test,clear,set}_bit
+ * all expect bit fields to be "unsigned long"
+ */
+ /* shadow kr_rcvctrl */
+ unsigned long ipath_rcvctrl;
+ /* shadow kr_sendctrl */
+ unsigned long ipath_sendctrl;
+
+ /* value we put in kr_rcvhdrcnt */
+ u32 ipath_rcvhdrcnt;
+ /* value we put in kr_rcvhdrsize */
+ u32 ipath_rcvhdrsize;
+ /* value we put in kr_rcvhdrentsize */
+ u32 ipath_rcvhdrentsize;
+ /* offset of last entry in rcvhdrq */
+ u32 ipath_hdrqlast;
+ /* kr_portcnt value */
+ u32 ipath_portcnt;
+ /* kr_pagealign value */
+ u32 ipath_palign;
+ /* number of "2KB" PIO buffers */
+ u32 ipath_piobcnt2k;
+ /* size in bytes of "2KB" PIO buffers */
+ u32 ipath_piosize2k;
+ /* number of "4KB" PIO buffers */
+ u32 ipath_piobcnt4k;
+ /* size in bytes of "4KB" PIO buffers */
+ u32 ipath_piosize4k;
+ /* kr_rcvegrbase value */
+ u32 ipath_rcvegrbase;
+ /* kr_rcvegrcnt value */
+ u32 ipath_rcvegrcnt;
+ /* kr_rcvtidbase value */
+ u32 ipath_rcvtidbase;
+ /* kr_rcvtidcnt value */
+ u32 ipath_rcvtidcnt;
+ /* kr_sendregbase */
+ u32 ipath_sregbase;
+ /* kr_userregbase */
+ u32 ipath_uregbase;
+ /* kr_counterregbase */
+ 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;
+
+ /* chip address space used by 4k pio buffers */
+ u32 ipath_4kalign;
+ /* The MTU programmed for this unit */
+ u32 ipath_ibmtu;
+ /*
+ * The max size IB packet, included IB headers that we can send.
+ * Starts same as ipath_piosize, but is affected when ibmtu is
+ * changed, or by size of eager buffers
+ */
+ u32 ipath_ibmaxlen;
+ /*
+ * ibmaxlen at init time, limited by chip and by receive buffer
+ * size. Not changed after init.
+ */
+ u32 ipath_init_ibmaxlen;
+ /* size of each rcvegrbuffer */
+ u32 ipath_rcvegrbufsize;
+ /* width (2,4,8,16,32) from HT config reg */
+ u32 ipath_htwidth;
+ /* HT speed (200,400,800,1000) from HT config */
+ u32 ipath_htspeed;
+ /* ports waiting for PIOavail intr */
+ unsigned long ipath_portpiowait;
+ /*
+ * number of sequential ibcstatus change for polling active/quiet
+ * (i.e., link not coming up).
+ */
+ u32 ipath_ibpollcnt;
+ /* low and high portions of MSI capability/vector */
+ u32 ipath_msi_lo;
+ /* saved after PCIe init for restore after reset */
+ u32 ipath_msi_hi;
+ /* MSI data (vector) saved for restore */
+ u16 ipath_msi_data;
+ /* MLID programmed for this instance */
+ u16 ipath_mlid;
+ /* LID programmed for this instance */
+ u16 ipath_lid;
+ /* list of pkeys programmed; 0 if not set */
+ u16 ipath_pkeys[4];
+ /* ASCII serial number, from flash */
+ u8 ipath_serial[12];
+ /* human readable board version */
+ u8 ipath_boardversion[80];
+ /* chip major rev, from ipath_revision */
+ u8 ipath_majrev;
+ /* chip minor rev, from ipath_revision */
+ u8 ipath_minrev;
+ /* board rev, from ipath_revision */
+ u8 ipath_boardrev;
+ /* unit # of this chip, if present */
+ int ipath_unit;
+ /* saved for restore after reset */
+ u8 ipath_pci_cacheline;
+ /* LID mask control */
+ u8 ipath_lmc;
+};
+
+extern volatile __le64 *ipath_port0_rcvhdrtail;
+extern dma_addr_t ipath_port0_rcvhdrtail_dma;
+
+#define IPATH_PORT0_RCVHDRTAIL_SIZE PAGE_SIZE
+
+extern struct list_head ipath_dev_list;
+extern spinlock_t ipath_devs_lock;
+extern struct ipath_devdata *ipath_lookup(int unit);
+
+extern u16 ipath_layer_rcv_opcode;
+extern int __ipath_layer_intr(struct ipath_devdata *, u32);
+extern int ipath_layer_intr(struct ipath_devdata *, u32);
+extern int __ipath_layer_rcv(struct ipath_devdata *, void *,
+ struct sk_buff *);
+extern int __ipath_layer_rcv_lid(struct ipath_devdata *, void *);
+extern int __ipath_verbs_piobufavail(struct ipath_devdata *);
+extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32);
+
+void ipath_layer_add(struct ipath_devdata *);
+void ipath_layer_del(struct ipath_devdata *);
+
+int ipath_init_chip(struct ipath_devdata *, int);
+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 *);
+
+struct file_operations;
+int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+ struct cdev **cdevp, struct class_device **class_devp);
+void ipath_cdev_cleanup(struct cdev **cdevp,
+ struct class_device **class_devp);
+
+int ipath_diag_init(void);
+void ipath_diag_cleanup(void);
+void ipath_diag_bringup_link(struct ipath_devdata *);
+
+extern wait_queue_head_t ipath_sma_state_wait;
+
+int ipath_user_add(struct ipath_devdata *dd);
+void ipath_user_del(struct ipath_devdata *dd);
+
+struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
+
+extern int ipath_diag_inuse;
+
+irqreturn_t ipath_intr(int irq, void *devid, struct pt_regs *regs);
+void ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
+#if __IPATH_INFO || __IPATH_DBG
+extern const char *ipath_ibcstatus_str[];
+#endif
+
+/* clean up any per-chip chip-specific stuff */
+void ipath_chip_cleanup(struct ipath_devdata *);
+/* clean up any chip type-specific stuff */
+void ipath_chip_done(void);
+
+/* check to see if we have to force ordering for write combining */
+int ipath_unordered_wc(void);
+
+void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
+ unsigned cnt);
+
+int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
+void ipath_free_pddata(struct ipath_devdata *, u32, int);
+
+int ipath_parse_ushort(const char *str, unsigned short *valp);
+
+int ipath_wait_linkstate(struct ipath_devdata *, u32, int);
+void ipath_set_ib_lstate(struct ipath_devdata *, int);
+void ipath_kreceive(struct ipath_devdata *);
+int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
+int ipath_reset_device(int);
+void ipath_get_faststats(unsigned long);
+
+/* for use in system calls, where we want to know device type, etc. */
+#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
+
+/*
+ * values for ipath_flags
+ */
+/* The chip is up and initted */
+#define IPATH_INITTED 0x2
+ /* set if any user code has set kr_rcvhdrsize */
+#define IPATH_RCVHDRSZ_SET 0x4
+ /* The chip is present and valid for accesses */
+#define IPATH_PRESENT 0x8
+ /* HT link0 is only 8 bits wide, ignore upper byte crc
+ * errors, etc. */
+#define IPATH_8BIT_IN_HT0 0x10
+ /* HT link1 is only 8 bits wide, ignore upper byte crc
+ * errors, etc. */
+#define IPATH_8BIT_IN_HT1 0x20
+ /* The link is down */
+#define IPATH_LINKDOWN 0x40
+ /* The link level is up (0x11) */
+#define IPATH_LINKINIT 0x80
+ /* The link is in the armed (0x21) state */
+#define IPATH_LINKARMED 0x100
+ /* The link is in the active (0x31) state */
+#define IPATH_LINKACTIVE 0x200
+ /* link current state is unknown */
+#define IPATH_LINKUNK 0x400
+ /* no IB cable, or no device on IB cable */
+#define IPATH_NOCABLE 0x4000
+ /* Supports port zero per packet receive interrupts via
+ * GPIO */
+#define IPATH_GPIO_INTR 0x8000
+ /* uses the coded 4byte TID, not 8 byte */
+#define IPATH_4BYTE_TID 0x10000
+ /* packet/word counters are 32 bit, else those 4 counters
+ * are 64bit */
+#define IPATH_32BITCOUNTERS 0x20000
+ /* can miss port0 rx interrupts */
+#define IPATH_POLL_RX_INTR 0x40000
+#define IPATH_DISABLED 0x80000 /* administratively disabled */
+
+/* portdata flag bit offsets */
+ /* waiting for a packet to arrive */
+#define IPATH_PORT_WAITING_RCV 2
+ /* waiting for a PIO buffer to be available */
+#define IPATH_PORT_WAITING_PIO 3
+
+/* free up any allocated data at closes */
+void ipath_free_data(struct ipath_portdata *dd);
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
+int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
+/* init PE-800-specific func */
+void ipath_init_pe800_funcs(struct ipath_devdata *);
+/* init HT-400-specific func */
+void ipath_init_ht400_funcs(struct ipath_devdata *);
+void ipath_get_guid(struct ipath_devdata *);
+u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
+
+/*
+ * number of words used for protocol header if not set by ipath_userinit();
+ */
+#define IPATH_DFLT_RCVHDRSIZE 9
+
+#define IPATH_MDIO_CMD_WRITE 1
+#define IPATH_MDIO_CMD_READ 2
+#define IPATH_MDIO_CLD_DIV 25 /* to get 2.5 Mhz mdio clock */
+#define IPATH_MDIO_CMDVALID 0x40000000 /* bit 30 */
+#define IPATH_MDIO_DATAVALID 0x80000000 /* bit 31 */
+#define IPATH_MDIO_CTRL_STD 0x0
+
+static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
+{
+ return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
+ (cmd << 26) |
+ (dev << 21) |
+ (reg << 16) |
+ (data & 0xFFFF);
+}
+
+ /* signal and fifo status, in bank 31 */
+#define IPATH_MDIO_CTRL_XGXS_REG_8 0x8
+ /* controls loopback, redundancy */
+#define IPATH_MDIO_CTRL_8355_REG_1 0x10
+ /* premph, encdec, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_2 0x11
+ /* Kchars, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_6 0x15
+#define IPATH_MDIO_CTRL_8355_REG_9 0x18
+#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
+
+int ipath_get_user_pages(unsigned long, size_t, struct page **);
+int ipath_get_user_pages_nocopy(unsigned long, struct page **);
+void ipath_release_user_pages(struct page **, size_t);
+void ipath_release_user_pages_on_close(struct page **, size_t);
+int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int);
+int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int);
+
+/* these are used for the registers that vary with port */
+void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+ unsigned, u64);
+u64 ipath_read_kreg64_port(const struct ipath_devdata *, ipath_kreg,
+ unsigned);
+
+/*
+ * We could have a single register get/put routine, that takes a group type,
+ * but this is somewhat clearer and cleaner. It also gives us some error
+ * checking. 64 bit register reads should always work, but are inefficient
+ * on opteron (the northbridge always generates 2 separate HT 32 bit reads),
+ * so we use kreg32 wherever possible. User register and counter register
+ * reads are always 32 bit reads, so only one form of those routines.
+ */
+
+/*
+ * At the moment, none of the s-registers are writable, so no
+ * ipath_write_sreg(), and none of the c-registers are writable, so no
+ * ipath_write_creg().
+ */
+
+/**
+ * ipath_read_ureg32 - read 32-bit virtualized per-port register
+ * @dd: device
+ * @regno: register number
+ * @port: port number
+ *
+ * Return the contents of a register that is virtualized to be per port.
+ * Prints a debug message and returns -1 on errors (not distinguishable from
+ * valid contents at runtime; we may add a separate error variable at some
+ * point).
+ *
+ * This is normally not used by the kernel, but may be for debugging, and
+ * has a different implementation than user mode, which is why it's not in
+ * _common.h.
+ */
+static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
+ ipath_ureg regno, int port)
+{
+ if (!dd->ipath_kregbase)
+ return 0;
+
+ return readl(regno + (u64 __iomem *)
+ (dd->ipath_uregbase +
+ (char __iomem *)dd->ipath_kregbase +
+ dd->ipath_palign * port));
+}
+
+/**
+ * ipath_write_ureg - write 32-bit virtualized per-port register
+ * @dd: device
+ * @regno: register number
+ * @value: value
+ * @port: port
+ *
+ * Write the contents of a register that is virtualized to be per port.
+ */
+static inline void ipath_write_ureg(const struct ipath_devdata *dd,
+ ipath_ureg regno, u64 value, int port)
+{
+ u64 __iomem *ubase = (u64 __iomem *)
+ (dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
+ dd->ipath_palign * port);
+ if (dd->ipath_kregbase)
+ writeq(value, &ubase[regno]);
+}
+
+static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd,
+ ipath_kreg regno)
+{
+ if (!dd->ipath_kregbase)
+ return -1;
+ return readl((u32 __iomem *) & dd->ipath_kregbase[regno]);
+}
+
+static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd,
+ ipath_kreg regno)
+{
+ if (!dd->ipath_kregbase)
+ return -1;
+
+ return readq(&dd->ipath_kregbase[regno]);
+}
+
+static inline void ipath_write_kreg(const struct ipath_devdata *dd,
+ ipath_kreg regno, u64 value)
+{
+ if (dd->ipath_kregbase)
+ writeq(value, &dd->ipath_kregbase[regno]);
+}
+
+static inline u64 ipath_read_creg(const struct ipath_devdata *dd,
+ ipath_sreg regno)
+{
+ if (!dd->ipath_kregbase)
+ return 0;
+
+ return readq(regno + (u64 __iomem *)
+ (dd->ipath_cregbase +
+ (char __iomem *)dd->ipath_kregbase));
+}
+
+static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
+ ipath_sreg regno)
+{
+ if (!dd->ipath_kregbase)
+ return 0;
+ return readl(regno + (u64 __iomem *)
+ (dd->ipath_cregbase +
+ (char __iomem *)dd->ipath_kregbase));
+}
+
+/*
+ * sysfs interface.
+ */
+
+struct device_driver;
+
+extern const char ipath_core_version[];
+
+int ipath_driver_create_group(struct device_driver *);
+void ipath_driver_remove_group(struct device_driver *);
+
+int ipath_device_create_group(struct device *, struct ipath_devdata *);
+void ipath_device_remove_group(struct device *, struct ipath_devdata *);
+int ipath_expose_reset(struct device *);
+
+int ipath_init_ipathfs(void);
+void ipath_exit_ipathfs(void);
+int ipathfs_add_device(struct ipath_devdata *);
+int ipathfs_remove_device(struct ipath_devdata *);
+
+/*
+ * Flush write combining store buffers (if present) and perform a write
+ * barrier.
+ */
+#if defined(CONFIG_X86_64)
+#define ipath_flush_wc() asm volatile("sfence" ::: "memory")
+#else
+#define ipath_flush_wc() wmb()
+#endif
+
+extern unsigned ipath_debug; /* debugging bit mask */
+
+const char *ipath_get_unit_name(int unit);
+
+extern struct mutex ipath_mutex;
+
+#define IPATH_DRV_NAME "ipath_core"
+#define IPATH_MAJOR 233
+#define IPATH_SMA_MINOR 128
+#define IPATH_DIAG_MINOR 129
+#define IPATH_NMINORS 130
+
+#define ipath_dev_err(dd,fmt,...) \
+ do { \
+ const struct ipath_devdata *__dd = (dd); \
+ if (__dd->pcidev) \
+ dev_err(&__dd->pcidev->dev, "%s: " fmt, \
+ ipath_get_unit_name(__dd->ipath_unit), \
+ ##__VA_ARGS__); \
+ else \
+ printk(KERN_ERR IPATH_DRV_NAME ": %s: " fmt, \
+ ipath_get_unit_name(__dd->ipath_unit), \
+ ##__VA_ARGS__); \
+ } while (0)
+
+#if _IPATH_DEBUGGING
+
+# define __IPATH_DBG_WHICH(which,fmt,...) \
+ do { \
+ if(unlikely(ipath_debug&(which))) \
+ printk(KERN_DEBUG IPATH_DRV_NAME ": %s: " fmt, \
+ __func__,##__VA_ARGS__); \
+ } while(0)
+
+# define ipath_dbg(fmt,...) \
+ __IPATH_DBG_WHICH(__IPATH_DBG,fmt,##__VA_ARGS__)
+# define ipath_cdbg(which,fmt,...) \
+ __IPATH_DBG_WHICH(__IPATH_##which##DBG,fmt,##__VA_ARGS__)
+
+#else /* ! _IPATH_DEBUGGING */
+
+# define ipath_dbg(fmt,...)
+# define ipath_cdbg(which,fmt,...)
+
+#endif /* _IPATH_DEBUGGING */
+
+#endif /* _IPATH_KERNEL_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
new file mode 100644
index 000000000000..aa33b0e9f2f6
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <asm/io.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_alloc_lkey - allocate an lkey
+ * @rkt: lkey table in which to allocate the lkey
+ * @mr: memory region that this lkey protects
+ *
+ * Returns 1 if successful, otherwise returns 0.
+ */
+
+int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr)
+{
+ unsigned long flags;
+ u32 r;
+ u32 n;
+ int ret;
+
+ spin_lock_irqsave(&rkt->lock, flags);
+
+ /* Find the next available LKEY */
+ r = n = rkt->next;
+ for (;;) {
+ if (rkt->table[r] == NULL)
+ break;
+ r = (r + 1) & (rkt->max - 1);
+ if (r == n) {
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ _VERBS_INFO("LKEY table full\n");
+ ret = 0;
+ goto bail;
+ }
+ }
+ rkt->next = (r + 1) & (rkt->max - 1);
+ /*
+ * Make sure lkey is never zero which is reserved to indicate an
+ * unrestricted LKEY.
+ */
+ rkt->gen++;
+ mr->lkey = (r << (32 - ib_ipath_lkey_table_size)) |
+ ((((1 << (24 - ib_ipath_lkey_table_size)) - 1) & rkt->gen)
+ << 8);
+ if (mr->lkey == 0) {
+ mr->lkey |= 1 << 8;
+ rkt->gen++;
+ }
+ rkt->table[r] = mr;
+ spin_unlock_irqrestore(&rkt->lock, flags);
+
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_free_lkey - free an lkey
+ * @rkt: table from which to free the lkey
+ * @lkey: lkey id to free
+ */
+void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
+{
+ unsigned long flags;
+ u32 r;
+
+ if (lkey == 0)
+ return;
+ r = lkey >> (32 - ib_ipath_lkey_table_size);
+ spin_lock_irqsave(&rkt->lock, flags);
+ rkt->table[r] = NULL;
+ spin_unlock_irqrestore(&rkt->lock, flags);
+}
+
+/**
+ * ipath_lkey_ok - check IB SGE for validity and initialize
+ * @rkt: table containing lkey to check SGE against
+ * @isge: outgoing internal SGE
+ * @sge: SGE to check
+ * @acc: access flags
+ *
+ * Return 1 if valid and successful, otherwise returns 0.
+ *
+ * Check the IB SGE for validity and initialize our internal version
+ * of it.
+ */
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+ struct ib_sge *sge, int acc)
+{
+ struct ipath_mregion *mr;
+ size_t off;
+ int ret;
+
+ /*
+ * We use LKEY == zero to mean a physical kmalloc() address.
+ * This is a bit of a hack since we rely on dma_map_single()
+ * being reversible by calling bus_to_virt().
+ */
+ if (sge->lkey == 0) {
+ isge->mr = NULL;
+ isge->vaddr = bus_to_virt(sge->addr);
+ isge->length = sge->length;
+ isge->sge_length = sge->length;
+ ret = 1;
+ goto bail;
+ }
+ spin_lock(&rkt->lock);
+ mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
+ spin_unlock(&rkt->lock);
+ if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off = sge->addr - mr->user_base;
+ if (unlikely(sge->addr < mr->user_base ||
+ off + sge->length > mr->length ||
+ (mr->access_flags & acc) != acc)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off += mr->offset;
+ isge->mr = mr;
+ isge->m = 0;
+ isge->n = 0;
+ while (off >= mr->map[isge->m]->segs[isge->n].length) {
+ off -= mr->map[isge->m]->segs[isge->n].length;
+ isge->n++;
+ if (isge->n >= IPATH_SEGSZ) {
+ isge->m++;
+ isge->n = 0;
+ }
+ }
+ isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
+ isge->length = mr->map[isge->m]->segs[isge->n].length - off;
+ isge->sge_length = sge->length;
+
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_rkey_ok - check the IB virtual address, length, and RKEY
+ * @dev: infiniband device
+ * @ss: SGE state
+ * @len: length of data
+ * @vaddr: virtual address to place data
+ * @rkey: rkey to check
+ * @acc: access flags
+ *
+ * Return 1 if successful, otherwise 0.
+ *
+ * The QP r_rq.lock should be held.
+ */
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+ u32 len, u64 vaddr, u32 rkey, int acc)
+{
+ struct ipath_lkey_table *rkt = &dev->lk_table;
+ struct ipath_sge *sge = &ss->sge;
+ struct ipath_mregion *mr;
+ size_t off;
+ int ret;
+
+ spin_lock(&rkt->lock);
+ mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
+ spin_unlock(&rkt->lock);
+ if (unlikely(mr == NULL || mr->lkey != rkey)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off = vaddr - mr->iova;
+ if (unlikely(vaddr < mr->iova || off + len > mr->length ||
+ (mr->access_flags & acc) == 0)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off += mr->offset;
+ sge->mr = mr;
+ sge->m = 0;
+ sge->n = 0;
+ while (off >= mr->map[sge->m]->segs[sge->n].length) {
+ off -= mr->map[sge->m]->segs[sge->n].length;
+ sge->n++;
+ if (sge->n >= IPATH_SEGSZ) {
+ sge->m++;
+ sge->n = 0;
+ }
+ }
+ sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
+ sge->length = mr->map[sge->m]->segs[sge->n].length - off;
+ sge->sge_length = len;
+ ss->sg_list = NULL;
+ ss->num_sge = 1;
+
+ ret = 1;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
new file mode 100644
index 000000000000..69ed1100701a
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -0,0 +1,1515 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * These are the routines used by layered drivers, currently just the
+ * layered ethernet driver and verbs layer.
+ */
+
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <asm/byteorder.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+/* Acquire before ipath_devs_lock. */
+static DEFINE_MUTEX(ipath_layer_mutex);
+
+u16 ipath_layer_rcv_opcode;
+static int (*layer_intr)(void *, u32);
+static int (*layer_rcv)(void *, void *, struct sk_buff *);
+static int (*layer_rcv_lid)(void *, void *);
+static int (*verbs_piobufavail)(void *);
+static void (*verbs_rcv)(void *, void *, void *, u32);
+static int ipath_verbs_registered;
+
+static void *(*layer_add_one)(int, struct ipath_devdata *);
+static void (*layer_remove_one)(void *);
+static void *(*verbs_add_one)(int, struct ipath_devdata *);
+static void (*verbs_remove_one)(void *);
+static void (*verbs_timer_cb)(void *);
+
+int __ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
+{
+ int ret = -ENODEV;
+
+ if (dd->ipath_layer.l_arg && layer_intr)
+ ret = layer_intr(dd->ipath_layer.l_arg, arg);
+
+ return ret;
+}
+
+int ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
+{
+ int ret;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ ret = __ipath_layer_intr(dd, arg);
+
+ mutex_unlock(&ipath_layer_mutex);
+
+ return ret;
+}
+
+int __ipath_layer_rcv(struct ipath_devdata *dd, void *hdr,
+ struct sk_buff *skb)
+{
+ int ret = -ENODEV;
+
+ if (dd->ipath_layer.l_arg && layer_rcv)
+ ret = layer_rcv(dd->ipath_layer.l_arg, hdr, skb);
+
+ return ret;
+}
+
+int __ipath_layer_rcv_lid(struct ipath_devdata *dd, void *hdr)
+{
+ int ret = -ENODEV;
+
+ if (dd->ipath_layer.l_arg && layer_rcv_lid)
+ ret = layer_rcv_lid(dd->ipath_layer.l_arg, hdr);
+
+ return ret;
+}
+
+int __ipath_verbs_piobufavail(struct ipath_devdata *dd)
+{
+ int ret = -ENODEV;
+
+ if (dd->verbs_layer.l_arg && verbs_piobufavail)
+ ret = verbs_piobufavail(dd->verbs_layer.l_arg);
+
+ return ret;
+}
+
+int __ipath_verbs_rcv(struct ipath_devdata *dd, void *rc, void *ebuf,
+ u32 tlen)
+{
+ int ret = -ENODEV;
+
+ if (dd->verbs_layer.l_arg && verbs_rcv) {
+ verbs_rcv(dd->verbs_layer.l_arg, rc, ebuf, tlen);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+{
+ u32 lstate;
+ int ret;
+
+ switch (newstate) {
+ case IPATH_IB_LINKDOWN:
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN_SLEEP:
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN_DISABLE:
+ ipath_set_ib_lstate(dd,
+ INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKINIT:
+ if (dd->ipath_flags & IPATH_LINKINIT) {
+ ret = 0;
+ goto bail;
+ }
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT <<
+ INFINIPATH_IBCC_LINKCMD_SHIFT);
+ lstate = IPATH_LINKINIT;
+ break;
+
+ case IPATH_IB_LINKARM:
+ if (dd->ipath_flags & IPATH_LINKARMED) {
+ ret = 0;
+ goto bail;
+ }
+ if (!(dd->ipath_flags &
+ (IPATH_LINKINIT | IPATH_LINKACTIVE))) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED <<
+ INFINIPATH_IBCC_LINKCMD_SHIFT);
+ /*
+ * Since the port can transition to ACTIVE by receiving
+ * a non VL 15 packet, wait for either state.
+ */
+ lstate = IPATH_LINKARMED | IPATH_LINKACTIVE;
+ break;
+
+ case IPATH_IB_LINKACTIVE:
+ if (dd->ipath_flags & IPATH_LINKACTIVE) {
+ ret = 0;
+ goto bail;
+ }
+ if (!(dd->ipath_flags & IPATH_LINKARMED)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE <<
+ INFINIPATH_IBCC_LINKCMD_SHIFT);
+ lstate = IPATH_LINKACTIVE;
+ break;
+
+ default:
+ ipath_dbg("Invalid linkstate 0x%x requested\n", newstate);
+ ret = -EINVAL;
+ goto bail;
+ }
+ ret = ipath_wait_linkstate(dd, lstate, 2000);
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_linkstate);
+
+/**
+ * ipath_layer_set_mtu - set the MTU
+ * @dd: the infinipath device
+ * @arg: the new MTU
+ *
+ * we can handle "any" incoming size, the issue here is whether we
+ * need to restrict our outgoing size. For now, we don't do any
+ * sanity checking on this, and we don't deal with what happens to
+ * programs that are already running when the size changes.
+ * NOTE: changing the MTU will usually cause the IBC to go back to
+ * link initialize (IPATH_IBSTATE_INIT) state...
+ */
+int ipath_layer_set_mtu(struct ipath_devdata *dd, u16 arg)
+{
+ u32 piosize;
+ int changed = 0;
+ int ret;
+
+ /*
+ * mtu is IB data payload max. It's the largest power of 2 less
+ * than piosize (or even larger, since it only really controls the
+ * largest we can receive; we can send the max of the mtu and
+ * piosize). We check that it's one of the valid IB sizes.
+ */
+ if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
+ arg != 4096) {
+ ipath_dbg("Trying to set invalid mtu %u, failing\n", arg);
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (dd->ipath_ibmtu == arg) {
+ ret = 0; /* same as current */
+ goto bail;
+ }
+
+ piosize = dd->ipath_ibmaxlen;
+ dd->ipath_ibmtu = arg;
+
+ if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) {
+ /* Only if it's not the initial value (or reset to it) */
+ if (piosize != dd->ipath_init_ibmaxlen) {
+ dd->ipath_ibmaxlen = piosize;
+ changed = 1;
+ }
+ } else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) {
+ piosize = arg + IPATH_PIO_MAXIBHDR;
+ ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x "
+ "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize,
+ arg);
+ dd->ipath_ibmaxlen = piosize;
+ changed = 1;
+ }
+
+ if (changed) {
+ /*
+ * set the IBC maxpktlength to the size of our pio
+ * buffers in words
+ */
+ u64 ibc = dd->ipath_ibcctrl;
+ ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
+ INFINIPATH_IBCC_MAXPKTLEN_SHIFT);
+
+ piosize = piosize - 2 * sizeof(u32); /* ignore pbc */
+ dd->ipath_ibmaxlen = piosize;
+ piosize /= sizeof(u32); /* in words */
+ /*
+ * for ICRC, which we only send in diag test pkt mode, and
+ * we don't need to worry about that for mtu
+ */
+ piosize += 1;
+
+ ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+ dd->ipath_ibcctrl = ibc;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ dd->ipath_f_tidtemplate(dd);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_mtu);
+
+int ipath_set_sps_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
+{
+ ipath_stats.sps_lid[dd->ipath_unit] = arg;
+ dd->ipath_lid = arg;
+ dd->ipath_lmc = lmc;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ if (dd->ipath_layer.l_arg && layer_intr)
+ layer_intr(dd->ipath_layer.l_arg, IPATH_LAYER_INT_LID);
+
+ mutex_unlock(&ipath_layer_mutex);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_set_sps_lid);
+
+int ipath_layer_set_guid(struct ipath_devdata *dd, __be64 guid)
+{
+ /* XXX - need to inform anyone who cares this just happened. */
+ dd->ipath_guid = guid;
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_guid);
+
+__be64 ipath_layer_get_guid(struct ipath_devdata *dd)
+{
+ return dd->ipath_guid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_guid);
+
+u32 ipath_layer_get_nguid(struct ipath_devdata *dd)
+{
+ return dd->ipath_nguid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_nguid);
+
+int ipath_layer_query_device(struct ipath_devdata *dd, u32 * vendor,
+ u32 * boardrev, u32 * majrev, u32 * minrev)
+{
+ *vendor = dd->ipath_vendorid;
+ *boardrev = dd->ipath_boardrev;
+ *majrev = dd->ipath_majrev;
+ *minrev = dd->ipath_minrev;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_query_device);
+
+u32 ipath_layer_get_flags(struct ipath_devdata *dd)
+{
+ return dd->ipath_flags;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_flags);
+
+struct device *ipath_layer_get_device(struct ipath_devdata *dd)
+{
+ return &dd->pcidev->dev;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_device);
+
+u16 ipath_layer_get_deviceid(struct ipath_devdata *dd)
+{
+ return dd->ipath_deviceid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_deviceid);
+
+u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd)
+{
+ return dd->ipath_lastibcstat;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_lastibcstat);
+
+u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd)
+{
+ return dd->ipath_ibmtu;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_ibmtu);
+
+void ipath_layer_add(struct ipath_devdata *dd)
+{
+ mutex_lock(&ipath_layer_mutex);
+
+ if (layer_add_one)
+ dd->ipath_layer.l_arg =
+ layer_add_one(dd->ipath_unit, dd);
+
+ if (verbs_add_one)
+ dd->verbs_layer.l_arg =
+ verbs_add_one(dd->ipath_unit, dd);
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+void ipath_layer_del(struct ipath_devdata *dd)
+{
+ mutex_lock(&ipath_layer_mutex);
+
+ if (dd->ipath_layer.l_arg && layer_remove_one) {
+ layer_remove_one(dd->ipath_layer.l_arg);
+ dd->ipath_layer.l_arg = NULL;
+ }
+
+ if (dd->verbs_layer.l_arg && verbs_remove_one) {
+ verbs_remove_one(dd->verbs_layer.l_arg);
+ dd->verbs_layer.l_arg = NULL;
+ }
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *),
+ int (*l_intr)(void *, u32),
+ int (*l_rcv)(void *, void *, struct sk_buff *),
+ u16 l_rcv_opcode,
+ int (*l_rcv_lid)(void *, void *))
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ layer_add_one = l_add;
+ layer_remove_one = l_remove;
+ layer_intr = l_intr;
+ layer_rcv = l_rcv;
+ layer_rcv_lid = l_rcv_lid;
+ ipath_layer_rcv_opcode = l_rcv_opcode;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ if (!(dd->ipath_flags & IPATH_INITTED))
+ continue;
+
+ if (dd->ipath_layer.l_arg)
+ continue;
+
+ if (!(*dd->ipath_statusp & IPATH_STATUS_SMA))
+ *dd->ipath_statusp |= IPATH_STATUS_OIB_SMA;
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ dd->ipath_layer.l_arg = l_add(dd->ipath_unit, dd);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ mutex_unlock(&ipath_layer_mutex);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_register);
+
+void ipath_layer_unregister(void)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ if (dd->ipath_layer.l_arg && layer_remove_one) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ layer_remove_one(dd->ipath_layer.l_arg);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ dd->ipath_layer.l_arg = NULL;
+ }
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ layer_add_one = NULL;
+ layer_remove_one = NULL;
+ layer_intr = NULL;
+ layer_rcv = NULL;
+ layer_rcv_lid = NULL;
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_unregister);
+
+static void __ipath_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. */
+ if (dd->verbs_layer.l_arg && verbs_timer_cb)
+ verbs_timer_cb(dd->verbs_layer.l_arg);
+
+ mod_timer(&dd->verbs_layer.l_timer, jiffies + 1);
+}
+
+/**
+ * ipath_verbs_register - verbs layer registration
+ * @l_piobufavail: callback for when PIO buffers become available
+ * @l_rcv: callback for receiving a packet
+ * @l_timer_cb: timer callback
+ * @ipath_devdata: device data structure is put here
+ */
+int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *arg),
+ int (*l_piobufavail) (void *arg),
+ void (*l_rcv) (void *arg, void *rhdr,
+ void *data, u32 tlen),
+ void (*l_timer_cb) (void *arg))
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ verbs_add_one = l_add;
+ verbs_remove_one = l_remove;
+ verbs_piobufavail = l_piobufavail;
+ verbs_rcv = l_rcv;
+ verbs_timer_cb = l_timer_cb;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ if (!(dd->ipath_flags & IPATH_INITTED))
+ continue;
+
+ if (dd->verbs_layer.l_arg)
+ continue;
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ dd->verbs_layer.l_arg = l_add(dd->ipath_unit, dd);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ mutex_unlock(&ipath_layer_mutex);
+
+ ipath_verbs_registered = 1;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_register);
+
+void ipath_verbs_unregister(void)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ *dd->ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
+
+ if (dd->verbs_layer.l_arg && verbs_remove_one) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ verbs_remove_one(dd->verbs_layer.l_arg);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ dd->verbs_layer.l_arg = NULL;
+ }
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ verbs_add_one = NULL;
+ verbs_remove_one = NULL;
+ verbs_piobufavail = NULL;
+ verbs_rcv = NULL;
+ verbs_timer_cb = NULL;
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_unregister);
+
+int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax)
+{
+ int ret;
+ u32 intval = 0;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ if (!dd->ipath_layer.l_arg) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ret = ipath_setrcvhdrsize(dd, NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE);
+
+ if (ret < 0)
+ goto bail;
+
+ *pktmax = dd->ipath_ibmaxlen;
+
+ if (*dd->ipath_statusp & IPATH_STATUS_IB_READY)
+ intval |= IPATH_LAYER_INT_IF_UP;
+ if (ipath_stats.sps_lid[dd->ipath_unit])
+ intval |= IPATH_LAYER_INT_LID;
+ if (ipath_stats.sps_mlid[dd->ipath_unit])
+ intval |= IPATH_LAYER_INT_BCAST;
+ /*
+ * do this on open, in case low level is already up and
+ * just layered driver was reloaded, etc.
+ */
+ if (intval)
+ layer_intr(dd->ipath_layer.l_arg, intval);
+
+ ret = 0;
+bail:
+ mutex_unlock(&ipath_layer_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_open);
+
+u16 ipath_layer_get_lid(struct ipath_devdata *dd)
+{
+ return dd->ipath_lid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_lid);
+
+/**
+ * ipath_layer_get_mac - get the MAC address
+ * @dd: the infinipath device
+ * @mac: the MAC is put here
+ *
+ * This is the EUID-64 OUI octets (top 3), then
+ * skip the next 2 (which should both be zero or 0xff).
+ * The returned MAC is in network order
+ * mac points to at least 6 bytes of buffer
+ * We assume that by the time the LID is set, that the GUID is as valid
+ * as it's ever going to be, rather than adding yet another status bit.
+ */
+
+int ipath_layer_get_mac(struct ipath_devdata *dd, u8 * mac)
+{
+ u8 *guid;
+
+ guid = (u8 *) &dd->ipath_guid;
+
+ mac[0] = guid[0];
+ mac[1] = guid[1];
+ mac[2] = guid[2];
+ mac[3] = guid[5];
+ mac[4] = guid[6];
+ mac[5] = guid[7];
+ if ((guid[3] || guid[4]) && !(guid[3] == 0xff && guid[4] == 0xff))
+ ipath_dbg("Warning, guid bytes 3 and 4 not 0 or 0xffff: "
+ "%x %x\n", guid[3], guid[4]);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_mac);
+
+u16 ipath_layer_get_bcast(struct ipath_devdata *dd)
+{
+ return dd->ipath_mlid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_bcast);
+
+u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd)
+{
+ return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_cr_errpkey);
+
+static void update_sge(struct ipath_sge_state *ss, u32 length)
+{
+ struct ipath_sge *sge = &ss->sge;
+
+ sge->vaddr += length;
+ sge->length -= length;
+ sge->sge_length -= length;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ return;
+ sge->n = 0;
+ }
+ sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length = sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+}
+
+#ifdef __LITTLE_ENDIAN
+static inline u32 get_upper_bits(u32 data, u32 shift)
+{
+ return data >> shift;
+}
+
+static inline u32 set_upper_bits(u32 data, u32 shift)
+{
+ return data << shift;
+}
+
+static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off)
+{
+ data <<= ((sizeof(u32) - n) * BITS_PER_BYTE);
+ data >>= ((sizeof(u32) - n - off) * BITS_PER_BYTE);
+ return data;
+}
+#else
+static inline u32 get_upper_bits(u32 data, u32 shift)
+{
+ return data << shift;
+}
+
+static inline u32 set_upper_bits(u32 data, u32 shift)
+{
+ return data >> shift;
+}
+
+static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off)
+{
+ data >>= ((sizeof(u32) - n) * BITS_PER_BYTE);
+ data <<= ((sizeof(u32) - n - off) * BITS_PER_BYTE);
+ return data;
+}
+#endif
+
+static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss,
+ u32 length)
+{
+ u32 extra = 0;
+ u32 data = 0;
+ u32 last;
+
+ while (1) {
+ u32 len = ss->sge.length;
+ u32 off;
+
+ BUG_ON(len == 0);
+ if (len > length)
+ len = length;
+ if (len > ss->sge.sge_length)
+ len = ss->sge.sge_length;
+ /* If the source address is not aligned, try to align it. */
+ off = (unsigned long)ss->sge.vaddr & (sizeof(u32) - 1);
+ if (off) {
+ u32 *addr = (u32 *)((unsigned long)ss->sge.vaddr &
+ ~(sizeof(u32) - 1));
+ u32 v = get_upper_bits(*addr, off * BITS_PER_BYTE);
+ u32 y;
+
+ y = sizeof(u32) - off;
+ if (len > y)
+ len = y;
+ if (len + extra >= sizeof(u32)) {
+ data |= set_upper_bits(v, extra *
+ BITS_PER_BYTE);
+ len = sizeof(u32) - extra;
+ if (len == length) {
+ last = data;
+ break;
+ }
+ __raw_writel(data, piobuf);
+ piobuf++;
+ extra = 0;
+ data = 0;
+ } else {
+ /* Clear unused upper bytes */
+ data |= clear_upper_bytes(v, len, extra);
+ if (len == length) {
+ last = data;
+ break;
+ }
+ extra += len;
+ }
+ } else if (extra) {
+ /* Source address is aligned. */
+ u32 *addr = (u32 *) ss->sge.vaddr;
+ int shift = extra * BITS_PER_BYTE;
+ int ushift = 32 - shift;
+ u32 l = len;
+
+ while (l >= sizeof(u32)) {
+ u32 v = *addr;
+
+ data |= set_upper_bits(v, shift);
+ __raw_writel(data, piobuf);
+ data = get_upper_bits(v, ushift);
+ piobuf++;
+ addr++;
+ l -= sizeof(u32);
+ }
+ /*
+ * We still have 'extra' number of bytes leftover.
+ */
+ if (l) {
+ u32 v = *addr;
+
+ if (l + extra >= sizeof(u32)) {
+ data |= set_upper_bits(v, shift);
+ len -= l + extra - sizeof(u32);
+ if (len == length) {
+ last = data;
+ break;
+ }
+ __raw_writel(data, piobuf);
+ piobuf++;
+ extra = 0;
+ data = 0;
+ } else {
+ /* Clear unused upper bytes */
+ data |= clear_upper_bytes(v, l,
+ extra);
+ if (len == length) {
+ last = data;
+ break;
+ }
+ extra += l;
+ }
+ } else if (len == length) {
+ last = data;
+ break;
+ }
+ } else if (len == length) {
+ u32 w;
+
+ /*
+ * Need to round up for the last dword in the
+ * packet.
+ */
+ w = (len + 3) >> 2;
+ __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1);
+ piobuf += w - 1;
+ last = ((u32 *) ss->sge.vaddr)[w - 1];
+ break;
+ } else {
+ u32 w = len >> 2;
+
+ __iowrite32_copy(piobuf, ss->sge.vaddr, w);
+ piobuf += w;
+
+ extra = len & (sizeof(u32) - 1);
+ if (extra) {
+ u32 v = ((u32 *) ss->sge.vaddr)[w];
+
+ /* Clear unused upper bytes */
+ data = clear_upper_bytes(v, extra, 0);
+ }
+ }
+ update_sge(ss, len);
+ length -= len;
+ }
+ /* must flush early everything before trigger word */
+ ipath_flush_wc();
+ __raw_writel(last, piobuf);
+ /* be sure trigger word is written */
+ ipath_flush_wc();
+ update_sge(ss, length);
+}
+
+/**
+ * ipath_verbs_send - send a packet from the verbs layer
+ * @dd: the infinipath device
+ * @hdrwords: the number of works in the header
+ * @hdr: the packet header
+ * @len: the length of the packet in bytes
+ * @ss: the SGE to send
+ *
+ * This is like ipath_sma_send_pkt() in that we need to be able to send
+ * packets after the chip is initialized (MADs) but also like
+ * ipath_layer_send_hdr() since its used by the verbs layer.
+ */
+int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
+ u32 *hdr, u32 len, struct ipath_sge_state *ss)
+{
+ u32 __iomem *piobuf;
+ u32 plen;
+ int ret;
+
+ /* +1 is for the qword padding of pbc */
+ plen = hdrwords + ((len + 3) >> 2) + 1;
+ if (unlikely((plen << 2) > dd->ipath_ibmaxlen)) {
+ ipath_dbg("packet len 0x%x too long, failing\n", plen);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ /* Get a PIO buffer to use. */
+ piobuf = ipath_getpiobuf(dd, NULL);
+ if (unlikely(piobuf == NULL)) {
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ /*
+ * Write len to control qword, no flags.
+ * We have to flush after the PBC for correctness on some cpus
+ * or WC buffer can be written out of order.
+ */
+ writeq(plen, piobuf);
+ ipath_flush_wc();
+ piobuf += 2;
+ if (len == 0) {
+ /*
+ * If there is just the header portion, must flush before
+ * writing last word of header for correctness, and after
+ * the last header word (trigger word).
+ */
+ __iowrite32_copy(piobuf, hdr, hdrwords - 1);
+ ipath_flush_wc();
+ __raw_writel(hdr[hdrwords - 1], piobuf + hdrwords - 1);
+ ipath_flush_wc();
+ ret = 0;
+ goto bail;
+ }
+
+ __iowrite32_copy(piobuf, hdr, hdrwords);
+ piobuf += hdrwords;
+
+ /* The common case is aligned and contained in one segment. */
+ if (likely(ss->num_sge == 1 && len <= ss->sge.length &&
+ !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) {
+ u32 w;
+
+ /* Need to round up for the last dword in the packet. */
+ w = (len + 3) >> 2;
+ __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1);
+ /* must flush early everything before trigger word */
+ ipath_flush_wc();
+ __raw_writel(((u32 *) ss->sge.vaddr)[w - 1],
+ piobuf + w - 1);
+ /* be sure trigger word is written */
+ ipath_flush_wc();
+ update_sge(ss, len);
+ ret = 0;
+ goto bail;
+ }
+ copy_io(piobuf, ss, len);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_send);
+
+int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords,
+ u64 *rwords, u64 *spkts, u64 *rpkts,
+ u64 *xmit_wait)
+{
+ int ret;
+
+ if (!(dd->ipath_flags & IPATH_INITTED)) {
+ /* no hardware, freeze, etc. */
+ ipath_dbg("unit %u not usable\n", dd->ipath_unit);
+ ret = -EINVAL;
+ goto bail;
+ }
+ *swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+ *rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+ *spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+ *rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+ *xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_snapshot_counters);
+
+/**
+ * ipath_layer_get_counters - get various chip counters
+ * @dd: the infinipath device
+ * @cntrs: counters are placed here
+ *
+ * Return the counters needed by recv_pma_get_portcounters().
+ */
+int ipath_layer_get_counters(struct ipath_devdata *dd,
+ struct ipath_layer_counters *cntrs)
+{
+ int ret;
+
+ if (!(dd->ipath_flags & IPATH_INITTED)) {
+ /* no hardware, freeze, etc. */
+ ipath_dbg("unit %u not usable\n", dd->ipath_unit);
+ ret = -EINVAL;
+ goto bail;
+ }
+ cntrs->symbol_error_counter =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
+ cntrs->link_error_recovery_counter =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
+ cntrs->link_downed_counter =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt);
+ cntrs->port_rcv_errors =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errrcvflowctrlcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlinkcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt);
+ cntrs->port_rcv_remphys_errors =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt);
+ cntrs->port_xmit_discards =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_unsupvlcnt);
+ cntrs->port_xmit_data =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+ cntrs->port_rcv_data =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+ cntrs->port_xmit_packets =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+ cntrs->port_rcv_packets =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_counters);
+
+int ipath_layer_want_buffer(struct ipath_devdata *dd)
+{
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_want_buffer);
+
+int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr)
+{
+ int ret = 0;
+ u32 __iomem *piobuf;
+ u32 plen, *uhdr;
+ size_t count;
+ __be16 vlsllnh;
+
+ if (!(dd->ipath_flags & IPATH_RCVHDRSZ_SET)) {
+ ipath_dbg("send while not open\n");
+ ret = -EINVAL;
+ } else
+ if ((dd->ipath_flags & (IPATH_LINKUNK | IPATH_LINKDOWN)) ||
+ dd->ipath_lid == 0) {
+ /*
+ * lid check is for when sma hasn't yet configured
+ */
+ ret = -ENETDOWN;
+ ipath_cdbg(VERBOSE, "send while not ready, "
+ "mylid=%u, flags=0x%x\n",
+ dd->ipath_lid, dd->ipath_flags);
+ }
+
+ vlsllnh = *((__be16 *) hdr);
+ if (vlsllnh != htons(IPS_LRH_BTH)) {
+ ipath_dbg("Warning: lrh[0] wrong (%x, not %x); "
+ "not sending\n", be16_to_cpu(vlsllnh),
+ IPS_LRH_BTH);
+ ret = -EINVAL;
+ }
+ if (ret)
+ goto done;
+
+ /* Get a PIO buffer to use. */
+ piobuf = ipath_getpiobuf(dd, NULL);
+ if (piobuf == NULL) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ plen = (sizeof(*hdr) >> 2); /* actual length */
+ ipath_cdbg(EPKT, "0x%x+1w pio %p\n", plen, piobuf);
+
+ writeq(plen+1, piobuf); /* len (+1 for pad) to pbc, no flags */
+ ipath_flush_wc();
+ piobuf += 2;
+ uhdr = (u32 *)hdr;
+ count = plen-1; /* amount we can copy before trigger word */
+ __iowrite32_copy(piobuf, uhdr, count);
+ ipath_flush_wc();
+ __raw_writel(uhdr[count], piobuf + count);
+ ipath_flush_wc(); /* ensure it's sent, now */
+
+ ipath_stats.sps_ether_spkts++; /* ether packet sent */
+
+done:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_send_hdr);
+
+int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd)
+{
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_piointbufavail_int);
+
+int ipath_layer_enable_timer(struct ipath_devdata *dd)
+{
+ /*
+ * HT-400 has a design flaw where the chip and kernel idea
+ * of the tail register don't always agree, and therefore we won't
+ * get an interrupt on the next packet received.
+ * If the board supports per packet receive interrupts, use it.
+ * Otherwise, the timer function periodically checks for packets
+ * to cover this case.
+ * Either way, the timer is needed for verbs layer related
+ * processing.
+ */
+ if (dd->ipath_flags & IPATH_GPIO_INTR) {
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
+ 0x2074076542310ULL);
+ /* Enable GPIO bit 2 interrupt */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+ (u64) (1 << 2));
+ }
+
+ init_timer(&dd->verbs_layer.l_timer);
+ dd->verbs_layer.l_timer.function = __ipath_verbs_timer;
+ dd->verbs_layer.l_timer.data = (unsigned long)dd;
+ dd->verbs_layer.l_timer.expires = jiffies + 1;
+ add_timer(&dd->verbs_layer.l_timer);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_enable_timer);
+
+int ipath_layer_disable_timer(struct ipath_devdata *dd)
+{
+ /* Disable GPIO bit 2 interrupt */
+ if (dd->ipath_flags & IPATH_GPIO_INTR)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, 0);
+
+ del_timer_sync(&dd->verbs_layer.l_timer);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_disable_timer);
+
+/**
+ * ipath_layer_set_verbs_flags - set the verbs layer flags
+ * @dd: the infinipath device
+ * @flags: the flags to set
+ */
+int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags)
+{
+ struct ipath_devdata *ss;
+ unsigned long lflags;
+
+ spin_lock_irqsave(&ipath_devs_lock, lflags);
+
+ list_for_each_entry(ss, &ipath_dev_list, ipath_list) {
+ if (!(ss->ipath_flags & IPATH_INITTED))
+ continue;
+ if ((flags & IPATH_VERBS_KERNEL_SMA) &&
+ !(*ss->ipath_statusp & IPATH_STATUS_SMA))
+ *ss->ipath_statusp |= IPATH_STATUS_OIB_SMA;
+ else
+ *ss->ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, lflags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_verbs_flags);
+
+/**
+ * ipath_layer_get_npkeys - return the size of the PKEY table for port 0
+ * @dd: the infinipath device
+ */
+unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd)
+{
+ return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_npkeys);
+
+/**
+ * ipath_layer_get_pkey - return the indexed PKEY from the port 0 PKEY table
+ * @dd: the infinipath device
+ * @index: the PKEY index
+ */
+unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index)
+{
+ unsigned ret;
+
+ if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys))
+ ret = 0;
+ else
+ ret = dd->ipath_pd[0]->port_pkeys[index];
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_pkey);
+
+/**
+ * ipath_layer_get_pkeys - return the PKEY table for port 0
+ * @dd: the infinipath device
+ * @pkeys: the pkey table is placed here
+ */
+int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 * pkeys)
+{
+ struct ipath_portdata *pd = dd->ipath_pd[0];
+
+ memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys));
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_pkeys);
+
+/**
+ * rm_pkey - decrecment the reference count for the given PKEY
+ * @dd: the infinipath device
+ * @key: the PKEY index
+ *
+ * Return true if this was the last reference and the hardware table entry
+ * needs to be changed.
+ */
+static int rm_pkey(struct ipath_devdata *dd, u16 key)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (dd->ipath_pkeys[i] != key)
+ continue;
+ if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) {
+ dd->ipath_pkeys[i] = 0;
+ ret = 1;
+ goto bail;
+ }
+ break;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * add_pkey - add the given PKEY to the hardware table
+ * @dd: the infinipath device
+ * @key: the PKEY
+ *
+ * Return an error code if unable to add the entry, zero if no change,
+ * or 1 if the hardware PKEY register needs to be updated.
+ */
+static int add_pkey(struct ipath_devdata *dd, u16 key)
+{
+ int i;
+ u16 lkey = key & 0x7FFF;
+ int any = 0;
+ int ret;
+
+ if (lkey == 0x7FFF) {
+ ret = 0;
+ goto bail;
+ }
+
+ /* Look for an empty slot or a matching PKEY. */
+ for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i]) {
+ any++;
+ continue;
+ }
+ /* If it matches exactly, try to increment the ref count */
+ if (dd->ipath_pkeys[i] == key) {
+ if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) {
+ ret = 0;
+ goto bail;
+ }
+ /* Lost the race. Look for an empty slot below. */
+ atomic_dec(&dd->ipath_pkeyrefs[i]);
+ any++;
+ }
+ /*
+ * It makes no sense to have both the limited and unlimited
+ * PKEY set at the same time since the unlimited one will
+ * disable the limited one.
+ */
+ if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
+ ret = -EEXIST;
+ goto bail;
+ }
+ }
+ if (!any) {
+ ret = -EBUSY;
+ goto bail;
+ }
+ for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i] &&
+ atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
+ /* for ipathstats, etc. */
+ ipath_stats.sps_pkeys[i] = lkey;
+ dd->ipath_pkeys[i] = key;
+ ret = 1;
+ goto bail;
+ }
+ }
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_layer_set_pkeys - set the PKEY table for port 0
+ * @dd: the infinipath device
+ * @pkeys: the PKEY table
+ */
+int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 * pkeys)
+{
+ struct ipath_portdata *pd;
+ int i;
+ int changed = 0;
+
+ pd = dd->ipath_pd[0];
+
+ for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+ u16 key = pkeys[i];
+ u16 okey = pd->port_pkeys[i];
+
+ if (key == okey)
+ continue;
+ /*
+ * The value of this PKEY table entry is changing.
+ * Remove the old entry in the hardware's array of PKEYs.
+ */
+ if (okey & 0x7FFF)
+ changed |= rm_pkey(dd, okey);
+ if (key & 0x7FFF) {
+ int ret = add_pkey(dd, key);
+
+ if (ret < 0)
+ key = 0;
+ else
+ changed |= ret;
+ }
+ pd->port_pkeys[i] = key;
+ }
+ if (changed) {
+ u64 pkey;
+
+ pkey = (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+ ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n",
+ (unsigned long long) pkey);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
+ pkey);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_pkeys);
+
+/**
+ * ipath_layer_get_linkdowndefaultstate - get the default linkdown state
+ * @dd: the infinipath device
+ *
+ * Returns zero if the default is POLL, 1 if the default is SLEEP.
+ */
+int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd)
+{
+ return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_linkdowndefaultstate);
+
+/**
+ * ipath_layer_set_linkdowndefaultstate - set the default linkdown state
+ * @dd: the infinipath device
+ * @sleep: the new state
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd,
+ int sleep)
+{
+ if (sleep)
+ dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
+ else
+ dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_linkdowndefaultstate);
+
+int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd)
+{
+ return (dd->ipath_ibcctrl >>
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_phyerrthreshold);
+
+/**
+ * ipath_layer_set_phyerrthreshold - set the physical error threshold
+ * @dd: the infinipath device
+ * @n: the new threshold
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n)
+{
+ unsigned v;
+
+ v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+ if (v != n) {
+ dd->ipath_ibcctrl &=
+ ~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK <<
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT);
+ dd->ipath_ibcctrl |=
+ (u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_phyerrthreshold);
+
+int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd)
+{
+ return (dd->ipath_ibcctrl >>
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_overrunthreshold);
+
+/**
+ * ipath_layer_set_overrunthreshold - set the overrun threshold
+ * @dd: the infinipath device
+ * @n: the new threshold
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n)
+{
+ unsigned v;
+
+ v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
+ if (v != n) {
+ dd->ipath_ibcctrl &=
+ ~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK <<
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT);
+ dd->ipath_ibcctrl |=
+ (u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_overrunthreshold);
+
+int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen)
+{
+ return dd->ipath_f_get_boardname(dd, name, namelen);
+}
+EXPORT_SYMBOL_GPL(ipath_layer_get_boardname);
+
+u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd)
+{
+ return dd->ipath_rcvhdrentsize;
+}
+EXPORT_SYMBOL_GPL(ipath_layer_get_rcvhdrentsize);
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.h b/drivers/infiniband/hw/ipath/ipath_layer.h
new file mode 100644
index 000000000000..6fefd15bd2da
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_layer.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_LAYER_H
+#define _IPATH_LAYER_H
+
+/*
+ * This header file is for symbols shared between the infinipath driver
+ * and drivers layered upon it (such as ipath).
+ */
+
+struct sk_buff;
+struct ipath_sge_state;
+struct ipath_devdata;
+struct ether_header;
+
+struct ipath_layer_counters {
+ u64 symbol_error_counter;
+ u64 link_error_recovery_counter;
+ u64 link_downed_counter;
+ u64 port_rcv_errors;
+ u64 port_rcv_remphys_errors;
+ u64 port_xmit_discards;
+ u64 port_xmit_data;
+ u64 port_rcv_data;
+ u64 port_xmit_packets;
+ u64 port_rcv_packets;
+};
+
+/*
+ * A segment is a linear region of low physical memory.
+ * XXX Maybe we should use phys addr here and kmap()/kunmap().
+ * Used by the verbs layer.
+ */
+struct ipath_seg {
+ void *vaddr;
+ size_t length;
+};
+
+/* The number of ipath_segs that fit in a page. */
+#define IPATH_SEGSZ (PAGE_SIZE / sizeof (struct ipath_seg))
+
+struct ipath_segarray {
+ struct ipath_seg segs[IPATH_SEGSZ];
+};
+
+struct ipath_mregion {
+ u64 user_base; /* User's address for this region */
+ u64 iova; /* IB start address of this region */
+ size_t length;
+ u32 lkey;
+ u32 offset; /* offset (bytes) to start of region */
+ int access_flags;
+ u32 max_segs; /* number of ipath_segs in all the arrays */
+ u32 mapsz; /* size of the map array */
+ struct ipath_segarray *map[0]; /* the segments */
+};
+
+/*
+ * These keep track of the copy progress within a memory region.
+ * Used by the verbs layer.
+ */
+struct ipath_sge {
+ struct ipath_mregion *mr;
+ void *vaddr; /* current pointer into the segment */
+ u32 sge_length; /* length of the SGE */
+ u32 length; /* remaining length of the segment */
+ u16 m; /* current index: mr->map[m] */
+ u16 n; /* current index: mr->map[m]->segs[n] */
+};
+
+struct ipath_sge_state {
+ struct ipath_sge *sg_list; /* next SGE to be used if any */
+ struct ipath_sge sge; /* progress state for the current SGE */
+ u8 num_sge;
+};
+
+int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *),
+ int (*l_intr)(void *, u32),
+ int (*l_rcv)(void *, void *,
+ struct sk_buff *),
+ u16 rcv_opcode,
+ int (*l_rcv_lid)(void *, void *));
+int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *arg),
+ int (*l_piobufavail)(void *arg),
+ void (*l_rcv)(void *arg, void *rhdr,
+ void *data, u32 tlen),
+ void (*l_timer_cb)(void *arg));
+void ipath_layer_unregister(void);
+void ipath_verbs_unregister(void);
+int ipath_layer_open(struct ipath_devdata *, u32 * pktmax);
+u16 ipath_layer_get_lid(struct ipath_devdata *dd);
+int ipath_layer_get_mac(struct ipath_devdata *dd, u8 *);
+u16 ipath_layer_get_bcast(struct ipath_devdata *dd);
+u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd);
+int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 state);
+int ipath_layer_set_mtu(struct ipath_devdata *, u16);
+int ipath_set_sps_lid(struct ipath_devdata *, u32, u8);
+int ipath_layer_send_hdr(struct ipath_devdata *dd,
+ struct ether_header *hdr);
+int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
+ u32 * hdr, u32 len, struct ipath_sge_state *ss);
+int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd);
+int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen);
+int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords,
+ u64 *rwords, u64 *spkts, u64 *rpkts,
+ u64 *xmit_wait);
+int ipath_layer_get_counters(struct ipath_devdata *dd,
+ struct ipath_layer_counters *cntrs);
+int ipath_layer_want_buffer(struct ipath_devdata *dd);
+int ipath_layer_set_guid(struct ipath_devdata *, __be64 guid);
+__be64 ipath_layer_get_guid(struct ipath_devdata *);
+u32 ipath_layer_get_nguid(struct ipath_devdata *);
+int ipath_layer_query_device(struct ipath_devdata *, u32 * vendor,
+ u32 * boardrev, u32 * majrev, u32 * minrev);
+u32 ipath_layer_get_flags(struct ipath_devdata *dd);
+struct device *ipath_layer_get_device(struct ipath_devdata *dd);
+u16 ipath_layer_get_deviceid(struct ipath_devdata *dd);
+u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd);
+u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd);
+int ipath_layer_enable_timer(struct ipath_devdata *dd);
+int ipath_layer_disable_timer(struct ipath_devdata *dd);
+int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags);
+unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd);
+unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index);
+int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 *pkeys);
+int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 *pkeys);
+int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd);
+int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd,
+ int sleep);
+int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd);
+int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n);
+int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd);
+int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n);
+u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd);
+
+/* ipath_ether interrupt values */
+#define IPATH_LAYER_INT_IF_UP 0x2
+#define IPATH_LAYER_INT_IF_DOWN 0x4
+#define IPATH_LAYER_INT_LID 0x8
+#define IPATH_LAYER_INT_SEND_CONTINUE 0x10
+#define IPATH_LAYER_INT_BCAST 0x40
+
+/* _verbs_layer.l_flags */
+#define IPATH_VERBS_KERNEL_SMA 0x1
+
+extern unsigned ipath_debug; /* debugging bit mask */
+
+#endif /* _IPATH_LAYER_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
new file mode 100644
index 000000000000..f7f8391fe43f
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_smi.h>
+
+#include "ipath_kernel.h"
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+#define IB_SMP_UNSUP_VERSION __constant_htons(0x0004)
+#define IB_SMP_UNSUP_METHOD __constant_htons(0x0008)
+#define IB_SMP_UNSUP_METH_ATTR __constant_htons(0x000C)
+#define IB_SMP_INVALID_FIELD __constant_htons(0x001C)
+
+static int reply(struct ib_smp *smp)
+{
+ /*
+ * The verbs framework will handle the directed/LID route
+ * packet changes.
+ */
+ smp->method = IB_MGMT_METHOD_GET_RESP;
+ if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+ smp->status |= IB_SMP_DIRECTION;
+ return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+}
+
+static int recv_subn_get_nodedescription(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ if (smp->attr_mod)
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ strncpy(smp->data, ibdev->node_desc, sizeof(smp->data));
+
+ return reply(smp);
+}
+
+struct nodeinfo {
+ u8 base_version;
+ u8 class_version;
+ u8 node_type;
+ u8 num_ports;
+ __be64 sys_guid;
+ __be64 node_guid;
+ __be64 port_guid;
+ __be16 partition_cap;
+ __be16 device_id;
+ __be32 revision;
+ u8 local_port_num;
+ u8 vendor_id[3];
+} __attribute__ ((packed));
+
+static int recv_subn_get_nodeinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct nodeinfo *nip = (struct nodeinfo *)&smp->data;
+ struct ipath_devdata *dd = to_idev(ibdev)->dd;
+ u32 vendor, boardid, majrev, minrev;
+
+ if (smp->attr_mod)
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ nip->base_version = 1;
+ nip->class_version = 1;
+ nip->node_type = 1; /* channel adapter */
+ /*
+ * XXX The num_ports value will need a layer function to get
+ * the value if we ever have more than one IB port on a chip.
+ * We will also need to get the GUID for the port.
+ */
+ nip->num_ports = ibdev->phys_port_cnt;
+ /* This is already in network order */
+ nip->sys_guid = to_idev(ibdev)->sys_image_guid;
+ nip->node_guid = ipath_layer_get_guid(dd);
+ nip->port_guid = nip->sys_guid;
+ nip->partition_cap = cpu_to_be16(ipath_layer_get_npkeys(dd));
+ nip->device_id = cpu_to_be16(ipath_layer_get_deviceid(dd));
+ ipath_layer_query_device(dd, &vendor, &boardid, &majrev, &minrev);
+ nip->revision = cpu_to_be32((majrev << 16) | minrev);
+ nip->local_port_num = port;
+ nip->vendor_id[0] = 0;
+ nip->vendor_id[1] = vendor >> 8;
+ nip->vendor_id[2] = vendor;
+
+ return reply(smp);
+}
+
+static int recv_subn_get_guidinfo(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ u32 startgx = 8 * be32_to_cpu(smp->attr_mod);
+ __be64 *p = (__be64 *) smp->data;
+
+ /* 32 blocks of 8 64-bit GUIDs per block */
+
+ memset(smp->data, 0, sizeof(smp->data));
+
+ /*
+ * We only support one GUID for now. If this changes, the
+ * portinfo.guid_cap field needs to be updated too.
+ */
+ if (startgx == 0)
+ /* The first is a copy of the read-only HW GUID. */
+ *p = ipath_layer_get_guid(to_idev(ibdev)->dd);
+ else
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ return reply(smp);
+}
+
+struct port_info {
+ __be64 mkey;
+ __be64 gid_prefix;
+ __be16 lid;
+ __be16 sm_lid;
+ __be32 cap_mask;
+ __be16 diag_code;
+ __be16 mkey_lease_period;
+ u8 local_port_num;
+ u8 link_width_enabled;
+ u8 link_width_supported;
+ u8 link_width_active;
+ u8 linkspeed_portstate; /* 4 bits, 4 bits */
+ u8 portphysstate_linkdown; /* 4 bits, 4 bits */
+ u8 mkeyprot_resv_lmc; /* 2 bits, 3, 3 */
+ u8 linkspeedactive_enabled; /* 4 bits, 4 bits */
+ u8 neighbormtu_mastersmsl; /* 4 bits, 4 bits */
+ u8 vlcap_inittype; /* 4 bits, 4 bits */
+ u8 vl_high_limit;
+ u8 vl_arb_high_cap;
+ u8 vl_arb_low_cap;
+ u8 inittypereply_mtucap; /* 4 bits, 4 bits */
+ u8 vlstallcnt_hoqlife; /* 3 bits, 5 bits */
+ u8 operationalvl_pei_peo_fpi_fpo; /* 4 bits, 1, 1, 1, 1 */
+ __be16 mkey_violations;
+ __be16 pkey_violations;
+ __be16 qkey_violations;
+ u8 guid_cap;
+ u8 clientrereg_resv_subnetto; /* 1 bit, 2 bits, 5 */
+ u8 resv_resptimevalue; /* 3 bits, 5 bits */
+ u8 localphyerrors_overrunerrors; /* 4 bits, 4 bits */
+ __be16 max_credit_hint;
+ u8 resv;
+ u8 link_roundtrip_latency[3];
+} __attribute__ ((packed));
+
+static int recv_subn_get_portinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ipath_ibdev *dev;
+ struct port_info *pip = (struct port_info *)smp->data;
+ u16 lid;
+ u8 ibcstat;
+ u8 mtu;
+ int ret;
+
+ if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) {
+ smp->status |= IB_SMP_INVALID_FIELD;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ dev = to_idev(ibdev);
+
+ /* Clear all fields. Only set the non-zero fields. */
+ memset(smp->data, 0, sizeof(smp->data));
+
+ /* Only return the mkey if the protection field allows it. */
+ if (smp->method == IB_MGMT_METHOD_SET || dev->mkey == smp->mkey ||
+ (dev->mkeyprot_resv_lmc >> 6) == 0)
+ pip->mkey = dev->mkey;
+ pip->gid_prefix = dev->gid_prefix;
+ lid = ipath_layer_get_lid(dev->dd);
+ pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE;
+ pip->sm_lid = cpu_to_be16(dev->sm_lid);
+ pip->cap_mask = cpu_to_be32(dev->port_cap_flags);
+ /* pip->diag_code; */
+ pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period);
+ pip->local_port_num = port;
+ pip->link_width_enabled = dev->link_width_enabled;
+ pip->link_width_supported = 3; /* 1x or 4x */
+ pip->link_width_active = 2; /* 4x */
+ pip->linkspeed_portstate = 0x10; /* 2.5Gbps */
+ ibcstat = ipath_layer_get_lastibcstat(dev->dd);
+ pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1;
+ pip->portphysstate_linkdown =
+ (ipath_cvt_physportstate[ibcstat & 0xf] << 4) |
+ (ipath_layer_get_linkdowndefaultstate(dev->dd) ? 1 : 2);
+ pip->mkeyprot_resv_lmc = dev->mkeyprot_resv_lmc;
+ pip->linkspeedactive_enabled = 0x11; /* 2.5Gbps, 2.5Gbps */
+ switch (ipath_layer_get_ibmtu(dev->dd)) {
+ case 4096:
+ mtu = IB_MTU_4096;
+ break;
+ case 2048:
+ mtu = IB_MTU_2048;
+ break;
+ case 1024:
+ mtu = IB_MTU_1024;
+ break;
+ case 512:
+ mtu = IB_MTU_512;
+ break;
+ case 256:
+ mtu = IB_MTU_256;
+ break;
+ default: /* oops, something is wrong */
+ mtu = IB_MTU_2048;
+ break;
+ }
+ pip->neighbormtu_mastersmsl = (mtu << 4) | dev->sm_sl;
+ pip->vlcap_inittype = 0x10; /* VLCap = VL0, InitType = 0 */
+ pip->vl_high_limit = dev->vl_high_limit;
+ /* pip->vl_arb_high_cap; // only one VL */
+ /* pip->vl_arb_low_cap; // only one VL */
+ /* InitTypeReply = 0 */
+ pip->inittypereply_mtucap = IB_MTU_4096;
+ // HCAs ignore VLStallCount and HOQLife
+ /* pip->vlstallcnt_hoqlife; */
+ pip->operationalvl_pei_peo_fpi_fpo = 0x10; /* OVLs = 1 */
+ pip->mkey_violations = cpu_to_be16(dev->mkey_violations);
+ /* P_KeyViolations are counted by hardware. */
+ pip->pkey_violations =
+ cpu_to_be16((ipath_layer_get_cr_errpkey(dev->dd) -
+ dev->n_pkey_violations) & 0xFFFF);
+ pip->qkey_violations = cpu_to_be16(dev->qkey_violations);
+ /* Only the hardware GUID is supported for now */
+ pip->guid_cap = 1;
+ pip->clientrereg_resv_subnetto = dev->subnet_timeout;
+ /* 32.768 usec. response time (guessing) */
+ pip->resv_resptimevalue = 3;
+ pip->localphyerrors_overrunerrors =
+ (ipath_layer_get_phyerrthreshold(dev->dd) << 4) |
+ ipath_layer_get_overrunthreshold(dev->dd);
+ /* pip->max_credit_hint; */
+ /* pip->link_roundtrip_latency[3]; */
+
+ ret = reply(smp);
+
+bail:
+ return ret;
+}
+
+static int recv_subn_get_pkeytable(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
+ u16 *p = (u16 *) smp->data;
+ __be16 *q = (__be16 *) smp->data;
+
+ /* 64 blocks of 32 16-bit P_Key entries */
+
+ memset(smp->data, 0, sizeof(smp->data));
+ if (startpx == 0) {
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned i, n = ipath_layer_get_npkeys(dev->dd);
+
+ ipath_layer_get_pkeys(dev->dd, p);
+
+ for (i = 0; i < n; i++)
+ q[i] = cpu_to_be16(p[i]);
+ } else
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ return reply(smp);
+}
+
+static int recv_subn_set_guidinfo(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ /* The only GUID we support is the first read-only entry. */
+ return recv_subn_get_guidinfo(smp, ibdev);
+}
+
+/**
+ * recv_subn_set_portinfo - set port information
+ * @smp: the incoming SM packet
+ * @ibdev: the infiniband device
+ * @port: the port on the device
+ *
+ * Set Portinfo (see ch. 14.2.5.6).
+ */
+static int recv_subn_set_portinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct port_info *pip = (struct port_info *)smp->data;
+ struct ib_event event;
+ struct ipath_ibdev *dev;
+ u32 flags;
+ char clientrereg = 0;
+ u16 lid, smlid;
+ u8 lwe;
+ u8 lse;
+ u8 state;
+ u16 lstate;
+ u32 mtu;
+ int ret;
+
+ if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt)
+ goto err;
+
+ dev = to_idev(ibdev);
+ event.device = ibdev;
+ event.element.port_num = port;
+
+ dev->mkey = pip->mkey;
+ dev->gid_prefix = pip->gid_prefix;
+ dev->mkey_lease_period = be16_to_cpu(pip->mkey_lease_period);
+
+ lid = be16_to_cpu(pip->lid);
+ if (lid != ipath_layer_get_lid(dev->dd)) {
+ /* Must be a valid unicast LID address. */
+ if (lid == 0 || lid >= IPS_MULTICAST_LID_BASE)
+ goto err;
+ ipath_set_sps_lid(dev->dd, lid, pip->mkeyprot_resv_lmc & 7);
+ event.event = IB_EVENT_LID_CHANGE;
+ ib_dispatch_event(&event);
+ }
+
+ smlid = be16_to_cpu(pip->sm_lid);
+ if (smlid != dev->sm_lid) {
+ /* Must be a valid unicast LID address. */
+ if (smlid == 0 || smlid >= IPS_MULTICAST_LID_BASE)
+ goto err;
+ dev->sm_lid = smlid;
+ event.event = IB_EVENT_SM_CHANGE;
+ ib_dispatch_event(&event);
+ }
+
+ /* Only 4x supported but allow 1x or 4x to be set (see 14.2.6.6). */
+ lwe = pip->link_width_enabled;
+ if ((lwe >= 4 && lwe <= 8) || (lwe >= 0xC && lwe <= 0xFE))
+ goto err;
+ if (lwe == 0xFF)
+ dev->link_width_enabled = 3; /* 1x or 4x */
+ else if (lwe)
+ dev->link_width_enabled = lwe;
+
+ /* Only 2.5 Gbs supported. */
+ lse = pip->linkspeedactive_enabled & 0xF;
+ if (lse >= 2 && lse <= 0xE)
+ goto err;
+
+ /* Set link down default state. */
+ switch (pip->portphysstate_linkdown & 0xF) {
+ case 0: /* NOP */
+ break;
+ case 1: /* SLEEP */
+ if (ipath_layer_set_linkdowndefaultstate(dev->dd, 1))
+ goto err;
+ break;
+ case 2: /* POLL */
+ if (ipath_layer_set_linkdowndefaultstate(dev->dd, 0))
+ goto err;
+ break;
+ default:
+ goto err;
+ }
+
+ dev->mkeyprot_resv_lmc = pip->mkeyprot_resv_lmc;
+ dev->vl_high_limit = pip->vl_high_limit;
+
+ switch ((pip->neighbormtu_mastersmsl >> 4) & 0xF) {
+ case IB_MTU_256:
+ mtu = 256;
+ break;
+ case IB_MTU_512:
+ mtu = 512;
+ break;
+ case IB_MTU_1024:
+ mtu = 1024;
+ break;
+ case IB_MTU_2048:
+ mtu = 2048;
+ break;
+ case IB_MTU_4096:
+ mtu = 4096;
+ break;
+ default:
+ /* XXX We have already partially updated our state! */
+ goto err;
+ }
+ ipath_layer_set_mtu(dev->dd, mtu);
+
+ dev->sm_sl = pip->neighbormtu_mastersmsl & 0xF;
+
+ /* We only support VL0 */
+ if (((pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF) > 1)
+ goto err;
+
+ if (pip->mkey_violations == 0)
+ dev->mkey_violations = 0;
+
+ /*
+ * Hardware counter can't be reset so snapshot and subtract
+ * later.
+ */
+ if (pip->pkey_violations == 0)
+ dev->n_pkey_violations =
+ ipath_layer_get_cr_errpkey(dev->dd);
+
+ if (pip->qkey_violations == 0)
+ dev->qkey_violations = 0;
+
+ if (ipath_layer_set_phyerrthreshold(
+ dev->dd,
+ (pip->localphyerrors_overrunerrors >> 4) & 0xF))
+ goto err;
+
+ if (ipath_layer_set_overrunthreshold(
+ dev->dd,
+ (pip->localphyerrors_overrunerrors & 0xF)))
+ goto err;
+
+ dev->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
+
+ if (pip->clientrereg_resv_subnetto & 0x80) {
+ clientrereg = 1;
+ event.event = IB_EVENT_LID_CHANGE;
+ ib_dispatch_event(&event);
+ }
+
+ /*
+ * Do the port state change now that the other link parameters
+ * have been set.
+ * Changing the port physical state only makes sense if the link
+ * is down or is being set to down.
+ */
+ state = pip->linkspeed_portstate & 0xF;
+ flags = ipath_layer_get_flags(dev->dd);
+ lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
+ if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
+ goto err;
+
+ /*
+ * Only state changes of DOWN, ARM, and ACTIVE are valid
+ * and must be in the correct state to take effect (see 7.2.6).
+ */
+ switch (state) {
+ case IB_PORT_NOP:
+ if (lstate == 0)
+ break;
+ /* FALLTHROUGH */
+ case IB_PORT_DOWN:
+ if (lstate == 0)
+ if (ipath_layer_get_linkdowndefaultstate(dev->dd))
+ lstate = IPATH_IB_LINKDOWN_SLEEP;
+ else
+ lstate = IPATH_IB_LINKDOWN;
+ else if (lstate == 1)
+ lstate = IPATH_IB_LINKDOWN_SLEEP;
+ else if (lstate == 2)
+ lstate = IPATH_IB_LINKDOWN;
+ else if (lstate == 3)
+ lstate = IPATH_IB_LINKDOWN_DISABLE;
+ else
+ goto err;
+ ipath_layer_set_linkstate(dev->dd, lstate);
+ if (flags & IPATH_LINKACTIVE) {
+ event.event = IB_EVENT_PORT_ERR;
+ ib_dispatch_event(&event);
+ }
+ break;
+ case IB_PORT_ARMED:
+ if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))
+ break;
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKARM);
+ if (flags & IPATH_LINKACTIVE) {
+ event.event = IB_EVENT_PORT_ERR;
+ ib_dispatch_event(&event);
+ }
+ break;
+ case IB_PORT_ACTIVE:
+ if (!(flags & IPATH_LINKARMED))
+ break;
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKACTIVE);
+ event.event = IB_EVENT_PORT_ACTIVE;
+ ib_dispatch_event(&event);
+ break;
+ default:
+ /* XXX We have already partially updated our state! */
+ goto err;
+ }
+
+ ret = recv_subn_get_portinfo(smp, ibdev, port);
+
+ if (clientrereg)
+ pip->clientrereg_resv_subnetto |= 0x80;
+
+ goto done;
+
+err:
+ smp->status |= IB_SMP_INVALID_FIELD;
+ ret = recv_subn_get_portinfo(smp, ibdev, port);
+
+done:
+ return ret;
+}
+
+static int recv_subn_set_pkeytable(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
+ __be16 *p = (__be16 *) smp->data;
+ u16 *q = (u16 *) smp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned i, n = ipath_layer_get_npkeys(dev->dd);
+
+ for (i = 0; i < n; i++)
+ q[i] = be16_to_cpu(p[i]);
+
+ if (startpx != 0 ||
+ ipath_layer_set_pkeys(dev->dd, q) != 0)
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ return recv_subn_get_pkeytable(smp, ibdev);
+}
+
+#define IB_PMA_CLASS_PORT_INFO __constant_htons(0x0001)
+#define IB_PMA_PORT_SAMPLES_CONTROL __constant_htons(0x0010)
+#define IB_PMA_PORT_SAMPLES_RESULT __constant_htons(0x0011)
+#define IB_PMA_PORT_COUNTERS __constant_htons(0x0012)
+#define IB_PMA_PORT_COUNTERS_EXT __constant_htons(0x001D)
+#define IB_PMA_PORT_SAMPLES_RESULT_EXT __constant_htons(0x001E)
+
+struct ib_perf {
+ u8 base_version;
+ u8 mgmt_class;
+ u8 class_version;
+ u8 method;
+ __be16 status;
+ __be16 unused;
+ __be64 tid;
+ __be16 attr_id;
+ __be16 resv;
+ __be32 attr_mod;
+ u8 reserved[40];
+ u8 data[192];
+} __attribute__ ((packed));
+
+struct ib_pma_classportinfo {
+ u8 base_version;
+ u8 class_version;
+ __be16 cap_mask;
+ u8 reserved[3];
+ u8 resp_time_value; /* only lower 5 bits */
+ union ib_gid redirect_gid;
+ __be32 redirect_tc_sl_fl; /* 8, 4, 20 bits respectively */
+ __be16 redirect_lid;
+ __be16 redirect_pkey;
+ __be32 redirect_qp; /* only lower 24 bits */
+ __be32 redirect_qkey;
+ union ib_gid trap_gid;
+ __be32 trap_tc_sl_fl; /* 8, 4, 20 bits respectively */
+ __be16 trap_lid;
+ __be16 trap_pkey;
+ __be32 trap_hl_qp; /* 8, 24 bits respectively */
+ __be32 trap_qkey;
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplescontrol {
+ u8 opcode;
+ u8 port_select;
+ u8 tick;
+ u8 counter_width; /* only lower 3 bits */
+ __be32 counter_mask0_9; /* 2, 10 * 3, bits */
+ __be16 counter_mask10_14; /* 1, 5 * 3, bits */
+ u8 sample_mechanisms;
+ u8 sample_status; /* only lower 2 bits */
+ __be64 option_mask;
+ __be64 vendor_mask;
+ __be32 sample_start;
+ __be32 sample_interval;
+ __be16 tag;
+ __be16 counter_select[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplesresult {
+ __be16 tag;
+ __be16 sample_status; /* only lower 2 bits */
+ __be32 counter[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplesresult_ext {
+ __be16 tag;
+ __be16 sample_status; /* only lower 2 bits */
+ __be32 extended_width; /* only upper 2 bits */
+ __be64 counter[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portcounters {
+ u8 reserved;
+ u8 port_select;
+ __be16 counter_select;
+ __be16 symbol_error_counter;
+ u8 link_error_recovery_counter;
+ u8 link_downed_counter;
+ __be16 port_rcv_errors;
+ __be16 port_rcv_remphys_errors;
+ __be16 port_rcv_switch_relay_errors;
+ __be16 port_xmit_discards;
+ u8 port_xmit_constraint_errors;
+ u8 port_rcv_constraint_errors;
+ u8 reserved1;
+ u8 lli_ebor_errors; /* 4, 4, bits */
+ __be16 reserved2;
+ __be16 vl15_dropped;
+ __be32 port_xmit_data;
+ __be32 port_rcv_data;
+ __be32 port_xmit_packets;
+ __be32 port_rcv_packets;
+} __attribute__ ((packed));
+
+#define IB_PMA_SEL_SYMBOL_ERROR __constant_htons(0x0001)
+#define IB_PMA_SEL_LINK_ERROR_RECOVERY __constant_htons(0x0002)
+#define IB_PMA_SEL_LINK_DOWNED __constant_htons(0x0004)
+#define IB_PMA_SEL_PORT_RCV_ERRORS __constant_htons(0x0008)
+#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS __constant_htons(0x0010)
+#define IB_PMA_SEL_PORT_XMIT_DISCARDS __constant_htons(0x0040)
+#define IB_PMA_SEL_PORT_XMIT_DATA __constant_htons(0x1000)
+#define IB_PMA_SEL_PORT_RCV_DATA __constant_htons(0x2000)
+#define IB_PMA_SEL_PORT_XMIT_PACKETS __constant_htons(0x4000)
+#define IB_PMA_SEL_PORT_RCV_PACKETS __constant_htons(0x8000)
+
+struct ib_pma_portcounters_ext {
+ u8 reserved;
+ u8 port_select;
+ __be16 counter_select;
+ __be32 reserved1;
+ __be64 port_xmit_data;
+ __be64 port_rcv_data;
+ __be64 port_xmit_packets;
+ __be64 port_rcv_packets;
+ __be64 port_unicast_xmit_packets;
+ __be64 port_unicast_rcv_packets;
+ __be64 port_multicast_xmit_packets;
+ __be64 port_multicast_rcv_packets;
+} __attribute__ ((packed));
+
+#define IB_PMA_SELX_PORT_XMIT_DATA __constant_htons(0x0001)
+#define IB_PMA_SELX_PORT_RCV_DATA __constant_htons(0x0002)
+#define IB_PMA_SELX_PORT_XMIT_PACKETS __constant_htons(0x0004)
+#define IB_PMA_SELX_PORT_RCV_PACKETS __constant_htons(0x0008)
+#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS __constant_htons(0x0010)
+#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS __constant_htons(0x0020)
+#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS __constant_htons(0x0040)
+#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS __constant_htons(0x0080)
+
+static int recv_pma_get_classportinfo(struct ib_perf *pmp)
+{
+ struct ib_pma_classportinfo *p =
+ (struct ib_pma_classportinfo *)pmp->data;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ if (pmp->attr_mod != 0)
+ pmp->status |= IB_SMP_INVALID_FIELD;
+
+ /* Indicate AllPortSelect is valid (only one port anyway) */
+ p->cap_mask = __constant_cpu_to_be16(1 << 8);
+ p->base_version = 1;
+ p->class_version = 1;
+ /*
+ * Expected response time is 4.096 usec. * 2^18 == 1.073741824
+ * sec.
+ */
+ p->resp_time_value = 18;
+
+ return reply((struct ib_smp *) pmp);
+}
+
+/*
+ * The PortSamplesControl.CounterMasks field is an array of 3 bit fields
+ * which specify the N'th counter's capabilities. See ch. 16.1.3.2.
+ * We support 5 counters which only count the mandatory quantities.
+ */
+#define COUNTER_MASK(q, n) (q << ((9 - n) * 3))
+#define COUNTER_MASK0_9 \
+ __constant_cpu_to_be32(COUNTER_MASK(1, 0) | \
+ COUNTER_MASK(1, 1) | \
+ COUNTER_MASK(1, 2) | \
+ COUNTER_MASK(1, 3) | \
+ COUNTER_MASK(1, 4))
+
+static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portsamplescontrol *p =
+ (struct ib_pma_portsamplescontrol *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned long flags;
+ u8 port_select = p->port_select;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ p->port_select = port_select;
+ if (pmp->attr_mod != 0 ||
+ (port_select != port && port_select != 0xFF))
+ pmp->status |= IB_SMP_INVALID_FIELD;
+ /*
+ * Ticks are 10x the link transfer period which for 2.5Gbs is 4
+ * nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample
+ * intervals are counted in ticks. Since we use Linux timers, that
+ * count in jiffies, we can't sample for less than 1000 ticks if HZ
+ * == 1000 (4000 ticks if HZ is 250).
+ */
+ /* XXX This is WRONG. */
+ p->tick = 250; /* 1 usec. */
+ p->counter_width = 4; /* 32 bit counters */
+ p->counter_mask0_9 = COUNTER_MASK0_9;
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ p->sample_status = dev->pma_sample_status;
+ p->sample_start = cpu_to_be32(dev->pma_sample_start);
+ p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
+ p->tag = cpu_to_be16(dev->pma_tag);
+ p->counter_select[0] = dev->pma_counter_select[0];
+ p->counter_select[1] = dev->pma_counter_select[1];
+ p->counter_select[2] = dev->pma_counter_select[2];
+ p->counter_select[3] = dev->pma_counter_select[3];
+ p->counter_select[4] = dev->pma_counter_select[4];
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portsamplescontrol *p =
+ (struct ib_pma_portsamplescontrol *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned long flags;
+ u32 start;
+ int ret;
+
+ if (pmp->attr_mod != 0 ||
+ (p->port_select != port && p->port_select != 0xFF)) {
+ pmp->status |= IB_SMP_INVALID_FIELD;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ start = be32_to_cpu(p->sample_start);
+ if (start != 0) {
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
+ dev->pma_sample_status =
+ IB_PMA_SAMPLE_STATUS_STARTED;
+ dev->pma_sample_start = start;
+ dev->pma_sample_interval =
+ be32_to_cpu(p->sample_interval);
+ dev->pma_tag = be16_to_cpu(p->tag);
+ if (p->counter_select[0])
+ dev->pma_counter_select[0] =
+ p->counter_select[0];
+ if (p->counter_select[1])
+ dev->pma_counter_select[1] =
+ p->counter_select[1];
+ if (p->counter_select[2])
+ dev->pma_counter_select[2] =
+ p->counter_select[2];
+ if (p->counter_select[3])
+ dev->pma_counter_select[3] =
+ p->counter_select[3];
+ if (p->counter_select[4])
+ dev->pma_counter_select[4] =
+ p->counter_select[4];
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+ }
+ ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
+
+bail:
+ return ret;
+}
+
+static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
+{
+ u64 ret;
+
+ switch (sel) {
+ case IB_PMA_PORT_XMIT_DATA:
+ ret = dev->ipath_sword;
+ break;
+ case IB_PMA_PORT_RCV_DATA:
+ ret = dev->ipath_rword;
+ break;
+ case IB_PMA_PORT_XMIT_PKTS:
+ ret = dev->ipath_spkts;
+ break;
+ case IB_PMA_PORT_RCV_PKTS:
+ ret = dev->ipath_rpkts;
+ break;
+ case IB_PMA_PORT_XMIT_WAIT:
+ ret = dev->ipath_xmit_wait;
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+ struct ib_device *ibdev)
+{
+ struct ib_pma_portsamplesresult *p =
+ (struct ib_pma_portsamplesresult *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int i;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+ p->tag = cpu_to_be16(dev->pma_tag);
+ p->sample_status = cpu_to_be16(dev->pma_sample_status);
+ for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+ p->counter[i] = cpu_to_be32(
+ get_counter(dev, dev->pma_counter_select[i]));
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+ struct ib_device *ibdev)
+{
+ struct ib_pma_portsamplesresult_ext *p =
+ (struct ib_pma_portsamplesresult_ext *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int i;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+ p->tag = cpu_to_be16(dev->pma_tag);
+ p->sample_status = cpu_to_be16(dev->pma_sample_status);
+ /* 64 bits */
+ p->extended_width = __constant_cpu_to_be32(0x80000000);
+ for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+ p->counter[i] = cpu_to_be64(
+ get_counter(dev, dev->pma_counter_select[i]));
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portcounters(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+ pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ struct ipath_layer_counters cntrs;
+ u8 port_select = p->port_select;
+
+ ipath_layer_get_counters(dev->dd, &cntrs);
+
+ /* Adjust counters for any resets done. */
+ cntrs.symbol_error_counter -= dev->n_symbol_error_counter;
+ cntrs.link_error_recovery_counter -=
+ dev->n_link_error_recovery_counter;
+ cntrs.link_downed_counter -= dev->n_link_downed_counter;
+ cntrs.port_rcv_errors += dev->rcv_errors;
+ cntrs.port_rcv_errors -= dev->n_port_rcv_errors;
+ cntrs.port_rcv_remphys_errors -= dev->n_port_rcv_remphys_errors;
+ cntrs.port_xmit_discards -= dev->n_port_xmit_discards;
+ cntrs.port_xmit_data -= dev->n_port_xmit_data;
+ cntrs.port_rcv_data -= dev->n_port_rcv_data;
+ cntrs.port_xmit_packets -= dev->n_port_xmit_packets;
+ cntrs.port_rcv_packets -= dev->n_port_rcv_packets;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ p->port_select = port_select;
+ if (pmp->attr_mod != 0 ||
+ (port_select != port && port_select != 0xFF))
+ pmp->status |= IB_SMP_INVALID_FIELD;
+
+ if (cntrs.symbol_error_counter > 0xFFFFUL)
+ p->symbol_error_counter = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->symbol_error_counter =
+ cpu_to_be16((u16)cntrs.symbol_error_counter);
+ if (cntrs.link_error_recovery_counter > 0xFFUL)
+ p->link_error_recovery_counter = 0xFF;
+ else
+ p->link_error_recovery_counter =
+ (u8)cntrs.link_error_recovery_counter;
+ if (cntrs.link_downed_counter > 0xFFUL)
+ p->link_downed_counter = 0xFF;
+ else
+ p->link_downed_counter = (u8)cntrs.link_downed_counter;
+ if (cntrs.port_rcv_errors > 0xFFFFUL)
+ p->port_rcv_errors = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->port_rcv_errors =
+ cpu_to_be16((u16) cntrs.port_rcv_errors);
+ if (cntrs.port_rcv_remphys_errors > 0xFFFFUL)
+ p->port_rcv_remphys_errors = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->port_rcv_remphys_errors =
+ cpu_to_be16((u16)cntrs.port_rcv_remphys_errors);
+ if (cntrs.port_xmit_discards > 0xFFFFUL)
+ p->port_xmit_discards = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->port_xmit_discards =
+ cpu_to_be16((u16)cntrs.port_xmit_discards);
+ if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
+ p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data);
+ if (cntrs.port_rcv_data > 0xFFFFFFFFUL)
+ p->port_rcv_data = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data);
+ if (cntrs.port_xmit_packets > 0xFFFFFFFFUL)
+ p->port_xmit_packets = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_xmit_packets =
+ cpu_to_be32((u32)cntrs.port_xmit_packets);
+ if (cntrs.port_rcv_packets > 0xFFFFFFFFUL)
+ p->port_rcv_packets = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_rcv_packets =
+ cpu_to_be32((u32) cntrs.port_rcv_packets);
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters_ext *p =
+ (struct ib_pma_portcounters_ext *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ u64 swords, rwords, spkts, rpkts, xwait;
+ u8 port_select = p->port_select;
+
+ ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
+ &rpkts, &xwait);
+
+ /* Adjust counters for any resets done. */
+ swords -= dev->n_port_xmit_data;
+ rwords -= dev->n_port_rcv_data;
+ spkts -= dev->n_port_xmit_packets;
+ rpkts -= dev->n_port_rcv_packets;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ p->port_select = port_select;
+ if (pmp->attr_mod != 0 ||
+ (port_select != port && port_select != 0xFF))
+ pmp->status |= IB_SMP_INVALID_FIELD;
+
+ p->port_xmit_data = cpu_to_be64(swords);
+ p->port_rcv_data = cpu_to_be64(rwords);
+ p->port_xmit_packets = cpu_to_be64(spkts);
+ p->port_rcv_packets = cpu_to_be64(rpkts);
+ p->port_unicast_xmit_packets = cpu_to_be64(dev->n_unicast_xmit);
+ p->port_unicast_rcv_packets = cpu_to_be64(dev->n_unicast_rcv);
+ p->port_multicast_xmit_packets = cpu_to_be64(dev->n_multicast_xmit);
+ p->port_multicast_rcv_packets = cpu_to_be64(dev->n_multicast_rcv);
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_set_portcounters(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+ pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ struct ipath_layer_counters cntrs;
+
+ /*
+ * Since the HW doesn't support clearing counters, we save the
+ * current count and subtract it from future responses.
+ */
+ ipath_layer_get_counters(dev->dd, &cntrs);
+
+ if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR)
+ dev->n_symbol_error_counter = cntrs.symbol_error_counter;
+
+ if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY)
+ dev->n_link_error_recovery_counter =
+ cntrs.link_error_recovery_counter;
+
+ if (p->counter_select & IB_PMA_SEL_LINK_DOWNED)
+ dev->n_link_downed_counter = cntrs.link_downed_counter;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS)
+ dev->n_port_rcv_errors =
+ cntrs.port_rcv_errors + dev->rcv_errors;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS)
+ dev->n_port_rcv_remphys_errors =
+ cntrs.port_rcv_remphys_errors;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS)
+ dev->n_port_xmit_discards = cntrs.port_xmit_discards;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
+ dev->n_port_xmit_data = cntrs.port_xmit_data;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA)
+ dev->n_port_rcv_data = cntrs.port_rcv_data;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS)
+ dev->n_port_xmit_packets = cntrs.port_xmit_packets;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS)
+ dev->n_port_rcv_packets = cntrs.port_rcv_packets;
+
+ return recv_pma_get_portcounters(pmp, ibdev, port);
+}
+
+static int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+ pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ u64 swords, rwords, spkts, rpkts, xwait;
+
+ ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
+ &rpkts, &xwait);
+
+ if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA)
+ dev->n_port_xmit_data = swords;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA)
+ dev->n_port_rcv_data = rwords;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS)
+ dev->n_port_xmit_packets = spkts;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS)
+ dev->n_port_rcv_packets = rpkts;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS)
+ dev->n_unicast_xmit = 0;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS)
+ dev->n_unicast_rcv = 0;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS)
+ dev->n_multicast_xmit = 0;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS)
+ dev->n_multicast_rcv = 0;
+
+ return recv_pma_get_portcounters_ext(pmp, ibdev, port);
+}
+
+static int process_subn(struct ib_device *ibdev, int mad_flags,
+ u8 port_num, struct ib_mad *in_mad,
+ struct ib_mad *out_mad)
+{
+ struct ib_smp *smp = (struct ib_smp *)out_mad;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ *out_mad = *in_mad;
+ if (smp->class_version != 1) {
+ smp->status |= IB_SMP_UNSUP_VERSION;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ /* Is the mkey in the process of expiring? */
+ if (dev->mkey_lease_timeout && jiffies >= dev->mkey_lease_timeout) {
+ /* Clear timeout and mkey protection field. */
+ dev->mkey_lease_timeout = 0;
+ dev->mkeyprot_resv_lmc &= 0x3F;
+ }
+
+ /*
+ * M_Key checking depends on
+ * Portinfo:M_Key_protect_bits
+ */
+ if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && dev->mkey != 0 &&
+ dev->mkey != smp->mkey &&
+ (smp->method == IB_MGMT_METHOD_SET ||
+ (smp->method == IB_MGMT_METHOD_GET &&
+ (dev->mkeyprot_resv_lmc >> 7) != 0))) {
+ if (dev->mkey_violations != 0xFFFF)
+ ++dev->mkey_violations;
+ if (dev->mkey_lease_timeout ||
+ dev->mkey_lease_period == 0) {
+ ret = IB_MAD_RESULT_SUCCESS |
+ IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ }
+ dev->mkey_lease_timeout = jiffies +
+ dev->mkey_lease_period * HZ;
+ /* Future: Generate a trap notice. */
+ ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ } else if (dev->mkey_lease_timeout)
+ dev->mkey_lease_timeout = 0;
+
+ switch (smp->method) {
+ case IB_MGMT_METHOD_GET:
+ switch (smp->attr_id) {
+ case IB_SMP_ATTR_NODE_DESC:
+ ret = recv_subn_get_nodedescription(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_NODE_INFO:
+ ret = recv_subn_get_nodeinfo(smp, ibdev, port_num);
+ goto bail;
+ case IB_SMP_ATTR_GUID_INFO:
+ ret = recv_subn_get_guidinfo(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_PORT_INFO:
+ ret = recv_subn_get_portinfo(smp, ibdev, port_num);
+ goto bail;
+ case IB_SMP_ATTR_PKEY_TABLE:
+ ret = recv_subn_get_pkeytable(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_SM_INFO:
+ if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
+ ret = IB_MAD_RESULT_SUCCESS |
+ IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ }
+ if (dev->port_cap_flags & IB_PORT_SM) {
+ ret = IB_MAD_RESULT_SUCCESS;
+ goto bail;
+ }
+ /* FALLTHROUGH */
+ default:
+ smp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_SET:
+ switch (smp->attr_id) {
+ case IB_SMP_ATTR_GUID_INFO:
+ ret = recv_subn_set_guidinfo(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_PORT_INFO:
+ ret = recv_subn_set_portinfo(smp, ibdev, port_num);
+ goto bail;
+ case IB_SMP_ATTR_PKEY_TABLE:
+ ret = recv_subn_set_pkeytable(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_SM_INFO:
+ if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
+ ret = IB_MAD_RESULT_SUCCESS |
+ IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ }
+ if (dev->port_cap_flags & IB_PORT_SM) {
+ ret = IB_MAD_RESULT_SUCCESS;
+ goto bail;
+ }
+ /* FALLTHROUGH */
+ default:
+ smp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_GET_RESP:
+ /*
+ * The ib_mad module will call us to process responses
+ * before checking for other consumers.
+ * Just tell the caller to process it normally.
+ */
+ ret = IB_MAD_RESULT_FAILURE;
+ goto bail;
+ default:
+ smp->status |= IB_SMP_UNSUP_METHOD;
+ ret = reply(smp);
+ }
+
+bail:
+ return ret;
+}
+
+static int process_perf(struct ib_device *ibdev, u8 port_num,
+ struct ib_mad *in_mad,
+ struct ib_mad *out_mad)
+{
+ struct ib_perf *pmp = (struct ib_perf *)out_mad;
+ int ret;
+
+ *out_mad = *in_mad;
+ if (pmp->class_version != 1) {
+ pmp->status |= IB_SMP_UNSUP_VERSION;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ switch (pmp->method) {
+ case IB_MGMT_METHOD_GET:
+ switch (pmp->attr_id) {
+ case IB_PMA_CLASS_PORT_INFO:
+ ret = recv_pma_get_classportinfo(pmp);
+ goto bail;
+ case IB_PMA_PORT_SAMPLES_CONTROL:
+ ret = recv_pma_get_portsamplescontrol(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_SAMPLES_RESULT:
+ ret = recv_pma_get_portsamplesresult(pmp, ibdev);
+ goto bail;
+ case IB_PMA_PORT_SAMPLES_RESULT_EXT:
+ ret = recv_pma_get_portsamplesresult_ext(pmp,
+ ibdev);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS:
+ ret = recv_pma_get_portcounters(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS_EXT:
+ ret = recv_pma_get_portcounters_ext(pmp, ibdev,
+ port_num);
+ goto bail;
+ default:
+ pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_SET:
+ switch (pmp->attr_id) {
+ case IB_PMA_PORT_SAMPLES_CONTROL:
+ ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS:
+ ret = recv_pma_set_portcounters(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS_EXT:
+ ret = recv_pma_set_portcounters_ext(pmp, ibdev,
+ port_num);
+ goto bail;
+ default:
+ pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_GET_RESP:
+ /*
+ * The ib_mad module will call us to process responses
+ * before checking for other consumers.
+ * Just tell the caller to process it normally.
+ */
+ ret = IB_MAD_RESULT_FAILURE;
+ goto bail;
+ default:
+ pmp->status |= IB_SMP_UNSUP_METHOD;
+ ret = reply((struct ib_smp *) pmp);
+ }
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_process_mad - process an incoming MAD packet
+ * @ibdev: the infiniband device this packet came in on
+ * @mad_flags: MAD flags
+ * @port_num: the port number this packet came in on
+ * @in_wc: the work completion entry for this packet
+ * @in_grh: the global route header for this packet
+ * @in_mad: the incoming MAD
+ * @out_mad: any outgoing MAD reply
+ *
+ * Returns IB_MAD_RESULT_SUCCESS if this is a MAD that we are not
+ * interested in processing.
+ *
+ * Note that the verbs framework has already done the MAD sanity checks,
+ * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE
+ * MADs.
+ *
+ * This is called by the ib_mad module.
+ */
+int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+ struct ib_wc *in_wc, struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ /*
+ * Snapshot current HW counters to "clear" them.
+ * This should be done when the driver is loaded except that for
+ * some reason we get a zillion errors when brining up the link.
+ */
+ if (dev->rcv_errors == 0) {
+ struct ipath_layer_counters cntrs;
+
+ ipath_layer_get_counters(to_idev(ibdev)->dd, &cntrs);
+ dev->rcv_errors++;
+ dev->n_symbol_error_counter = cntrs.symbol_error_counter;
+ dev->n_link_error_recovery_counter =
+ cntrs.link_error_recovery_counter;
+ dev->n_link_downed_counter = cntrs.link_downed_counter;
+ dev->n_port_rcv_errors = cntrs.port_rcv_errors + 1;
+ dev->n_port_rcv_remphys_errors =
+ cntrs.port_rcv_remphys_errors;
+ dev->n_port_xmit_discards = cntrs.port_xmit_discards;
+ dev->n_port_xmit_data = cntrs.port_xmit_data;
+ dev->n_port_rcv_data = cntrs.port_rcv_data;
+ dev->n_port_xmit_packets = cntrs.port_xmit_packets;
+ dev->n_port_rcv_packets = cntrs.port_rcv_packets;
+ }
+ switch (in_mad->mad_hdr.mgmt_class) {
+ case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
+ case IB_MGMT_CLASS_SUBN_LID_ROUTED:
+ ret = process_subn(ibdev, mad_flags, port_num,
+ in_mad, out_mad);
+ goto bail;
+ case IB_MGMT_CLASS_PERF_MGMT:
+ ret = process_perf(ibdev, port_num, in_mad, out_mad);
+ goto bail;
+ default:
+ ret = IB_MAD_RESULT_SUCCESS;
+ }
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
new file mode 100644
index 000000000000..69ffec66d45d
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_pack.h>
+#include <rdma/ib_smi.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_get_dma_mr - get a DMA memory region
+ * @pd: protection domain for this memory region
+ * @acc: access flags
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc)
+{
+ struct ipath_mr *mr;
+ struct ib_mr *ret;
+
+ mr = kzalloc(sizeof *mr, GFP_KERNEL);
+ if (!mr) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ mr->mr.access_flags = acc;
+ ret = &mr->ibmr;
+
+bail:
+ return ret;
+}
+
+static struct ipath_mr *alloc_mr(int count,
+ struct ipath_lkey_table *lk_table)
+{
+ struct ipath_mr *mr;
+ int m, i = 0;
+
+ /* Allocate struct plus pointers to first level page tables. */
+ m = (count + IPATH_SEGSZ - 1) / IPATH_SEGSZ;
+ mr = kmalloc(sizeof *mr + m * sizeof mr->mr.map[0], GFP_KERNEL);
+ if (!mr)
+ goto done;
+
+ /* Allocate first level page tables. */
+ for (; i < m; i++) {
+ mr->mr.map[i] = kmalloc(sizeof *mr->mr.map[0], GFP_KERNEL);
+ if (!mr->mr.map[i])
+ goto bail;
+ }
+ mr->mr.mapsz = m;
+
+ /*
+ * ib_reg_phys_mr() will initialize mr->ibmr except for
+ * lkey and rkey.
+ */
+ if (!ipath_alloc_lkey(lk_table, &mr->mr))
+ goto bail;
+ mr->ibmr.rkey = mr->ibmr.lkey = mr->mr.lkey;
+
+ goto done;
+
+bail:
+ while (i) {
+ i--;
+ kfree(mr->mr.map[i]);
+ }
+ kfree(mr);
+ mr = NULL;
+
+done:
+ return mr;
+}
+
+/**
+ * ipath_reg_phys_mr - register a physical memory region
+ * @pd: protection domain for this memory region
+ * @buffer_list: pointer to the list of physical buffers to register
+ * @num_phys_buf: the number of physical buffers to register
+ * @iova_start: the starting address passed over IB which maps to this MR
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
+ struct ib_phys_buf *buffer_list,
+ int num_phys_buf, int acc, u64 *iova_start)
+{
+ struct ipath_mr *mr;
+ int n, m, i;
+ struct ib_mr *ret;
+
+ mr = alloc_mr(num_phys_buf, &to_idev(pd->device)->lk_table);
+ if (mr == NULL) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ mr->mr.user_base = *iova_start;
+ mr->mr.iova = *iova_start;
+ mr->mr.length = 0;
+ mr->mr.offset = 0;
+ mr->mr.access_flags = acc;
+ mr->mr.max_segs = num_phys_buf;
+
+ m = 0;
+ n = 0;
+ for (i = 0; i < num_phys_buf; i++) {
+ mr->mr.map[m]->segs[n].vaddr =
+ phys_to_virt(buffer_list[i].addr);
+ mr->mr.map[m]->segs[n].length = buffer_list[i].size;
+ mr->mr.length += buffer_list[i].size;
+ n++;
+ if (n == IPATH_SEGSZ) {
+ m++;
+ n = 0;
+ }
+ }
+
+ ret = &mr->ibmr;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_reg_user_mr - register a userspace memory region
+ * @pd: protection domain for this memory region
+ * @region: the user memory region
+ * @mr_access_flags: access flags for this memory region
+ * @udata: unused by the InfiniPath driver
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+ int mr_access_flags, struct ib_udata *udata)
+{
+ struct ipath_mr *mr;
+ struct ib_umem_chunk *chunk;
+ int n, m, i;
+ struct ib_mr *ret;
+
+ n = 0;
+ list_for_each_entry(chunk, &region->chunk_list, list)
+ n += chunk->nents;
+
+ mr = alloc_mr(n, &to_idev(pd->device)->lk_table);
+ if (!mr) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ mr->mr.user_base = region->user_base;
+ mr->mr.iova = region->virt_base;
+ mr->mr.length = region->length;
+ mr->mr.offset = region->offset;
+ mr->mr.access_flags = mr_access_flags;
+ mr->mr.max_segs = n;
+
+ m = 0;
+ n = 0;
+ list_for_each_entry(chunk, &region->chunk_list, list) {
+ for (i = 0; i < chunk->nmap; i++) {
+ mr->mr.map[m]->segs[n].vaddr =
+ page_address(chunk->page_list[i].page);
+ mr->mr.map[m]->segs[n].length = region->page_size;
+ n++;
+ if (n == IPATH_SEGSZ) {
+ m++;
+ n = 0;
+ }
+ }
+ }
+ ret = &mr->ibmr;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_dereg_mr - unregister and free a memory region
+ * @ibmr: the memory region to free
+ *
+ * Returns 0 on success.
+ *
+ * Note that this is called to free MRs created by ipath_get_dma_mr()
+ * or ipath_reg_user_mr().
+ */
+int ipath_dereg_mr(struct ib_mr *ibmr)
+{
+ struct ipath_mr *mr = to_imr(ibmr);
+ int i;
+
+ ipath_free_lkey(&to_idev(ibmr->device)->lk_table, ibmr->lkey);
+ i = mr->mr.mapsz;
+ while (i) {
+ i--;
+ kfree(mr->mr.map[i]);
+ }
+ kfree(mr);
+ return 0;
+}
+
+/**
+ * ipath_alloc_fmr - allocate a fast memory region
+ * @pd: the protection domain for this memory region
+ * @mr_access_flags: access flags for this memory region
+ * @fmr_attr: fast memory region attributes
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
+ struct ib_fmr_attr *fmr_attr)
+{
+ struct ipath_fmr *fmr;
+ int m, i = 0;
+ struct ib_fmr *ret;
+
+ /* Allocate struct plus pointers to first level page tables. */
+ m = (fmr_attr->max_pages + IPATH_SEGSZ - 1) / IPATH_SEGSZ;
+ fmr = kmalloc(sizeof *fmr + m * sizeof fmr->mr.map[0], GFP_KERNEL);
+ if (!fmr)
+ goto bail;
+
+ /* Allocate first level page tables. */
+ for (; i < m; i++) {
+ fmr->mr.map[i] = kmalloc(sizeof *fmr->mr.map[0],
+ GFP_KERNEL);
+ if (!fmr->mr.map[i])
+ goto bail;
+ }
+ fmr->mr.mapsz = m;
+
+ /*
+ * ib_alloc_fmr() will initialize fmr->ibfmr except for lkey &
+ * rkey.
+ */
+ if (!ipath_alloc_lkey(&to_idev(pd->device)->lk_table, &fmr->mr))
+ goto bail;
+ fmr->ibfmr.rkey = fmr->ibfmr.lkey = fmr->mr.lkey;
+ /*
+ * Resources are allocated but no valid mapping (RKEY can't be
+ * used).
+ */
+ fmr->mr.user_base = 0;
+ fmr->mr.iova = 0;
+ fmr->mr.length = 0;
+ fmr->mr.offset = 0;
+ fmr->mr.access_flags = mr_access_flags;
+ fmr->mr.max_segs = fmr_attr->max_pages;
+ fmr->page_shift = fmr_attr->page_shift;
+
+ ret = &fmr->ibfmr;
+ goto done;
+
+bail:
+ while (i)
+ kfree(fmr->mr.map[--i]);
+ kfree(fmr);
+ ret = ERR_PTR(-ENOMEM);
+
+done:
+ return ret;
+}
+
+/**
+ * ipath_map_phys_fmr - set up a fast memory region
+ * @ibmfr: the fast memory region to set up
+ * @page_list: the list of pages to associate with the fast memory region
+ * @list_len: the number of pages to associate with the fast memory region
+ * @iova: the virtual address of the start of the fast memory region
+ *
+ * This may be called from interrupt context.
+ */
+
+int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
+ int list_len, u64 iova)
+{
+ struct ipath_fmr *fmr = to_ifmr(ibfmr);
+ struct ipath_lkey_table *rkt;
+ unsigned long flags;
+ int m, n, i;
+ u32 ps;
+ int ret;
+
+ if (list_len > fmr->mr.max_segs) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ rkt = &to_idev(ibfmr->device)->lk_table;
+ spin_lock_irqsave(&rkt->lock, flags);
+ fmr->mr.user_base = iova;
+ fmr->mr.iova = iova;
+ ps = 1 << fmr->page_shift;
+ fmr->mr.length = list_len * ps;
+ m = 0;
+ n = 0;
+ ps = 1 << fmr->page_shift;
+ for (i = 0; i < list_len; i++) {
+ fmr->mr.map[m]->segs[n].vaddr = phys_to_virt(page_list[i]);
+ fmr->mr.map[m]->segs[n].length = ps;
+ if (++n == IPATH_SEGSZ) {
+ m++;
+ n = 0;
+ }
+ }
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_unmap_fmr - unmap fast memory regions
+ * @fmr_list: the list of fast memory regions to unmap
+ *
+ * Returns 0 on success.
+ */
+int ipath_unmap_fmr(struct list_head *fmr_list)
+{
+ struct ipath_fmr *fmr;
+ struct ipath_lkey_table *rkt;
+ unsigned long flags;
+
+ list_for_each_entry(fmr, fmr_list, ibfmr.list) {
+ rkt = &to_idev(fmr->ibfmr.device)->lk_table;
+ spin_lock_irqsave(&rkt->lock, flags);
+ fmr->mr.user_base = 0;
+ fmr->mr.iova = 0;
+ fmr->mr.length = 0;
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ }
+ return 0;
+}
+
+/**
+ * ipath_dealloc_fmr - deallocate a fast memory region
+ * @ibfmr: the fast memory region to deallocate
+ *
+ * Returns 0 on success.
+ */
+int ipath_dealloc_fmr(struct ib_fmr *ibfmr)
+{
+ struct ipath_fmr *fmr = to_ifmr(ibfmr);
+ int i;
+
+ ipath_free_lkey(&to_idev(ibfmr->device)->lk_table, ibfmr->lkey);
+ i = fmr->mr.mapsz;
+ while (i)
+ kfree(fmr->mr.map[--i]);
+ kfree(fmr);
+ return 0;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c
new file mode 100644
index 000000000000..e1dc4f757062
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_pe800.c
@@ -0,0 +1,1247 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/*
+ * This file contains all of the code that is specific to the
+ * InfiniPath PE-800 chip.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+
+#include "ipath_kernel.h"
+#include "ipath_registers.h"
+
+/*
+ * This file contains all the chip-specific register information and
+ * access functions for the PathScale PE800, the PCI-Express chip.
+ *
+ * This lists the InfiniPath PE800 registers, in the actual chip layout.
+ * This structure should never be directly accessed.
+ */
+struct _infinipath_do_not_use_kernel_regs {
+ unsigned long long Revision;
+ unsigned long long Control;
+ unsigned long long PageAlign;
+ unsigned long long PortCnt;
+ unsigned long long DebugPortSelect;
+ unsigned long long Reserved0;
+ unsigned long long SendRegBase;
+ unsigned long long UserRegBase;
+ unsigned long long CounterRegBase;
+ unsigned long long Scratch;
+ unsigned long long Reserved1;
+ unsigned long long Reserved2;
+ unsigned long long IntBlocked;
+ unsigned long long IntMask;
+ unsigned long long IntStatus;
+ unsigned long long IntClear;
+ unsigned long long ErrorMask;
+ unsigned long long ErrorStatus;
+ unsigned long long ErrorClear;
+ unsigned long long HwErrMask;
+ unsigned long long HwErrStatus;
+ unsigned long long HwErrClear;
+ unsigned long long HwDiagCtrl;
+ unsigned long long MDIO;
+ unsigned long long IBCStatus;
+ unsigned long long IBCCtrl;
+ unsigned long long ExtStatus;
+ unsigned long long ExtCtrl;
+ unsigned long long GPIOOut;
+ unsigned long long GPIOMask;
+ unsigned long long GPIOStatus;
+ unsigned long long GPIOClear;
+ unsigned long long RcvCtrl;
+ unsigned long long RcvBTHQP;
+ unsigned long long RcvHdrSize;
+ unsigned long long RcvHdrCnt;
+ unsigned long long RcvHdrEntSize;
+ unsigned long long RcvTIDBase;
+ unsigned long long RcvTIDCnt;
+ unsigned long long RcvEgrBase;
+ unsigned long long RcvEgrCnt;
+ unsigned long long RcvBufBase;
+ unsigned long long RcvBufSize;
+ unsigned long long RxIntMemBase;
+ unsigned long long RxIntMemSize;
+ unsigned long long RcvPartitionKey;
+ unsigned long long Reserved3;
+ unsigned long long RcvPktLEDCnt;
+ unsigned long long Reserved4[8];
+ unsigned long long SendCtrl;
+ unsigned long long SendPIOBufBase;
+ unsigned long long SendPIOSize;
+ unsigned long long SendPIOBufCnt;
+ unsigned long long SendPIOAvailAddr;
+ unsigned long long TxIntMemBase;
+ unsigned long long TxIntMemSize;
+ unsigned long long Reserved5;
+ unsigned long long PCIeRBufTestReg0;
+ unsigned long long PCIeRBufTestReg1;
+ unsigned long long Reserved51[6];
+ unsigned long long SendBufferError;
+ unsigned long long SendBufferErrorCONT1;
+ unsigned long long Reserved6SBE[6];
+ unsigned long long RcvHdrAddr0;
+ unsigned long long RcvHdrAddr1;
+ unsigned long long RcvHdrAddr2;
+ unsigned long long RcvHdrAddr3;
+ unsigned long long RcvHdrAddr4;
+ unsigned long long Reserved7RHA[11];
+ unsigned long long RcvHdrTailAddr0;
+ unsigned long long RcvHdrTailAddr1;
+ unsigned long long RcvHdrTailAddr2;
+ unsigned long long RcvHdrTailAddr3;
+ unsigned long long RcvHdrTailAddr4;
+ unsigned long long Reserved8RHTA[11];
+ unsigned long long Reserved9SW[8];
+ unsigned long long SerdesConfig0;
+ unsigned long long SerdesConfig1;
+ unsigned long long SerdesStatus;
+ unsigned long long XGXSConfig;
+ unsigned long long IBPLLCfg;
+ unsigned long long Reserved10SW2[3];
+ unsigned long long PCIEQ0SerdesConfig0;
+ unsigned long long PCIEQ0SerdesConfig1;
+ unsigned long long PCIEQ0SerdesStatus;
+ unsigned long long Reserved11;
+ unsigned long long PCIEQ1SerdesConfig0;
+ unsigned long long PCIEQ1SerdesConfig1;
+ unsigned long long PCIEQ1SerdesStatus;
+ unsigned long long Reserved12;
+};
+
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+ _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_CREG_OFFSET(field) (offsetof( \
+ struct infinipath_counters, field) / sizeof(u64))
+
+static const struct ipath_kregs ipath_pe_kregs = {
+ .kr_control = IPATH_KREG_OFFSET(Control),
+ .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
+ .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
+ .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
+ .kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
+ .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
+ .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
+ .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
+ .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
+ .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
+ .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
+ .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
+ .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
+ .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
+ .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
+ .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
+ .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
+ .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
+ .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
+ .kr_intclear = IPATH_KREG_OFFSET(IntClear),
+ .kr_intmask = IPATH_KREG_OFFSET(IntMask),
+ .kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
+ .kr_mdio = IPATH_KREG_OFFSET(MDIO),
+ .kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
+ .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
+ .kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
+ .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
+ .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
+ .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
+ .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
+ .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
+ .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
+ .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
+ .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
+ .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
+ .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
+ .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
+ .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
+ .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
+ .kr_revision = IPATH_KREG_OFFSET(Revision),
+ .kr_scratch = IPATH_KREG_OFFSET(Scratch),
+ .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
+ .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
+ .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),
+ .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),
+ .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),
+ .kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),
+ .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
+ .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
+ .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
+ .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
+ .kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),
+ .kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),
+ .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),
+ .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
+ .kr_ibpllcfg = IPATH_KREG_OFFSET(IBPLLCfg),
+
+ /*
+ * These should not be used directly via ipath_read_kreg64(),
+ * use them with ipath_read_kreg64_port()
+ */
+ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
+ .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
+
+ /* This group is pe-800-specific; and used only in this file */
+ /* The rcvpktled register controls one of the debug port signals, so
+ * a packet activity LED can be connected to it. */
+ .kr_rcvpktledcnt = IPATH_KREG_OFFSET(RcvPktLEDCnt),
+ .kr_pcierbuftestreg0 = IPATH_KREG_OFFSET(PCIeRBufTestReg0),
+ .kr_pcierbuftestreg1 = IPATH_KREG_OFFSET(PCIeRBufTestReg1),
+ .kr_pcieq0serdesconfig0 = IPATH_KREG_OFFSET(PCIEQ0SerdesConfig0),
+ .kr_pcieq0serdesconfig1 = IPATH_KREG_OFFSET(PCIEQ0SerdesConfig1),
+ .kr_pcieq0serdesstatus = IPATH_KREG_OFFSET(PCIEQ0SerdesStatus),
+ .kr_pcieq1serdesconfig0 = IPATH_KREG_OFFSET(PCIEQ1SerdesConfig0),
+ .kr_pcieq1serdesconfig1 = IPATH_KREG_OFFSET(PCIEQ1SerdesConfig1),
+ .kr_pcieq1serdesstatus = IPATH_KREG_OFFSET(PCIEQ1SerdesStatus)
+};
+
+static const struct ipath_cregs ipath_pe_cregs = {
+ .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
+ .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
+ .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
+ .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
+ .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
+ .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
+ .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
+ .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
+ .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
+ .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
+ .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
+ .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
+ .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
+ .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
+ .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
+ .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
+ .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
+ .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
+ .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
+ .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
+ .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
+ .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
+ .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
+ .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
+ .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
+ .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
+ .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
+ .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
+ .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
+ .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
+ .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
+ .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
+ .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+};
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_MASK 0x1F
+#define INFINIPATH_I_RCVAVAIL_MASK 0x1F
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+#define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK 0x000000000000003fULL
+#define INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT 0
+#define INFINIPATH_HWE_PCIEPOISONEDTLP 0x0000000010000000ULL
+#define INFINIPATH_HWE_PCIECPLTIMEOUT 0x0000000020000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYXTLH 0x0000000040000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYXADM 0x0000000080000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYRADM 0x0000000100000000ULL
+#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL
+#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL
+#define INFINIPATH_HWE_PCIE1PLLFAILED 0x0400000000000000ULL
+#define INFINIPATH_HWE_PCIE0PLLFAILED 0x0800000000000000ULL
+#define INFINIPATH_HWE_SERDESPLLFAILED 0x1000000000000000ULL
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_FREQSEL 0x2
+#define INFINIPATH_EXTS_SERDESSEL 0x4
+#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
+#define INFINIPATH_EXTS_MEMBIST_FOUND 0x0000000000008000
+
+#define _IPATH_GPIO_SDA_NUM 1
+#define _IPATH_GPIO_SCL_NUM 0
+
+#define IPATH_GPIO_SDA (1ULL << \
+ (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+#define IPATH_GPIO_SCL (1ULL << \
+ (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
+/**
+ * ipath_pe_handle_hwerrors - display hardware errors.
+ * @dd: the infinipath device
+ * @msg: the output buffer
+ * @msgl: the size of the output buffer
+ *
+ * Use same msg buffer as regular errors to avoid excessive stack
+ * use. Most hardware errors are catastrophic, but for right now,
+ * we'll print them and continue. We reuse the same message buffer as
+ * ipath_handle_errors() to avoid excessive stack usage.
+ */
+static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ size_t msgl)
+{
+ ipath_err_t hwerrs;
+ u32 bits, ctrl;
+ int isfatal = 0;
+ char bitsmsg[64];
+
+ hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+ if (!hwerrs) {
+ /*
+ * better than printing cofusing messages
+ * This seems to be related to clearing the crc error, or
+ * the pll error during init.
+ */
+ ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
+ return;
+ } else if (hwerrs == ~0ULL) {
+ ipath_dev_err(dd, "Read of hardware error status failed "
+ "(all bits set); ignoring\n");
+ return;
+ }
+ ipath_stats.sps_hwerrs++;
+
+ /* Always clear the error status register, except MEMBISTFAIL,
+ * regardless of whether we continue or stop using the chip.
+ * We want that set so we know it failed, even across driver reload.
+ * We'll still ignore it in the hwerrmask. We do this partly for
+ * diagnostics, but also for support */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
+
+ hwerrs &= dd->ipath_hwerrmask;
+
+ /*
+ * make sure we get this much out, unless told to be quiet,
+ * or it's occurred within the last 5 seconds
+ */
+ if ((hwerrs & ~dd->ipath_lasthwerror) ||
+ (ipath_debug & __IPATH_VERBDBG))
+ dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+ "(cleared)\n", (unsigned long long) hwerrs);
+ dd->ipath_lasthwerror |= hwerrs;
+
+ if (hwerrs & ~infinipath_hwe_bitsextant)
+ ipath_dev_err(dd, "hwerror interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+ (hwerrs & ~infinipath_hwe_bitsextant));
+
+ ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+ if (ctrl & INFINIPATH_C_FREEZEMODE) {
+ if (hwerrs) {
+ /*
+ * if any set that we aren't ignoring only make the
+ * complaint once, in case it's stuck or recurring,
+ * and we get here multiple times
+ */
+ if (dd->ipath_flags & IPATH_INITTED) {
+ ipath_dev_err(dd, "Fatal Error (freeze "
+ "mode), no longer usable\n");
+ isfatal = 1;
+ }
+ /*
+ * Mark as having had an error for driver, and also
+ * for /sys and status word mapped to user programs.
+ * This marks unit as not usable, until reset
+ */
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ dd->ipath_flags &= ~IPATH_INITTED;
+ } else {
+ ipath_dbg("Clearing freezemode on ignored hardware "
+ "error\n");
+ ctrl &= ~INFINIPATH_C_FREEZEMODE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ ctrl);
+ }
+ }
+
+ *msg = '\0';
+
+ if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
+ strlcat(msg, "[Memory BIST test failed, PE-800 unusable]",
+ msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+ if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_PCIEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[PCIe Mem Parity Errs %x] ", bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
+ strlcat(msg, "[IB2IPATH Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
+ strlcat(msg, "[IPATH2IB Parity]", msgl);
+
+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \
+ INFINIPATH_HWE_COREPLL_RFSLIP )
+
+ if (hwerrs & _IPATH_PLL_FAIL) {
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[PLL failed (%llx), PE-800 unusable]",
+ (unsigned long long) hwerrs & _IPATH_PLL_FAIL);
+ strlcat(msg, bitsmsg, msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+ /*
+ * If it occurs, it is left masked since the eternal
+ * interface is unused
+ */
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_PCIEPOISONEDTLP)
+ strlcat(msg, "[PCIe Poisoned TLP]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIECPLTIMEOUT)
+ strlcat(msg, "[PCIe completion timeout]", msgl);
+
+ /*
+ * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
+ * parity or memory parity error failures, because most likely we
+ * won't be able to talk to the core of the chip. Nonetheless, we
+ * might see them, if they are in parts of the PCIe core that aren't
+ * essential.
+ */
+ if (hwerrs & INFINIPATH_HWE_PCIE1PLLFAILED)
+ strlcat(msg, "[PCIePLL1]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIE0PLLFAILED)
+ strlcat(msg, "[PCIePLL0]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXTLH)
+ strlcat(msg, "[PCIe XTLH core parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXADM)
+ strlcat(msg, "[PCIe ADM TX core parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYRADM)
+ strlcat(msg, "[PCIe ADM RX core parity]", msgl);
+
+ if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
+ strlcat(msg, "[Rx Dsync]", msgl);
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
+ strlcat(msg, "[SerDes PLL]", msgl);
+
+ ipath_dev_err(dd, "%s hardware error\n", msg);
+ if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {
+ /*
+ * for /sys status file ; if no trailing } is copied, we'll
+ * know it was truncated.
+ */
+ snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
+ "{%s}", msg);
+ }
+}
+
+/**
+ * ipath_pe_boardname - fill in the board name
+ * @dd: the infinipath device
+ * @name: the output buffer
+ * @namelen: the size of the output buffer
+ *
+ * info is based on the board revision register
+ */
+static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen)
+{
+ char *n = NULL;
+ u8 boardrev = dd->ipath_boardrev;
+ int ret;
+
+ switch (boardrev) {
+ case 0:
+ n = "InfiniPath_Emulation";
+ break;
+ case 1:
+ n = "InfiniPath_PE-800-Bringup";
+ break;
+ case 2:
+ n = "InfiniPath_PE-880";
+ break;
+ case 3:
+ n = "InfiniPath_PE-850";
+ break;
+ case 4:
+ n = "InfiniPath_PE-860";
+ break;
+ default:
+ ipath_dev_err(dd,
+ "Don't yet know about board with ID %u\n",
+ boardrev);
+ snprintf(name, namelen, "Unknown_InfiniPath_PE-8xx_%u",
+ boardrev);
+ break;
+ }
+ if (n)
+ snprintf(name, namelen, "%s", n);
+
+ if (dd->ipath_majrev != 4 || dd->ipath_minrev != 1) {
+ ipath_dev_err(dd, "Unsupported PE-800 revision %u.%u!\n",
+ dd->ipath_majrev, dd->ipath_minrev);
+ ret = 1;
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+/**
+ * ipath_pe_init_hwerrors - enable hardware errors
+ * @dd: the infinipath device
+ *
+ * now that we have finished initializing everything that might reasonably
+ * cause a hardware error, and cleared those errors bits as they occur,
+ * we can enable hardware errors in the mask (potentially enabling
+ * freeze mode), and enable hardware errors as errors (along with
+ * everything else) in errormask
+ */
+static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
+{
+ ipath_err_t val;
+ u64 extsval;
+
+ extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+ if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))
+ ipath_dev_err(dd, "MemBIST did not complete!\n");
+
+ val = ~0ULL; /* barring bugs, all hwerrors become interrupts, */
+
+ if (!dd->ipath_boardrev) // no PLL for Emulator
+ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+
+ /* workaround bug 9460 in internal interface bus parity checking */
+ val &= ~INFINIPATH_HWE_PCIEBUSPARITYRADM;
+
+ dd->ipath_hwerrmask = val;
+}
+
+/**
+ * ipath_pe_bringup_serdes - bring up the serdes
+ * @dd: the infinipath device
+ */
+static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
+{
+ u64 val, tmp, config1;
+ int ret = 0, change = 0;
+
+ ipath_dbg("Trying to bringup serdes\n");
+
+ if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
+ INFINIPATH_HWE_SERDESPLLFAILED) {
+ ipath_dbg("At start, serdes PLL failed bit set "
+ "in hwerrstatus, clearing and continuing\n");
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ INFINIPATH_HWE_SERDESPLLFAILED);
+ }
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+ config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
+
+ ipath_cdbg(VERBOSE, "SerDes status config0=%llx config1=%llx, "
+ "xgxsconfig %llx\n", (unsigned long long) val,
+ (unsigned long long) config1, (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ /*
+ * Force reset on, also set rxdetect enable. Must do before reading
+ * serdesstatus at least for simulation, or some of the bits in
+ * serdes status will come back as undefined and cause simulation
+ * failures
+ */
+ val |= INFINIPATH_SERDC0_RESET_PLL | INFINIPATH_SERDC0_RXDETECT_EN
+ | INFINIPATH_SERDC0_L1PWR_DN;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ /* be sure chip saw it */
+ tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ udelay(5); /* need pll reset set at least for a bit */
+ /*
+ * after PLL is reset, set the per-lane Resets and TxIdle and
+ * clear the PLL reset and rxdetect (to get falling edge).
+ * Leave L1PWR bits set (permanently)
+ */
+ val &= ~(INFINIPATH_SERDC0_RXDETECT_EN | INFINIPATH_SERDC0_RESET_PLL
+ | INFINIPATH_SERDC0_L1PWR_DN);
+ val |= INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE;
+ ipath_cdbg(VERBOSE, "Clearing pll reset and setting lane resets "
+ "and txidle (%llx)\n", (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ /* be sure chip saw it */
+ tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ /* need PLL reset clear for at least 11 usec before lane
+ * resets cleared; give it a few more to be sure */
+ udelay(15);
+ val &= ~(INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE);
+
+ ipath_cdbg(VERBOSE, "Clearing lane resets and txidle "
+ "(writing %llx)\n", (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ /* be sure chip saw it */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+ val &=
+ ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+ INFINIPATH_XGXS_MDIOADDR_SHIFT);
+ /* MDIO address 3 */
+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+ change = 1;
+ }
+ if (val & INFINIPATH_XGXS_RESET) {
+ val &= ~INFINIPATH_XGXS_RESET;
+ change = 1;
+ }
+ if (change)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ /* clear current and de-emphasis bits */
+ config1 &= ~0x0ffffffff00ULL;
+ /* set current to 20ma */
+ config1 |= 0x00000000000ULL;
+ /* set de-emphasis to -5.68dB */
+ config1 |= 0x0cccc000000ULL;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);
+
+ ipath_cdbg(VERBOSE, "done: SerDes status config0=%llx "
+ "config1=%llx, sstatus=%llx xgxs=%llx\n",
+ (unsigned long long) val, (unsigned long long) config1,
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ if (!ipath_waitfor_mdio_cmdready(dd)) {
+ ipath_write_kreg(
+ dd, dd->ipath_kregs->kr_mdio,
+ ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+ IPATH_MDIO_CTRL_XGXS_REG_8, 0));
+ if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+ IPATH_MDIO_DATAVALID, &val))
+ ipath_dbg("Never got MDIO data for XGXS "
+ "status read\n");
+ else
+ ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+ "'bank' 31 %x\n", (u32) val);
+ } else
+ ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
+ return ret;
+}
+
+/**
+ * ipath_pe_quiet_serdes - set serdes to txidle
+ * @dd: the infinipath device
+ * Called when driver is being unloaded
+ */
+static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
+{
+ u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ val |= INFINIPATH_SERDC0_TXIDLE;
+ ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
+ (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+}
+
+/* this is not yet needed on the PE800, so just return 0. */
+static int ipath_pe_intconfig(struct ipath_devdata *dd)
+{
+ return 0;
+}
+
+/**
+ * ipath_setup_pe_setextled - set the state of the two external LEDs
+ * @dd: the infinipath device
+ * @lst: the L state
+ * @ltst: the LT state
+
+ * These LEDs indicate the physical and logical state of IB link.
+ * For this chip (at least with recommended board pinouts), LED1
+ * is Yellow (logical state) and LED2 is Green (physical state),
+ *
+ * Note: We try to match the Mellanox HCA LED behavior as best
+ * we can. Green indicates physical link state is OK (something is
+ * plugged in, and we can train).
+ * Amber indicates the link is logically up (ACTIVE).
+ * Mellanox further blinks the amber LED to indicate data packet
+ * activity, but we have no hardware support for that, so it would
+ * require waking up every 10-20 msecs and checking the counters
+ * on the chip, and then turning the LED off if appropriate. That's
+ * visible overhead, so not something we will do.
+ *
+ */
+static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
+ u64 ltst)
+{
+ u64 extctl;
+
+ /* 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;
+
+ extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+ INFINIPATH_EXTC_LED2PRIPORT_ON);
+
+ if (ltst & INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+ dd->ipath_extctrl = extctl;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+}
+
+/**
+ * ipath_setup_pe_cleanup - clean up any per-chip chip-specific stuff
+ * @dd: the infinipath device
+ *
+ * This is called during driver unload.
+ * We do the pci_disable_msi here, not in generic code, because it
+ * isn't used for the HT-400. If we do end up needing pci_enable_msi
+ * at some point in the future for HT-400, we'll move the call back
+ * into the main init_one code.
+ */
+static void ipath_setup_pe_cleanup(struct ipath_devdata *dd)
+{
+ dd->ipath_msi_lo = 0; /* just in case unload fails */
+ pci_disable_msi(dd->pcidev);
+}
+
+/**
+ * ipath_setup_pe_config - setup PCIe config related stuff
+ * @dd: the infinipath device
+ * @pdev: the PCI device
+ *
+ * The pci_enable_msi() call will fail on systems with MSI quirks
+ * such as those with AMD8131, even if the device of interest is not
+ * attached to that device, (in the 2.6.13 - 2.6.15 kernels, at least, fixed
+ * late in 2.6.16).
+ * All that can be done is to edit the kernel source to remove the quirk
+ * check until that is fixed.
+ * We do not need to call enable_msi() for our HyperTransport chip (HT-400),
+ * even those it uses MSI, and we want to avoid the quirk warning, so
+ * So we call enable_msi only for the PE-800. If we do end up needing
+ * pci_enable_msi at some point in the future for HT-400, we'll move the
+ * call back into the main init_one code.
+ * We save the msi lo and hi values, so we can restore them after
+ * chip reset (the kernel PCI infrastructure doesn't yet handle that
+ * correctly).
+ */
+static int ipath_setup_pe_config(struct ipath_devdata *dd,
+ struct pci_dev *pdev)
+{
+ int pos, ret;
+
+ dd->ipath_msi_lo = 0; /* used as a flag during reset processing */
+ ret = pci_enable_msi(dd->pcidev);
+ if (ret)
+ ipath_dev_err(dd, "pci_enable_msi failed: %d, "
+ "interrupts may not work\n", ret);
+ /* continue even if it fails, we may still be OK... */
+
+ if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
+ u16 control;
+ pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
+ &dd->ipath_msi_lo);
+ pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
+ &dd->ipath_msi_hi);
+ pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
+ &control);
+ /* now save the data (vector) info */
+ pci_read_config_word(dd->pcidev,
+ pos + ((control & PCI_MSI_FLAGS_64BIT)
+ ? 12 : 8),
+ &dd->ipath_msi_data);
+ ipath_cdbg(VERBOSE, "Read msi data 0x%x from config offset "
+ "0x%x, control=0x%x\n", dd->ipath_msi_data,
+ pos + ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
+ control);
+ /* we save the cachelinesize also, although it doesn't
+ * really matter */
+ pci_read_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
+ &dd->ipath_pci_cacheline);
+ } else
+ ipath_dev_err(dd, "Can't find MSI capability, "
+ "can't save MSI settings for reset\n");
+ if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP))) {
+ u16 linkstat;
+ pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
+ &linkstat);
+ linkstat >>= 4;
+ linkstat &= 0x1f;
+ if (linkstat != 8)
+ ipath_dev_err(dd, "PCIe width %u, "
+ "performance reduced\n", linkstat);
+ }
+ else
+ ipath_dev_err(dd, "Can't find PCI Express "
+ "capability!\n");
+ return 0;
+}
+
+static void ipath_init_pe_variables(void)
+{
+ /*
+ * bits for selecting i2c direction and values,
+ * used for I2C serial flash
+ */
+ ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+ ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+ ipath_gpio_sda = IPATH_GPIO_SDA;
+ ipath_gpio_scl = IPATH_GPIO_SCL;
+
+ /* variables for sanity checking interrupt and errors */
+ infinipath_hwe_bitsextant =
+ (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+ (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |
+ INFINIPATH_HWE_PCIE1PLLFAILED |
+ INFINIPATH_HWE_PCIE0PLLFAILED |
+ INFINIPATH_HWE_PCIEPOISONEDTLP |
+ INFINIPATH_HWE_PCIECPLTIMEOUT |
+ INFINIPATH_HWE_PCIEBUSPARITYXTLH |
+ INFINIPATH_HWE_PCIEBUSPARITYXADM |
+ INFINIPATH_HWE_PCIEBUSPARITYRADM |
+ INFINIPATH_HWE_MEMBISTFAILED |
+ INFINIPATH_HWE_COREPLL_FBSLIP |
+ INFINIPATH_HWE_COREPLL_RFSLIP |
+ INFINIPATH_HWE_SERDESPLLFAILED |
+ INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
+ INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
+ infinipath_i_bitsextant =
+ (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+ (INFINIPATH_I_RCVAVAIL_MASK <<
+ INFINIPATH_I_RCVAVAIL_SHIFT) |
+ INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
+ INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
+ infinipath_e_bitsextant =
+ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
+ INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
+ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
+ INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
+ INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
+ INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
+ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+ INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
+ INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |
+ INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |
+ INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
+ INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
+ INFINIPATH_E_HARDWARE;
+
+ infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+ infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+}
+
+/* setup the MSI stuff again after a reset. I'd like to just call
+ * pci_enable_msi() and request_irq() again, but when I do that,
+ * the MSI enable bit doesn't get set in the command word, and
+ * we switch to to a different interrupt vector, which is confusing,
+ * so I instead just do it all inline. Perhaps somehow can tie this
+ * into the PCIe hotplug support at some point
+ * Note, because I'm doing it all here, I don't call pci_disable_msi()
+ * or free_irq() at the start of ipath_setup_pe_reset().
+ */
+static int ipath_reinit_msi(struct ipath_devdata *dd)
+{
+ int pos;
+ u16 control;
+ int ret;
+
+ if (!dd->ipath_msi_lo) {
+ dev_info(&dd->pcidev->dev, "Can't restore MSI config, "
+ "initial setup failed?\n");
+ ret = 0;
+ goto bail;
+ }
+
+ if (!(pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
+ ipath_dev_err(dd, "Can't find MSI capability, "
+ "can't restore MSI settings\n");
+ ret = 0;
+ goto bail;
+ }
+ ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
+ dd->ipath_msi_lo, pos + PCI_MSI_ADDRESS_LO);
+ pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
+ dd->ipath_msi_lo);
+ ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
+ dd->ipath_msi_hi, pos + PCI_MSI_ADDRESS_HI);
+ pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
+ dd->ipath_msi_hi);
+ pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS, &control);
+ if (!(control & PCI_MSI_FLAGS_ENABLE)) {
+ ipath_cdbg(VERBOSE, "MSI control at off %x was %x, "
+ "setting MSI enable (%x)\n", pos + PCI_MSI_FLAGS,
+ control, control | PCI_MSI_FLAGS_ENABLE);
+ control |= PCI_MSI_FLAGS_ENABLE;
+ pci_write_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
+ control);
+ }
+ /* now rewrite the data (vector) info */
+ pci_write_config_word(dd->pcidev, pos +
+ ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
+ dd->ipath_msi_data);
+ /* we restore the cachelinesize also, although it doesn't really
+ * matter */
+ pci_write_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
+ dd->ipath_pci_cacheline);
+ /* and now set the pci master bit again */
+ pci_set_master(dd->pcidev);
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/* This routine sleeps, so it can only be called from user context, not
+ * from interrupt context. If we need interrupt context, we can split
+ * it into two routines.
+*/
+static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+{
+ u64 val;
+ int i;
+ int ret;
+
+ /* Use ERROR so it shows up in logs, etc. */
+ ipath_dev_err(dd, "Resetting PE-800 unit %u\n",
+ dd->ipath_unit);
+ val = dd->ipath_control | INFINIPATH_C_RESET;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);
+ mb();
+
+ for (i = 1; i <= 5; i++) {
+ int r;
+ /* allow MBIST, etc. to complete; longer on each retry.
+ * We sometimes get machine checks from bus timeout if no
+ * response, so for now, make it *really* long.
+ */
+ msleep(1000 + (1 + i) * 2000);
+ if ((r =
+ pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0,
+ dd->ipath_pcibar0)))
+ ipath_dev_err(dd, "rewrite of BAR0 failed: %d\n",
+ r);
+ if ((r =
+ pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1,
+ dd->ipath_pcibar1)))
+ ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n",
+ r);
+ /* now re-enable memory access */
+ if ((r = pci_enable_device(dd->pcidev)))
+ ipath_dev_err(dd, "pci_enable_device failed after "
+ "reset: %d\n", r);
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+ if (val == dd->ipath_revision) {
+ ipath_cdbg(VERBOSE, "Got matching revision "
+ "register %llx on try %d\n",
+ (unsigned long long) val, i);
+ ret = ipath_reinit_msi(dd);
+ goto bail;
+ }
+ /* Probably getting -1 back */
+ ipath_dbg("Didn't get expected revision register, "
+ "got %llx, try %d\n", (unsigned long long) val,
+ i + 1);
+ }
+ ret = 0; /* failed */
+
+bail:
+ return ret;
+}
+
+/**
+ * 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
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for special locking etc.
+ * It's used for both the full cleanup on exit, as well as the normal
+ * setup and teardown.
+ */
+static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ u32 type, unsigned long pa)
+{
+ u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
+ unsigned long flags = 0; /* keep gcc quiet */
+
+ if (pa != dd->ipath_tidinvalid) {
+ if (pa & ((1U << 11) - 1)) {
+ dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
+ "not 4KB aligned!\n", pa);
+ return;
+ }
+ pa >>= 11;
+ /* paranoia check */
+ if (pa & (7<<29))
+ ipath_dev_err(dd,
+ "BUG: Physical page address 0x%lx "
+ "has bits set in 31-29\n", pa);
+
+ if (type == 0)
+ pa |= dd->ipath_tidtemplate;
+ else /* for now, always full 4KB page */
+ pa |= 2 << 29;
+ }
+
+ /* workaround chip bug 9437 by writing each TID twice
+ * and holding a spinlock around the writes, so they don't
+ * intermix with other TID (eager or expected) writes
+ * Unfortunately, this call can be done from interrupt level
+ * for the port 0 eager TIDs, so we have to use irqsave
+ */
+ spin_lock_irqsave(&dd->ipath_tid_lock, flags);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf);
+ if (dd->ipath_kregbase)
+ writel(pa, tidp32);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef);
+ mmiowb();
+ spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);
+}
+
+/**
+ * ipath_pe_clear_tid - clear all TID entries for a port, expected and eager
+ * @dd: the infinipath device
+ * @port: the port
+ *
+ * clear all TID entries for a port, expected and eager.
+ * Used from ipath_close(). On PE800, TIDs are only 32 bits,
+ * not 64, but they are still on 64 bit boundaries, so tidbase
+ * is declared as u64 * for the pointer math, even though we write 32 bits
+ */
+static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
+{
+ u64 __iomem *tidbase;
+ unsigned long tidinv;
+ int i;
+
+ if (!dd->ipath_kregbase)
+ return;
+
+ ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
+
+ tidinv = dd->ipath_tidinvalid;
+ tidbase = (u64 __iomem *)
+ ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
+
+ for (i = 0; i < dd->ipath_rcvtidcnt; i++)
+ ipath_pe_put_tid(dd, &tidbase[i], 0, tidinv);
+
+ tidbase = (u64 __iomem *)
+ ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvegrbase +
+ 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_tidtemplate - setup constants for TID updates
+ * @dd: the infinipath device
+ *
+ * We setup stuff that we use a lot, to avoid calculating each time
+ */
+static void ipath_pe_tidtemplate(struct ipath_devdata *dd)
+{
+ u32 egrsize = dd->ipath_rcvegrbufsize;
+
+ /* For now, we always allocate 4KB buffers (at init) so we can
+ * receive max size packets. We may want a module parameter to
+ * specify 2KB or 4KB and/or make be per port instead of per device
+ * for those who want to reduce memory footprint. Note that the
+ * ipath_rcvhdrentsize size must be large enough to hold the largest
+ * IB header (currently 96 bytes) that we expect to handle (plus of
+ * course the 2 dwords of RHF).
+ */
+ if (egrsize == 2048)
+ dd->ipath_tidtemplate = 1U << 29;
+ else if (egrsize == 4096)
+ dd->ipath_tidtemplate = 2U << 29;
+ else {
+ egrsize = 4096;
+ dev_info(&dd->pcidev->dev, "BUG: unsupported egrbufsize "
+ "%u, using %u\n", dd->ipath_rcvegrbufsize,
+ egrsize);
+ dd->ipath_tidtemplate = 2U << 29;
+ }
+ dd->ipath_tidinvalid = 0;
+}
+
+static int ipath_pe_early_init(struct ipath_devdata *dd)
+{
+ dd->ipath_flags |= IPATH_4BYTE_TID;
+
+ /*
+ * For openib, we need to be able to handle an IB header of 96 bytes
+ * or 24 dwords. HT-400 has arbitrary sized receive buffers, so we
+ * made them the same size as the PIO buffers. The PE-800 does not
+ * handle arbitrary size buffers, so we need the header large enough
+ * to handle largest IB header, but still have room for a 2KB MTU
+ * standard IB packet.
+ */
+ dd->ipath_rcvhdrentsize = 24;
+ dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+
+ /* For HT-400, we allocate a somewhat overly large eager buffer,
+ * such that we can guarantee that we can receive the largest packet
+ * that we can send out. To truly support a 4KB MTU, we need to
+ * bump this to a larger value. We'll do this when I get around to
+ * testing 4KB sends on the PE-800, which I have not yet done.
+ */
+ dd->ipath_rcvegrbufsize = 2048;
+ /*
+ * the min() check here is currently a nop, but it may not always
+ * be, depending on just how we do ipath_rcvegrbufsize
+ */
+ dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
+ dd->ipath_rcvegrbufsize +
+ (dd->ipath_rcvhdrentsize << 2));
+ dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+
+ /*
+ * For PE-800, we can request a receive interrupt for 1 or
+ * more packets from current offset. For now, we set this
+ * up for a single packet, to match the HT-400 behavior.
+ */
+ dd->ipath_rhdrhead_intr_off = 1ULL<<32;
+
+ return 0;
+}
+
+int __attribute__((weak)) ipath_unordered_wc(void)
+{
+ return 0;
+}
+
+/**
+ * ipath_init_pe_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+ * @kbase: ipath_base_info pointer
+ *
+ * We set the PCIE flag because the lower bandwidth on PCIe vs
+ * HyperTransport can affect some user packet algorithims.
+ */
+static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
+{
+ struct ipath_base_info *kinfo = kbase;
+
+ if (ipath_unordered_wc()) {
+ kinfo->spi_runtime_flags |= IPATH_RUNTIME_FORCE_WC_ORDER;
+ ipath_cdbg(PROC, "Intel processor, forcing WC order\n");
+ }
+ else
+ ipath_cdbg(PROC, "Not Intel processor, WC ordered\n");
+
+ kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
+
+ return 0;
+}
+
+/**
+ * ipath_init_pe800_funcs - set up the chip-specific function pointers
+ * @dd: the infinipath device
+ *
+ * This is global, and is called directly at init to set up the
+ * chip-specific function pointers for later use.
+ */
+void ipath_init_pe800_funcs(struct ipath_devdata *dd)
+{
+ dd->ipath_f_intrsetup = ipath_pe_intconfig;
+ dd->ipath_f_bus = ipath_setup_pe_config;
+ dd->ipath_f_reset = ipath_setup_pe_reset;
+ dd->ipath_f_get_boardname = ipath_pe_boardname;
+ dd->ipath_f_init_hwerrors = ipath_pe_init_hwerrors;
+ dd->ipath_f_early_init = ipath_pe_early_init;
+ dd->ipath_f_handle_hwerrors = ipath_pe_handle_hwerrors;
+ dd->ipath_f_quiet_serdes = ipath_pe_quiet_serdes;
+ dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
+ dd->ipath_f_clear_tids = ipath_pe_clear_tids;
+ dd->ipath_f_put_tid = ipath_pe_put_tid;
+ dd->ipath_f_cleanup = ipath_setup_pe_cleanup;
+ dd->ipath_f_setextled = ipath_setup_pe_setextled;
+ dd->ipath_f_get_base_info = ipath_pe_get_base_info;
+
+ /* initialize chip-specific variables */
+ dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
+
+ /*
+ * setup the register offsets, since they are different for each
+ * chip
+ */
+ dd->ipath_kregs = &ipath_pe_kregs;
+ dd->ipath_cregs = &ipath_pe_cregs;
+
+ ipath_init_pe_variables();
+}
+
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
new file mode 100644
index 000000000000..18890716db1e
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -0,0 +1,913 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+#define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE)
+#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1)
+#define mk_qpn(qpt, map, off) (((map) - (qpt)->map) * BITS_PER_PAGE + \
+ (off))
+#define find_next_offset(map, off) find_next_zero_bit((map)->page, \
+ BITS_PER_PAGE, off)
+
+#define TRANS_INVALID 0
+#define TRANS_ANY2RST 1
+#define TRANS_RST2INIT 2
+#define TRANS_INIT2INIT 3
+#define TRANS_INIT2RTR 4
+#define TRANS_RTR2RTS 5
+#define TRANS_RTS2RTS 6
+#define TRANS_SQERR2RTS 7
+#define TRANS_ANY2ERR 8
+#define TRANS_RTS2SQD 9 /* XXX Wait for expected ACKs & signal event */
+#define TRANS_SQD2SQD 10 /* error if not drained & parameter change */
+#define TRANS_SQD2RTS 11 /* error if not drained */
+
+/*
+ * Convert the AETH credit code into the number of credits.
+ */
+static u32 credit_table[31] = {
+ 0, /* 0 */
+ 1, /* 1 */
+ 2, /* 2 */
+ 3, /* 3 */
+ 4, /* 4 */
+ 6, /* 5 */
+ 8, /* 6 */
+ 12, /* 7 */
+ 16, /* 8 */
+ 24, /* 9 */
+ 32, /* A */
+ 48, /* B */
+ 64, /* C */
+ 96, /* D */
+ 128, /* E */
+ 192, /* F */
+ 256, /* 10 */
+ 384, /* 11 */
+ 512, /* 12 */
+ 768, /* 13 */
+ 1024, /* 14 */
+ 1536, /* 15 */
+ 2048, /* 16 */
+ 3072, /* 17 */
+ 4096, /* 18 */
+ 6144, /* 19 */
+ 8192, /* 1A */
+ 12288, /* 1B */
+ 16384, /* 1C */
+ 24576, /* 1D */
+ 32768 /* 1E */
+};
+
+static u32 alloc_qpn(struct ipath_qp_table *qpt)
+{
+ u32 i, offset, max_scan, qpn;
+ struct qpn_map *map;
+ u32 ret;
+
+ qpn = qpt->last + 1;
+ if (qpn >= QPN_MAX)
+ qpn = 2;
+ offset = qpn & BITS_PER_PAGE_MASK;
+ map = &qpt->map[qpn / BITS_PER_PAGE];
+ max_scan = qpt->nmaps - !offset;
+ for (i = 0;;) {
+ if (unlikely(!map->page)) {
+ unsigned long page = get_zeroed_page(GFP_KERNEL);
+ unsigned long flags;
+
+ /*
+ * Free the page if someone raced with us
+ * installing it:
+ */
+ spin_lock_irqsave(&qpt->lock, flags);
+ if (map->page)
+ free_page(page);
+ else
+ map->page = (void *)page;
+ spin_unlock_irqrestore(&qpt->lock, flags);
+ if (unlikely(!map->page))
+ break;
+ }
+ if (likely(atomic_read(&map->n_free))) {
+ do {
+ if (!test_and_set_bit(offset, map->page)) {
+ atomic_dec(&map->n_free);
+ qpt->last = qpn;
+ ret = qpn;
+ goto bail;
+ }
+ offset = find_next_offset(map, offset);
+ qpn = mk_qpn(qpt, map, offset);
+ /*
+ * This test differs from alloc_pidmap().
+ * If find_next_offset() does find a zero
+ * bit, we don't need to check for QPN
+ * wrapping around past our starting QPN.
+ * We just need to be sure we don't loop
+ * forever.
+ */
+ } while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
+ }
+ /*
+ * In order to keep the number of pages allocated to a
+ * minimum, we scan the all existing pages before increasing
+ * the size of the bitmap table.
+ */
+ if (++i > max_scan) {
+ if (qpt->nmaps == QPNMAP_ENTRIES)
+ break;
+ map = &qpt->map[qpt->nmaps++];
+ offset = 0;
+ } else if (map < &qpt->map[qpt->nmaps]) {
+ ++map;
+ offset = 0;
+ } else {
+ map = &qpt->map[0];
+ offset = 2;
+ }
+ qpn = mk_qpn(qpt, map, offset);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static void free_qpn(struct ipath_qp_table *qpt, u32 qpn)
+{
+ struct qpn_map *map;
+
+ map = qpt->map + qpn / BITS_PER_PAGE;
+ if (map->page)
+ clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
+ atomic_inc(&map->n_free);
+}
+
+/**
+ * ipath_alloc_qpn - allocate a QP number
+ * @qpt: the QP table
+ * @qp: the QP
+ * @type: the QP type (IB_QPT_SMI and IB_QPT_GSI are special)
+ *
+ * Allocate the next available QPN and put the QP into the hash table.
+ * The hash table holds a reference to the QP.
+ */
+static int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
+ enum ib_qp_type type)
+{
+ unsigned long flags;
+ u32 qpn;
+ int ret;
+
+ if (type == IB_QPT_SMI)
+ qpn = 0;
+ else if (type == IB_QPT_GSI)
+ qpn = 1;
+ else {
+ /* Allocate the next available QPN */
+ qpn = alloc_qpn(qpt);
+ if (qpn == 0) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ }
+ qp->ibqp.qp_num = qpn;
+
+ /* Add the QP to the hash table. */
+ spin_lock_irqsave(&qpt->lock, flags);
+
+ qpn %= qpt->max;
+ qp->next = qpt->table[qpn];
+ qpt->table[qpn] = qp;
+ atomic_inc(&qp->refcount);
+
+ spin_unlock_irqrestore(&qpt->lock, flags);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_free_qp - remove a QP from the QP table
+ * @qpt: the QP table
+ * @qp: the QP to remove
+ *
+ * Remove the QP from the table so it can't be found asynchronously by
+ * the receive interrupt routine.
+ */
+static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
+{
+ struct ipath_qp *q, **qpp;
+ unsigned long flags;
+ int fnd = 0;
+
+ spin_lock_irqsave(&qpt->lock, flags);
+
+ /* Remove QP from the hash table. */
+ qpp = &qpt->table[qp->ibqp.qp_num % qpt->max];
+ for (; (q = *qpp) != NULL; qpp = &q->next) {
+ if (q == qp) {
+ *qpp = qp->next;
+ qp->next = NULL;
+ atomic_dec(&qp->refcount);
+ fnd = 1;
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&qpt->lock, flags);
+
+ if (!fnd)
+ return;
+
+ /* If QPN is not reserved, mark QPN free in the bitmap. */
+ if (qp->ibqp.qp_num > 1)
+ free_qpn(qpt, qp->ibqp.qp_num);
+
+ wait_event(qp->wait, !atomic_read(&qp->refcount));
+}
+
+/**
+ * ipath_free_all_qps - remove all QPs from the table
+ * @qpt: the QP table to empty
+ */
+void ipath_free_all_qps(struct ipath_qp_table *qpt)
+{
+ unsigned long flags;
+ struct ipath_qp *qp, *nqp;
+ u32 n;
+
+ for (n = 0; n < qpt->max; n++) {
+ spin_lock_irqsave(&qpt->lock, flags);
+ qp = qpt->table[n];
+ qpt->table[n] = NULL;
+ spin_unlock_irqrestore(&qpt->lock, flags);
+
+ while (qp) {
+ nqp = qp->next;
+ if (qp->ibqp.qp_num > 1)
+ free_qpn(qpt, qp->ibqp.qp_num);
+ if (!atomic_dec_and_test(&qp->refcount) ||
+ !ipath_destroy_qp(&qp->ibqp))
+ _VERBS_INFO("QP memory leak!\n");
+ qp = nqp;
+ }
+ }
+
+ for (n = 0; n < ARRAY_SIZE(qpt->map); n++) {
+ if (qpt->map[n].page)
+ free_page((unsigned long)qpt->map[n].page);
+ }
+}
+
+/**
+ * ipath_lookup_qpn - return the QP with the given QPN
+ * @qpt: the QP table
+ * @qpn: the QP number to look up
+ *
+ * The caller is responsible for decrementing the QP reference count
+ * when done.
+ */
+struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn)
+{
+ unsigned long flags;
+ struct ipath_qp *qp;
+
+ spin_lock_irqsave(&qpt->lock, flags);
+
+ for (qp = qpt->table[qpn % qpt->max]; qp; qp = qp->next) {
+ if (qp->ibqp.qp_num == qpn) {
+ atomic_inc(&qp->refcount);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&qpt->lock, flags);
+ return qp;
+}
+
+/**
+ * ipath_reset_qp - initialize the QP state to the reset state
+ * @qp: the QP to reset
+ */
+static void ipath_reset_qp(struct ipath_qp *qp)
+{
+ qp->remote_qpn = 0;
+ qp->qkey = 0;
+ qp->qp_access_flags = 0;
+ qp->s_hdrwords = 0;
+ qp->s_psn = 0;
+ qp->r_psn = 0;
+ atomic_set(&qp->msn, 0);
+ if (qp->ibqp.qp_type == IB_QPT_RC) {
+ qp->s_state = IB_OPCODE_RC_SEND_LAST;
+ qp->r_state = IB_OPCODE_RC_SEND_LAST;
+ } else {
+ qp->s_state = IB_OPCODE_UC_SEND_LAST;
+ qp->r_state = IB_OPCODE_UC_SEND_LAST;
+ }
+ qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+ qp->s_nak_state = 0;
+ qp->s_rnr_timeout = 0;
+ qp->s_head = 0;
+ qp->s_tail = 0;
+ qp->s_cur = 0;
+ qp->s_last = 0;
+ qp->s_ssn = 1;
+ qp->s_lsn = 0;
+ qp->r_rq.head = 0;
+ qp->r_rq.tail = 0;
+ qp->r_reuse_sge = 0;
+}
+
+/**
+ * ipath_error_qp - put a QP into an error state
+ * @qp: the QP to put into an error state
+ *
+ * Flushes both send and receive work queues.
+ * QP r_rq.lock and s_lock should be held.
+ */
+
+static void ipath_error_qp(struct ipath_qp *qp)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ib_wc wc;
+
+ _VERBS_INFO("QP%d/%d in error state\n",
+ qp->ibqp.qp_num, qp->remote_qpn);
+
+ spin_lock(&dev->pending_lock);
+ /* XXX What if its already removed by the timeout code? */
+ if (qp->timerwait.next != LIST_POISON1)
+ list_del(&qp->timerwait);
+ if (qp->piowait.next != LIST_POISON1)
+ list_del(&qp->piowait);
+ spin_unlock(&dev->pending_lock);
+
+ wc.status = IB_WC_WR_FLUSH_ERR;
+ wc.vendor_err = 0;
+ wc.byte_len = 0;
+ wc.imm_data = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = 0;
+ wc.wc_flags = 0;
+ wc.pkey_index = 0;
+ wc.slid = 0;
+ wc.sl = 0;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+
+ while (qp->s_last != qp->s_head) {
+ struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+ wc.wr_id = wqe->wr.wr_id;
+ wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+ }
+ qp->s_cur = qp->s_tail = qp->s_head;
+ qp->s_hdrwords = 0;
+ qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+
+ wc.opcode = IB_WC_RECV;
+ while (qp->r_rq.tail != qp->r_rq.head) {
+ wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
+ if (++qp->r_rq.tail >= qp->r_rq.size)
+ qp->r_rq.tail = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
+ }
+}
+
+/**
+ * ipath_modify_qp - modify the attributes of a queue pair
+ * @ibqp: the queue pair who's attributes we're modifying
+ * @attr: the new attributes
+ * @attr_mask: the mask of attributes to modify
+ *
+ * Returns 0 on success, otherwise returns an errno.
+ */
+int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ enum ib_qp_state cur_state, new_state;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ spin_lock(&qp->s_lock);
+
+ cur_state = attr_mask & IB_QP_CUR_STATE ?
+ attr->cur_qp_state : qp->state;
+ new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+ if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
+ attr_mask))
+ goto inval;
+
+ switch (new_state) {
+ case IB_QPS_RESET:
+ ipath_reset_qp(qp);
+ break;
+
+ case IB_QPS_ERR:
+ ipath_error_qp(qp);
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (attr_mask & IB_QP_PKEY_INDEX) {
+ struct ipath_ibdev *dev = to_idev(ibqp->device);
+
+ if (attr->pkey_index >= ipath_layer_get_npkeys(dev->dd))
+ goto inval;
+ qp->s_pkey_index = attr->pkey_index;
+ }
+
+ if (attr_mask & IB_QP_DEST_QPN)
+ qp->remote_qpn = attr->dest_qp_num;
+
+ if (attr_mask & IB_QP_SQ_PSN) {
+ qp->s_next_psn = attr->sq_psn;
+ qp->s_last_psn = qp->s_next_psn - 1;
+ }
+
+ if (attr_mask & IB_QP_RQ_PSN)
+ qp->r_psn = attr->rq_psn;
+
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ qp->qp_access_flags = attr->qp_access_flags;
+
+ if (attr_mask & IB_QP_AV) {
+ if (attr->ah_attr.dlid == 0 ||
+ attr->ah_attr.dlid >= IPS_MULTICAST_LID_BASE)
+ goto inval;
+ qp->remote_ah_attr = attr->ah_attr;
+ }
+
+ if (attr_mask & IB_QP_PATH_MTU)
+ qp->path_mtu = attr->path_mtu;
+
+ if (attr_mask & IB_QP_RETRY_CNT)
+ qp->s_retry = qp->s_retry_cnt = attr->retry_cnt;
+
+ if (attr_mask & IB_QP_RNR_RETRY) {
+ qp->s_rnr_retry = attr->rnr_retry;
+ if (qp->s_rnr_retry > 7)
+ qp->s_rnr_retry = 7;
+ qp->s_rnr_retry_cnt = qp->s_rnr_retry;
+ }
+
+ if (attr_mask & IB_QP_MIN_RNR_TIMER) {
+ if (attr->min_rnr_timer > 31)
+ goto inval;
+ qp->s_min_rnr_timer = attr->min_rnr_timer;
+ }
+
+ if (attr_mask & IB_QP_QKEY)
+ qp->qkey = attr->qkey;
+
+ if (attr_mask & IB_QP_PKEY_INDEX)
+ qp->s_pkey_index = attr->pkey_index;
+
+ qp->state = new_state;
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+ /*
+ * If QP1 changed to the RTS state, try to move to the link to INIT
+ * even if it was ACTIVE so the SM will reinitialize the SMA's
+ * state.
+ */
+ if (qp->ibqp.qp_num == 1 && new_state == IB_QPS_RTS) {
+ struct ipath_ibdev *dev = to_idev(ibqp->device);
+
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
+ }
+ ret = 0;
+ goto bail;
+
+inval:
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ ret = -EINVAL;
+
+bail:
+ return ret;
+}
+
+int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_qp_init_attr *init_attr)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+
+ attr->qp_state = qp->state;
+ attr->cur_qp_state = attr->qp_state;
+ attr->path_mtu = qp->path_mtu;
+ attr->path_mig_state = 0;
+ attr->qkey = qp->qkey;
+ attr->rq_psn = qp->r_psn;
+ attr->sq_psn = qp->s_next_psn;
+ attr->dest_qp_num = qp->remote_qpn;
+ attr->qp_access_flags = qp->qp_access_flags;
+ attr->cap.max_send_wr = qp->s_size - 1;
+ attr->cap.max_recv_wr = qp->r_rq.size - 1;
+ attr->cap.max_send_sge = qp->s_max_sge;
+ attr->cap.max_recv_sge = qp->r_rq.max_sge;
+ attr->cap.max_inline_data = 0;
+ attr->ah_attr = qp->remote_ah_attr;
+ memset(&attr->alt_ah_attr, 0, sizeof(attr->alt_ah_attr));
+ attr->pkey_index = qp->s_pkey_index;
+ attr->alt_pkey_index = 0;
+ attr->en_sqd_async_notify = 0;
+ attr->sq_draining = 0;
+ attr->max_rd_atomic = 1;
+ attr->max_dest_rd_atomic = 1;
+ attr->min_rnr_timer = qp->s_min_rnr_timer;
+ attr->port_num = 1;
+ attr->timeout = 0;
+ attr->retry_cnt = qp->s_retry_cnt;
+ attr->rnr_retry = qp->s_rnr_retry;
+ attr->alt_port_num = 0;
+ attr->alt_timeout = 0;
+
+ init_attr->event_handler = qp->ibqp.event_handler;
+ init_attr->qp_context = qp->ibqp.qp_context;
+ init_attr->send_cq = qp->ibqp.send_cq;
+ init_attr->recv_cq = qp->ibqp.recv_cq;
+ init_attr->srq = qp->ibqp.srq;
+ init_attr->cap = attr->cap;
+ init_attr->sq_sig_type =
+ (qp->s_flags & (1 << IPATH_S_SIGNAL_REQ_WR))
+ ? IB_SIGNAL_REQ_WR : 0;
+ init_attr->qp_type = qp->ibqp.qp_type;
+ init_attr->port_num = 1;
+ return 0;
+}
+
+/**
+ * ipath_compute_aeth - compute the AETH (syndrome + MSN)
+ * @qp: the queue pair to compute the AETH for
+ *
+ * Returns the AETH.
+ *
+ * The QP s_lock should be held.
+ */
+__be32 ipath_compute_aeth(struct ipath_qp *qp)
+{
+ u32 aeth = atomic_read(&qp->msn) & IPS_MSN_MASK;
+
+ if (qp->s_nak_state) {
+ aeth |= qp->s_nak_state << IPS_AETH_CREDIT_SHIFT;
+ } else if (qp->ibqp.srq) {
+ /*
+ * Shared receive queues don't generate credits.
+ * Set the credit field to the invalid value.
+ */
+ aeth |= IPS_AETH_CREDIT_INVAL << IPS_AETH_CREDIT_SHIFT;
+ } else {
+ u32 min, max, x;
+ u32 credits;
+
+ /*
+ * Compute the number of credits available (RWQEs).
+ * XXX Not holding the r_rq.lock here so there is a small
+ * chance that the pair of reads are not atomic.
+ */
+ credits = qp->r_rq.head - qp->r_rq.tail;
+ if ((int)credits < 0)
+ credits += qp->r_rq.size;
+ /*
+ * Binary search the credit table to find the code to
+ * use.
+ */
+ min = 0;
+ max = 31;
+ for (;;) {
+ x = (min + max) / 2;
+ if (credit_table[x] == credits)
+ break;
+ if (credit_table[x] > credits)
+ max = x;
+ else if (min == x)
+ break;
+ else
+ min = x;
+ }
+ aeth |= x << IPS_AETH_CREDIT_SHIFT;
+ }
+ return cpu_to_be32(aeth);
+}
+
+/**
+ * ipath_create_qp - create a queue pair for a device
+ * @ibpd: the protection domain who's device we create the queue pair for
+ * @init_attr: the attributes of the queue pair
+ * @udata: unused by InfiniPath
+ *
+ * Returns the queue pair on success, otherwise returns an errno.
+ *
+ * Called by the ib_create_qp() core verbs function.
+ */
+struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct ipath_qp *qp;
+ int err;
+ struct ipath_swqe *swq = NULL;
+ struct ipath_ibdev *dev;
+ size_t sz;
+ struct ib_qp *ret;
+
+ if (init_attr->cap.max_send_sge > 255 ||
+ init_attr->cap.max_recv_sge > 255) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ switch (init_attr->qp_type) {
+ case IB_QPT_UC:
+ case IB_QPT_RC:
+ sz = sizeof(struct ipath_sge) *
+ init_attr->cap.max_send_sge +
+ sizeof(struct ipath_swqe);
+ swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz);
+ if (swq == NULL) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+ /* FALLTHROUGH */
+ case IB_QPT_UD:
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ qp = kmalloc(sizeof(*qp), GFP_KERNEL);
+ if (!qp) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+ qp->r_rq.size = init_attr->cap.max_recv_wr + 1;
+ sz = sizeof(struct ipath_sge) *
+ init_attr->cap.max_recv_sge +
+ sizeof(struct ipath_rwqe);
+ qp->r_rq.wq = vmalloc(qp->r_rq.size * sz);
+ if (!qp->r_rq.wq) {
+ kfree(qp);
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * ib_create_qp() will initialize qp->ibqp
+ * except for qp->ibqp.qp_num.
+ */
+ spin_lock_init(&qp->s_lock);
+ spin_lock_init(&qp->r_rq.lock);
+ atomic_set(&qp->refcount, 0);
+ init_waitqueue_head(&qp->wait);
+ tasklet_init(&qp->s_task,
+ init_attr->qp_type == IB_QPT_RC ?
+ ipath_do_rc_send : ipath_do_uc_send,
+ (unsigned long)qp);
+ qp->piowait.next = LIST_POISON1;
+ qp->piowait.prev = LIST_POISON2;
+ qp->timerwait.next = LIST_POISON1;
+ qp->timerwait.prev = LIST_POISON2;
+ qp->state = IB_QPS_RESET;
+ qp->s_wq = swq;
+ qp->s_size = init_attr->cap.max_send_wr + 1;
+ qp->s_max_sge = init_attr->cap.max_send_sge;
+ qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
+ qp->s_flags = init_attr->sq_sig_type == IB_SIGNAL_REQ_WR ?
+ 1 << IPATH_S_SIGNAL_REQ_WR : 0;
+ dev = to_idev(ibpd->device);
+ err = ipath_alloc_qpn(&dev->qp_table, qp,
+ init_attr->qp_type);
+ if (err) {
+ vfree(swq);
+ vfree(qp->r_rq.wq);
+ kfree(qp);
+ ret = ERR_PTR(err);
+ goto bail;
+ }
+ ipath_reset_qp(qp);
+
+ /* Tell the core driver that the kernel SMA is present. */
+ if (qp->ibqp.qp_type == IB_QPT_SMI)
+ ipath_layer_set_verbs_flags(dev->dd,
+ IPATH_VERBS_KERNEL_SMA);
+ break;
+
+ default:
+ /* Don't support raw QPs */
+ ret = ERR_PTR(-ENOSYS);
+ goto bail;
+ }
+
+ init_attr->cap.max_inline_data = 0;
+
+ ret = &qp->ibqp;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_destroy_qp - destroy a queue pair
+ * @ibqp: the queue pair to destroy
+ *
+ * Returns 0 on success.
+ *
+ * Note that this can be called while the QP is actively sending or
+ * receiving!
+ */
+int ipath_destroy_qp(struct ib_qp *ibqp)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ struct ipath_ibdev *dev = to_idev(ibqp->device);
+ unsigned long flags;
+
+ /* Tell the core driver that the kernel SMA is gone. */
+ if (qp->ibqp.qp_type == IB_QPT_SMI)
+ ipath_layer_set_verbs_flags(dev->dd, 0);
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ spin_lock(&qp->s_lock);
+ qp->state = IB_QPS_ERR;
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+ /* Stop the sending tasklet. */
+ tasklet_kill(&qp->s_task);
+
+ /* Make sure the QP isn't on the timeout list. */
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (qp->timerwait.next != LIST_POISON1)
+ list_del(&qp->timerwait);
+ if (qp->piowait.next != LIST_POISON1)
+ list_del(&qp->piowait);
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ /*
+ * Make sure that the QP is not in the QPN table so receive
+ * interrupts will discard packets for this QP. XXX Also remove QP
+ * from multicast table.
+ */
+ if (atomic_read(&qp->refcount) != 0)
+ ipath_free_qp(&dev->qp_table, qp);
+
+ vfree(qp->s_wq);
+ vfree(qp->r_rq.wq);
+ kfree(qp);
+ return 0;
+}
+
+/**
+ * ipath_init_qp_table - initialize the QP table for a device
+ * @idev: the device who's QP table we're initializing
+ * @size: the size of the QP table
+ *
+ * Returns 0 on success, otherwise returns an errno.
+ */
+int ipath_init_qp_table(struct ipath_ibdev *idev, int size)
+{
+ int i;
+ int ret;
+
+ idev->qp_table.last = 1; /* QPN 0 and 1 are special. */
+ idev->qp_table.max = size;
+ idev->qp_table.nmaps = 1;
+ idev->qp_table.table = kzalloc(size * sizeof(*idev->qp_table.table),
+ GFP_KERNEL);
+ if (idev->qp_table.table == NULL) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(idev->qp_table.map); i++) {
+ atomic_set(&idev->qp_table.map[i].n_free, BITS_PER_PAGE);
+ idev->qp_table.map[i].page = NULL;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_sqerror_qp - put a QP's send queue into an error state
+ * @qp: QP who's send queue will be put into an error state
+ * @wc: the WC responsible for putting the QP in this state
+ *
+ * Flushes the send work queue.
+ * The QP s_lock should be held.
+ */
+
+void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+ _VERBS_INFO("Send queue error on QP%d/%d: err: %d\n",
+ qp->ibqp.qp_num, qp->remote_qpn, wc->status);
+
+ spin_lock(&dev->pending_lock);
+ /* XXX What if its already removed by the timeout code? */
+ if (qp->timerwait.next != LIST_POISON1)
+ list_del(&qp->timerwait);
+ if (qp->piowait.next != LIST_POISON1)
+ list_del(&qp->piowait);
+ spin_unlock(&dev->pending_lock);
+
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1);
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+
+ wc->status = IB_WC_WR_FLUSH_ERR;
+
+ while (qp->s_last != qp->s_head) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1);
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ }
+ qp->s_cur = qp->s_tail = qp->s_head;
+ qp->state = IB_QPS_SQE;
+}
+
+/**
+ * ipath_get_credit - flush the send work queue of a QP
+ * @qp: the qp who's send work queue to flush
+ * @aeth: the Acknowledge Extended Transport Header
+ *
+ * The QP s_lock should be held.
+ */
+void ipath_get_credit(struct ipath_qp *qp, u32 aeth)
+{
+ u32 credit = (aeth >> IPS_AETH_CREDIT_SHIFT) & IPS_AETH_CREDIT_MASK;
+
+ /*
+ * If the credit is invalid, we can send
+ * as many packets as we like. Otherwise, we have to
+ * honor the credit field.
+ */
+ if (credit == IPS_AETH_CREDIT_INVAL) {
+ qp->s_lsn = (u32) -1;
+ } else if (qp->s_lsn != (u32) -1) {
+ /* Compute new LSN (i.e., MSN + credit) */
+ credit = (aeth + credit_table[credit]) & IPS_MSN_MASK;
+ if (ipath_cmp24(credit, qp->s_lsn) > 0)
+ qp->s_lsn = credit;
+ }
+
+ /* Restart sending if it was blocked due to lack of credits. */
+ if (qp->s_cur != qp->s_head &&
+ (qp->s_lsn == (u32) -1 ||
+ ipath_cmp24(get_swqe_ptr(qp, qp->s_cur)->ssn,
+ qp->s_lsn + 1) <= 0))
+ tasklet_hi_schedule(&qp->s_task);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
new file mode 100644
index 000000000000..a4055ca00614
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -0,0 +1,1857 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* cut down ridiculously long IB macro names */
+#define OP(x) IB_OPCODE_RC_##x
+
+/**
+ * ipath_init_restart- initialize the qp->s_sge after a restart
+ * @qp: the QP who's SGE we're restarting
+ * @wqe: the work queue to initialize the QP's SGE from
+ *
+ * The QP s_lock should be held.
+ */
+static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe)
+{
+ struct ipath_ibdev *dev;
+ u32 len;
+
+ len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) *
+ ib_mtu_enum_to_int(qp->path_mtu);
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+ qp->s_sge.num_sge = wqe->wr.num_sge;
+ ipath_skip_sge(&qp->s_sge, len);
+ qp->s_len = wqe->length - len;
+ dev = to_idev(qp->ibqp.device);
+ spin_lock(&dev->pending_lock);
+ if (qp->timerwait.next == LIST_POISON1)
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+}
+
+/**
+ * ipath_make_rc_ack - construct a response packet (ACK, NAK, or RDMA read)
+ * @qp: a pointer to the QP
+ * @ohdr: a pointer to the IB header being constructed
+ * @pmtu: the path MTU
+ *
+ * Return bth0 if constructed; otherwise, return 0.
+ * Note the QP s_lock must be held.
+ */
+static inline u32 ipath_make_rc_ack(struct ipath_qp *qp,
+ struct ipath_other_headers *ohdr,
+ u32 pmtu)
+{
+ struct ipath_sge_state *ss;
+ u32 hwords;
+ u32 len;
+ u32 bth0;
+
+ /* header size in 32-bit words LRH+BTH = (8+12)/4. */
+ hwords = 5;
+
+ /*
+ * Send a response. Note that we are in the responder's
+ * side of the QP context.
+ */
+ switch (qp->s_ack_state) {
+ case OP(RDMA_READ_REQUEST):
+ ss = &qp->s_rdma_sge;
+ len = qp->s_rdma_len;
+ if (len > pmtu) {
+ len = pmtu;
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
+ }
+ else
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
+ qp->s_rdma_len -= len;
+ bth0 = qp->s_ack_state << 24;
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ hwords++;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_FIRST):
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(RDMA_READ_RESPONSE_MIDDLE):
+ ss = &qp->s_rdma_sge;
+ len = qp->s_rdma_len;
+ if (len > pmtu)
+ len = pmtu;
+ else {
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ hwords++;
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
+ }
+ qp->s_rdma_len -= len;
+ bth0 = qp->s_ack_state << 24;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_LAST):
+ case OP(RDMA_READ_RESPONSE_ONLY):
+ /*
+ * We have to prevent new requests from changing
+ * the r_sge state while a ipath_verbs_send()
+ * is in progress.
+ * Changing r_state allows the receiver
+ * to continue processing new packets.
+ * We do it here now instead of above so
+ * that we are sure the packet was sent before
+ * changing the state.
+ */
+ qp->r_state = OP(RDMA_READ_RESPONSE_LAST);
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ return 0;
+
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ ss = NULL;
+ len = 0;
+ qp->r_state = OP(SEND_LAST);
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ bth0 = IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24;
+ ohdr->u.at.aeth = ipath_compute_aeth(qp);
+ ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic);
+ hwords += sizeof(ohdr->u.at) / 4;
+ break;
+
+ default:
+ /* Send a regular ACK. */
+ ss = NULL;
+ len = 0;
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ bth0 = qp->s_ack_state << 24;
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ hwords++;
+ }
+ qp->s_hdrwords = hwords;
+ qp->s_cur_sge = ss;
+ qp->s_cur_size = len;
+
+ return bth0;
+}
+
+/**
+ * ipath_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC)
+ * @qp: a pointer to the QP
+ * @ohdr: a pointer to the IB header being constructed
+ * @pmtu: the path MTU
+ * @bth0p: pointer to the BTH opcode word
+ * @bth2p: pointer to the BTH PSN word
+ *
+ * Return 1 if constructed; otherwise, return 0.
+ * Note the QP s_lock must be held.
+ */
+static inline int ipath_make_rc_req(struct ipath_qp *qp,
+ struct ipath_other_headers *ohdr,
+ u32 pmtu, u32 *bth0p, u32 *bth2p)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_sge_state *ss;
+ struct ipath_swqe *wqe;
+ u32 hwords;
+ u32 len;
+ u32 bth0;
+ u32 bth2;
+ char newreq;
+
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) ||
+ qp->s_rnr_timeout)
+ goto done;
+
+ /* header size in 32-bit words LRH+BTH = (8+12)/4. */
+ hwords = 5;
+ bth0 = 0;
+
+ /* Send a request. */
+ wqe = get_swqe_ptr(qp, qp->s_cur);
+ switch (qp->s_state) {
+ default:
+ /*
+ * Resend an old request or start a new one.
+ *
+ * We keep track of the current SWQE so that
+ * we don't reset the "furthest progress" state
+ * if we need to back up.
+ */
+ newreq = 0;
+ if (qp->s_cur == qp->s_tail) {
+ /* Check if send work queue is empty. */
+ if (qp->s_tail == qp->s_head)
+ goto done;
+ qp->s_psn = wqe->psn = qp->s_next_psn;
+ newreq = 1;
+ }
+ /*
+ * Note that we have to be careful not to modify the
+ * original work request since we may need to resend
+ * it.
+ */
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+ qp->s_sge.num_sge = wqe->wr.num_sge;
+ qp->s_len = len = wqe->length;
+ ss = &qp->s_sge;
+ bth2 = 0;
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ /* If no credit, return. */
+ if (qp->s_lsn != (u32) -1 &&
+ ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0)
+ goto done;
+ wqe->lpsn = wqe->psn;
+ if (len > pmtu) {
+ wqe->lpsn += (len - 1) / pmtu;
+ qp->s_state = OP(SEND_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_ONLY);
+ else {
+ qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ bth2 = 1 << 31; /* Request ACK. */
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ if (newreq)
+ qp->s_lsn++;
+ /* FALLTHROUGH */
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ /* If no credit, return. */
+ if (qp->s_lsn != (u32) -1 &&
+ ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0)
+ goto done;
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(len);
+ hwords += sizeof(struct ib_reth) / 4;
+ wqe->lpsn = wqe->psn;
+ if (len > pmtu) {
+ wqe->lpsn += (len - 1) / pmtu;
+ qp->s_state = OP(RDMA_WRITE_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_ONLY);
+ else {
+ qp->s_state =
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes
+ * after RETH */
+ ohdr->u.rc.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ bth2 = 1 << 31; /* Request ACK. */
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case IB_WR_RDMA_READ:
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(len);
+ qp->s_state = OP(RDMA_READ_REQUEST);
+ hwords += sizeof(ohdr->u.rc.reth) / 4;
+ if (newreq) {
+ qp->s_lsn++;
+ /*
+ * Adjust s_next_psn to count the
+ * expected number of responses.
+ */
+ if (len > pmtu)
+ qp->s_next_psn += (len - 1) / pmtu;
+ wqe->lpsn = qp->s_next_psn++;
+ }
+ ss = NULL;
+ len = 0;
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP)
+ qp->s_state = OP(COMPARE_SWAP);
+ else
+ qp->s_state = OP(FETCH_ADD);
+ ohdr->u.atomic_eth.vaddr = cpu_to_be64(
+ wqe->wr.wr.atomic.remote_addr);
+ ohdr->u.atomic_eth.rkey = cpu_to_be32(
+ wqe->wr.wr.atomic.rkey);
+ ohdr->u.atomic_eth.swap_data = cpu_to_be64(
+ wqe->wr.wr.atomic.swap);
+ ohdr->u.atomic_eth.compare_data = cpu_to_be64(
+ wqe->wr.wr.atomic.compare_add);
+ hwords += sizeof(struct ib_atomic_eth) / 4;
+ if (newreq) {
+ qp->s_lsn++;
+ wqe->lpsn = wqe->psn;
+ }
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ ss = NULL;
+ len = 0;
+ break;
+
+ default:
+ goto done;
+ }
+ if (newreq) {
+ qp->s_tail++;
+ if (qp->s_tail >= qp->s_size)
+ qp->s_tail = 0;
+ }
+ bth2 |= qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ spin_lock(&dev->pending_lock);
+ if (qp->timerwait.next == LIST_POISON1)
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+ break;
+
+ case OP(RDMA_READ_RESPONSE_FIRST):
+ /*
+ * This case can only happen if a send is restarted. See
+ * ipath_restart_rc().
+ */
+ ipath_init_restart(qp, wqe);
+ /* FALLTHROUGH */
+ case OP(SEND_FIRST):
+ qp->s_state = OP(SEND_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ bth2 = qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ ss = &qp->s_sge;
+ len = qp->s_len;
+ if (len > pmtu) {
+ /*
+ * Request an ACK every 1/2 MB to avoid retransmit
+ * timeouts.
+ */
+ if (((wqe->length - len) % (512 * 1024)) == 0)
+ bth2 |= 1 << 31;
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_LAST);
+ else {
+ qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ bth2 |= 1 << 31; /* Request ACK. */
+ qp->s_cur++;
+ if (qp->s_cur >= qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_LAST):
+ /*
+ * This case can only happen if a RDMA write is restarted.
+ * See ipath_restart_rc().
+ */
+ ipath_init_restart(qp, wqe);
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_FIRST):
+ qp->s_state = OP(RDMA_WRITE_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_MIDDLE):
+ bth2 = qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ ss = &qp->s_sge;
+ len = qp->s_len;
+ if (len > pmtu) {
+ /*
+ * Request an ACK every 1/2 MB to avoid retransmit
+ * timeouts.
+ */
+ if (((wqe->length - len) % (512 * 1024)) == 0)
+ bth2 |= 1 << 31;
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_LAST);
+ else {
+ qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ bth2 |= 1 << 31; /* Request ACK. */
+ qp->s_cur++;
+ if (qp->s_cur >= qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_MIDDLE):
+ /*
+ * This case can only happen if a RDMA read is restarted.
+ * See ipath_restart_rc().
+ */
+ ipath_init_restart(qp, wqe);
+ len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) * pmtu;
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len);
+ qp->s_state = OP(RDMA_READ_REQUEST);
+ hwords += sizeof(ohdr->u.rc.reth) / 4;
+ bth2 = qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ ss = NULL;
+ len = 0;
+ qp->s_cur++;
+ if (qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case OP(RDMA_READ_REQUEST):
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ /*
+ * We shouldn't start anything new until this request is
+ * finished. The ACK will handle rescheduling us. XXX The
+ * number of outstanding ones is negotiated at connection
+ * setup time (see pg. 258,289)? XXX Also, if we support
+ * multiple outstanding requests, we need to check the WQE
+ * IB_SEND_FENCE flag and not send a new request if a RDMA
+ * read or atomic is pending.
+ */
+ goto done;
+ }
+ qp->s_len -= len;
+ qp->s_hdrwords = hwords;
+ qp->s_cur_sge = ss;
+ qp->s_cur_size = len;
+ *bth0p = bth0 | (qp->s_state << 24);
+ *bth2p = bth2;
+ return 1;
+
+done:
+ return 0;
+}
+
+static inline void ipath_make_rc_grh(struct ipath_qp *qp,
+ struct ib_global_route *grh,
+ u32 nwords)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+
+ /* GRH header size in 32-bit words. */
+ qp->s_hdrwords += 10;
+ qp->s_hdr.u.l.grh.version_tclass_flow =
+ cpu_to_be32((6 << 28) |
+ (grh->traffic_class << 20) |
+ grh->flow_label);
+ qp->s_hdr.u.l.grh.paylen =
+ cpu_to_be16(((qp->s_hdrwords - 12) + nwords +
+ SIZE_OF_CRC) << 2);
+ /* next_hdr is defined by C8-7 in ch. 8.4.1 */
+ qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+ qp->s_hdr.u.l.grh.hop_limit = grh->hop_limit;
+ /* The SGID is 32-bit aligned. */
+ qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = dev->gid_prefix;
+ qp->s_hdr.u.l.grh.sgid.global.interface_id =
+ ipath_layer_get_guid(dev->dd);
+ qp->s_hdr.u.l.grh.dgid = grh->dgid;
+}
+
+/**
+ * ipath_do_rc_send - perform a send on an RC QP
+ * @data: contains a pointer to the QP
+ *
+ * Process entries in the send work queue until credit or queue is
+ * exhausted. Only allow one CPU to send a packet per QP (tasklet).
+ * Otherwise, after we drop the QP s_lock, two threads could send
+ * packets out of order.
+ */
+void ipath_do_rc_send(unsigned long data)
+{
+ struct ipath_qp *qp = (struct ipath_qp *)data;
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ unsigned long flags;
+ u16 lrh0;
+ u32 nwords;
+ u32 extra_bytes;
+ u32 bth0;
+ u32 bth2;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ struct ipath_other_headers *ohdr;
+
+ if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
+ goto bail;
+
+ if (unlikely(qp->remote_ah_attr.dlid ==
+ ipath_layer_get_lid(dev->dd))) {
+ struct ib_wc wc;
+
+ /*
+ * Pass in an uninitialized ib_wc to be consistent with
+ * other places where ipath_ruc_loopback() is called.
+ */
+ ipath_ruc_loopback(qp, &wc);
+ goto clear;
+ }
+
+ ohdr = &qp->s_hdr.u.oth;
+ if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
+ ohdr = &qp->s_hdr.u.l.oth;
+
+again:
+ /* Check for a constructed packet to be sent. */
+ if (qp->s_hdrwords != 0) {
+ /*
+ * If no PIO bufs are available, return. An interrupt will
+ * call ipath_ib_piobufavail() when one is available.
+ */
+ _VERBS_INFO("h %u %p\n", qp->s_hdrwords, &qp->s_hdr);
+ _VERBS_INFO("d %u %p %u %p %u %u %u %u\n", qp->s_cur_size,
+ qp->s_cur_sge->sg_list,
+ qp->s_cur_sge->num_sge,
+ qp->s_cur_sge->sge.vaddr,
+ qp->s_cur_sge->sge.sge_length,
+ qp->s_cur_sge->sge.length,
+ qp->s_cur_sge->sge.m,
+ qp->s_cur_sge->sge.n);
+ if (ipath_verbs_send(dev->dd, qp->s_hdrwords,
+ (u32 *) &qp->s_hdr, qp->s_cur_size,
+ qp->s_cur_sge)) {
+ ipath_no_bufs_available(qp, dev);
+ goto bail;
+ }
+ dev->n_unicast_xmit++;
+ /* Record that we sent the packet and s_hdr is empty. */
+ qp->s_hdrwords = 0;
+ }
+
+ /*
+ * The lock is needed to synchronize between setting
+ * qp->s_ack_state, resend timer, and post_send().
+ */
+ spin_lock_irqsave(&qp->s_lock, flags);
+
+ /* Sending responses has higher priority over sending requests. */
+ if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+ (bth0 = ipath_make_rc_ack(qp, ohdr, pmtu)) != 0)
+ bth2 = qp->s_ack_psn++ & IPS_PSN_MASK;
+ else if (!ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2))
+ goto done;
+
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ /* Construct the header. */
+ extra_bytes = (4 - qp->s_cur_size) & 3;
+ nwords = (qp->s_cur_size + extra_bytes) >> 2;
+ lrh0 = IPS_LRH_BTH;
+ if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+ ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, nwords);
+ lrh0 = IPS_LRH_GRH;
+ }
+ lrh0 |= qp->remote_ah_attr.sl << 4;
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords +
+ SIZE_OF_CRC);
+ qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+ bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+ bth0 |= extra_bytes << 20;
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(bth2);
+
+ /* Check for more work to do. */
+ goto again;
+
+done:
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+clear:
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+bail:
+ return;
+}
+
+static void send_rc_ack(struct ipath_qp *qp)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ u16 lrh0;
+ u32 bth0;
+ struct ipath_other_headers *ohdr;
+
+ /* Construct the header. */
+ ohdr = &qp->s_hdr.u.oth;
+ lrh0 = IPS_LRH_BTH;
+ /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */
+ qp->s_hdrwords = 6;
+ if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+ ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, 0);
+ ohdr = &qp->s_hdr.u.l.oth;
+ lrh0 = IPS_LRH_GRH;
+ }
+ bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ if (qp->s_ack_state >= OP(COMPARE_SWAP)) {
+ bth0 |= IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24;
+ ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic);
+ qp->s_hdrwords += sizeof(ohdr->u.at.atomic_ack_eth) / 4;
+ }
+ else
+ bth0 |= OP(ACKNOWLEDGE) << 24;
+ lrh0 |= qp->remote_ah_attr.sl << 4;
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + SIZE_OF_CRC);
+ qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(qp->s_ack_psn & IPS_PSN_MASK);
+
+ /*
+ * If we can send the ACK, clear the ACK state.
+ */
+ if (ipath_verbs_send(dev->dd, qp->s_hdrwords, (u32 *) &qp->s_hdr,
+ 0, NULL) == 0) {
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ dev->n_rc_qacks++;
+ dev->n_unicast_xmit++;
+ }
+}
+
+/**
+ * ipath_restart_rc - back up requester to resend the last un-ACKed request
+ * @qp: the QP to restart
+ * @psn: packet sequence number for the request
+ * @wc: the work completion request
+ *
+ * The QP s_lock should be held.
+ */
+void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
+{
+ struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+ struct ipath_ibdev *dev;
+ u32 n;
+
+ /*
+ * If there are no requests pending, we are done.
+ */
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0 ||
+ qp->s_last == qp->s_tail)
+ goto done;
+
+ if (qp->s_retry == 0) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = IB_WC_RETRY_EXC_ERR;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = 0;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = qp->remote_qpn;
+ wc->pkey_index = 0;
+ wc->slid = qp->remote_ah_attr.dlid;
+ wc->sl = qp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_sqerror_qp(qp, wc);
+ goto bail;
+ }
+ qp->s_retry--;
+
+ /*
+ * Remove the QP from the timeout queue.
+ * Note: it may already have been removed by ipath_ib_timer().
+ */
+ dev = to_idev(qp->ibqp.device);
+ spin_lock(&dev->pending_lock);
+ if (qp->timerwait.next != LIST_POISON1)
+ list_del(&qp->timerwait);
+ spin_unlock(&dev->pending_lock);
+
+ if (wqe->wr.opcode == IB_WR_RDMA_READ)
+ dev->n_rc_resends++;
+ else
+ dev->n_rc_resends += (int)qp->s_psn - (int)psn;
+
+ /*
+ * If we are starting the request from the beginning, let the normal
+ * send code handle initialization.
+ */
+ qp->s_cur = qp->s_last;
+ if (ipath_cmp24(psn, wqe->psn) <= 0) {
+ qp->s_state = OP(SEND_LAST);
+ qp->s_psn = wqe->psn;
+ } else {
+ n = qp->s_cur;
+ for (;;) {
+ if (++n == qp->s_size)
+ n = 0;
+ if (n == qp->s_tail) {
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0) {
+ qp->s_cur = n;
+ wqe = get_swqe_ptr(qp, n);
+ }
+ break;
+ }
+ wqe = get_swqe_ptr(qp, n);
+ if (ipath_cmp24(psn, wqe->psn) < 0)
+ break;
+ qp->s_cur = n;
+ }
+ qp->s_psn = psn;
+
+ /*
+ * Reset the state to restart in the middle of a request.
+ * Don't change the s_sge, s_cur_sge, or s_cur_size.
+ * See ipath_do_rc_send().
+ */
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_FIRST);
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_LAST);
+ break;
+
+ case IB_WR_RDMA_READ:
+ qp->s_state =
+ OP(RDMA_READ_RESPONSE_MIDDLE);
+ break;
+
+ default:
+ /*
+ * This case shouldn't happen since its only
+ * one PSN per req.
+ */
+ qp->s_state = OP(SEND_LAST);
+ }
+ }
+
+done:
+ tasklet_hi_schedule(&qp->s_task);
+
+bail:
+ return;
+}
+
+/**
+ * reset_psn - reset the QP state to send starting from PSN
+ * @qp: the QP
+ * @psn: the packet sequence number to restart at
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC ACK
+ * for the given QP.
+ * Called at interrupt level with the QP s_lock held.
+ */
+static void reset_psn(struct ipath_qp *qp, u32 psn)
+{
+ struct ipath_swqe *wqe;
+ u32 n;
+
+ n = qp->s_cur;
+ wqe = get_swqe_ptr(qp, n);
+ for (;;) {
+ if (++n == qp->s_size)
+ n = 0;
+ if (n == qp->s_tail) {
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0) {
+ qp->s_cur = n;
+ wqe = get_swqe_ptr(qp, n);
+ }
+ break;
+ }
+ wqe = get_swqe_ptr(qp, n);
+ if (ipath_cmp24(psn, wqe->psn) < 0)
+ break;
+ qp->s_cur = n;
+ }
+ qp->s_psn = psn;
+
+ /*
+ * Set the state to restart in the middle of a
+ * request. Don't change the s_sge, s_cur_sge, or
+ * s_cur_size. See ipath_do_rc_send().
+ */
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_FIRST);
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_LAST);
+ break;
+
+ case IB_WR_RDMA_READ:
+ qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE);
+ break;
+
+ default:
+ /*
+ * This case shouldn't happen since its only
+ * one PSN per req.
+ */
+ qp->s_state = OP(SEND_LAST);
+ }
+}
+
+/**
+ * do_rc_ack - process an incoming RC ACK
+ * @qp: the QP the ACK came in on
+ * @psn: the packet sequence number of the ACK
+ * @opcode: the opcode of the request that resulted in the ACK
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC ACK
+ * for the given QP.
+ * Called at interrupt level with the QP s_lock held.
+ * 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)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ib_wc wc;
+ struct ipath_swqe *wqe;
+ int ret = 0;
+
+ /*
+ * Remove the QP from the timeout queue (or RNR timeout queue).
+ * If ipath_ib_timer() has already removed it,
+ * it's OK since we hold the QP s_lock and ipath_restart_rc()
+ * just won't find anything to restart if we ACK everything.
+ */
+ spin_lock(&dev->pending_lock);
+ if (qp->timerwait.next != LIST_POISON1)
+ list_del(&qp->timerwait);
+ spin_unlock(&dev->pending_lock);
+
+ /*
+ * Note that NAKs implicitly ACK outstanding SEND and RDMA write
+ * requests and implicitly NAK RDMA read and atomic requests issued
+ * before the NAK'ed request. The MSN won't include the NAK'ed
+ * request but will include an ACK'ed request(s).
+ */
+ wqe = get_swqe_ptr(qp, qp->s_last);
+
+ /* Nothing is pending to ACK/NAK. */
+ if (qp->s_last == qp->s_tail)
+ goto bail;
+
+ /*
+ * The MSN might be for a later WQE than the PSN indicates so
+ * only complete WQEs that the PSN finishes.
+ */
+ while (ipath_cmp24(psn, wqe->lpsn) >= 0) {
+ /* If we are ACKing a WQE, the MSN should be >= the SSN. */
+ if (ipath_cmp24(aeth, wqe->ssn) < 0)
+ break;
+ /*
+ * If this request is a RDMA read or atomic, and the ACK is
+ * for a later operation, this ACK NAKs the RDMA read or
+ * atomic. In other words, only a RDMA_READ_LAST or ONLY
+ * can ACK a RDMA read and likewise for atomic ops. Note
+ * that the NAK case can only happen if relaxed ordering is
+ * used and requests are sent after an RDMA read or atomic
+ * is sent but before the response is received.
+ */
+ if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
+ opcode != OP(RDMA_READ_RESPONSE_LAST)) ||
+ ((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))) {
+ /*
+ * The last valid PSN seen is the previous
+ * request's.
+ */
+ qp->s_last_psn = wqe->psn - 1;
+ /* Retry this request. */
+ ipath_restart_rc(qp, wqe->psn, &wc);
+ /*
+ * No need to process the ACK/NAK since we are
+ * restarting an earlier request.
+ */
+ goto bail;
+ }
+ /* Post a send completion queue entry if requested. */
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+ wc.wr_id = wqe->wr.wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc.vendor_err = 0;
+ wc.byte_len = wqe->length;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
+ }
+ qp->s_retry = qp->s_retry_cnt;
+ /*
+ * If we are completing a request which is in the process of
+ * being resent, we can stop resending it since we know the
+ * responder has already seen it.
+ */
+ if (qp->s_last == qp->s_cur) {
+ if (++qp->s_cur >= qp->s_size)
+ qp->s_cur = 0;
+ wqe = get_swqe_ptr(qp, qp->s_cur);
+ qp->s_state = OP(SEND_LAST);
+ qp->s_psn = wqe->psn;
+ }
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ if (qp->s_last == qp->s_tail)
+ break;
+ }
+
+ switch (aeth >> 29) {
+ case 0: /* ACK */
+ dev->n_rc_acks++;
+ /* If this is a partial ACK, reset the retransmit timer. */
+ if (qp->s_last != qp->s_tail) {
+ spin_lock(&dev->pending_lock);
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+ }
+ ipath_get_credit(qp, aeth);
+ qp->s_rnr_retry = qp->s_rnr_retry_cnt;
+ qp->s_retry = qp->s_retry_cnt;
+ qp->s_last_psn = psn;
+ ret = 1;
+ goto bail;
+
+ case 1: /* RNR NAK */
+ dev->n_rnr_naks++;
+ if (qp->s_rnr_retry == 0) {
+ if (qp->s_last == qp->s_tail)
+ goto bail;
+
+ wc.status = IB_WC_RNR_RETRY_EXC_ERR;
+ goto class_b;
+ }
+ if (qp->s_rnr_retry_cnt < 7)
+ qp->s_rnr_retry--;
+ if (qp->s_last == qp->s_tail)
+ goto bail;
+
+ /* The last valid PSN seen is the previous request's. */
+ qp->s_last_psn = wqe->psn - 1;
+
+ dev->n_rc_resends += (int)qp->s_psn - (int)psn;
+
+ /*
+ * If we are starting the request from the beginning, let
+ * the normal send code handle initialization.
+ */
+ qp->s_cur = qp->s_last;
+ wqe = get_swqe_ptr(qp, qp->s_cur);
+ if (ipath_cmp24(psn, wqe->psn) <= 0) {
+ qp->s_state = OP(SEND_LAST);
+ qp->s_psn = wqe->psn;
+ } else
+ reset_psn(qp, psn);
+
+ qp->s_rnr_timeout =
+ ib_ipath_rnr_table[(aeth >> IPS_AETH_CREDIT_SHIFT) &
+ IPS_AETH_CREDIT_MASK];
+ ipath_insert_rnr_queue(qp);
+ goto bail;
+
+ case 3: /* NAK */
+ /* The last valid PSN seen is the previous request's. */
+ if (qp->s_last != qp->s_tail)
+ qp->s_last_psn = wqe->psn - 1;
+ switch ((aeth >> IPS_AETH_CREDIT_SHIFT) &
+ IPS_AETH_CREDIT_MASK) {
+ case 0: /* PSN sequence error */
+ dev->n_seq_naks++;
+ /*
+ * Back up to the responder's expected PSN. XXX
+ * Note that we might get a NAK in the middle of an
+ * RDMA READ response which terminates the RDMA
+ * READ.
+ */
+ if (qp->s_last == qp->s_tail)
+ break;
+
+ if (ipath_cmp24(psn, wqe->psn) < 0)
+ break;
+
+ /* Retry the request. */
+ ipath_restart_rc(qp, psn, &wc);
+ break;
+
+ case 1: /* Invalid Request */
+ wc.status = IB_WC_REM_INV_REQ_ERR;
+ dev->n_other_naks++;
+ goto class_b;
+
+ case 2: /* Remote Access Error */
+ wc.status = IB_WC_REM_ACCESS_ERR;
+ dev->n_other_naks++;
+ goto class_b;
+
+ case 3: /* Remote Operation Error */
+ wc.status = IB_WC_REM_OP_ERR;
+ dev->n_other_naks++;
+ class_b:
+ wc.wr_id = wqe->wr.wr_id;
+ wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc.vendor_err = 0;
+ wc.byte_len = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ ipath_sqerror_qp(qp, &wc);
+ break;
+
+ default:
+ /* Ignore other reserved NAK error codes */
+ goto reserved;
+ }
+ qp->s_rnr_retry = qp->s_rnr_retry_cnt;
+ goto bail;
+
+ default: /* 2: reserved */
+ reserved:
+ /* Ignore reserved NAK codes. */
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_rc_rcv_resp - process an incoming RC response packet
+ * @dev: the device this packet came in on
+ * @ohdr: the other headers for this packet
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP for this packet
+ * @opcode: the opcode for this packet
+ * @psn: the packet sequence number for this packet
+ * @hdrsize: the header length
+ * @pmtu: the path MTU
+ * @header_in_data: true if part of the header data is in the data buffer
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC response
+ * packet for the given QP.
+ * Called at interrupt level.
+ */
+static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
+ struct ipath_other_headers *ohdr,
+ void *data, u32 tlen,
+ struct ipath_qp *qp,
+ u32 opcode,
+ u32 psn, u32 hdrsize, u32 pmtu,
+ int header_in_data)
+{
+ unsigned long flags;
+ struct ib_wc wc;
+ int diff;
+ u32 pad;
+ u32 aeth;
+
+ spin_lock_irqsave(&qp->s_lock, flags);
+
+ /* Ignore invalid responses. */
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0)
+ goto ack_done;
+
+ /* Ignore duplicate responses. */
+ diff = ipath_cmp24(psn, qp->s_last_psn);
+ if (unlikely(diff <= 0)) {
+ /* Update credits for "ghost" ACKs */
+ if (diff == 0 && opcode == OP(ACKNOWLEDGE)) {
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else {
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ }
+ if ((aeth >> 29) == 0)
+ ipath_get_credit(qp, aeth);
+ }
+ goto ack_done;
+ }
+
+ switch (opcode) {
+ case OP(ACKNOWLEDGE):
+ case OP(ATOMIC_ACKNOWLEDGE):
+ case OP(RDMA_READ_RESPONSE_FIRST):
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else {
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ }
+ if (opcode == OP(ATOMIC_ACKNOWLEDGE))
+ *(u64 *) qp->s_sge.sge.vaddr = *(u64 *) data;
+ if (!do_rc_ack(qp, aeth, psn, opcode) ||
+ opcode != OP(RDMA_READ_RESPONSE_FIRST))
+ goto ack_done;
+ hdrsize += 4;
+ /*
+ * do_rc_ack() has already checked the PSN so skip
+ * the sequence check.
+ */
+ goto rdma_read;
+
+ case OP(RDMA_READ_RESPONSE_MIDDLE):
+ /* no AETH, no ACK */
+ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
+ dev->n_rdma_seq++;
+ ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ goto ack_done;
+ }
+ rdma_read:
+ if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST)))
+ goto ack_done;
+ if (unlikely(tlen != (hdrsize + pmtu + 4)))
+ goto ack_done;
+ if (unlikely(pmtu >= qp->s_len))
+ goto ack_done;
+ /* We got a response so update the timeout. */
+ if (unlikely(qp->s_last == qp->s_tail ||
+ get_swqe_ptr(qp, qp->s_last)->wr.opcode !=
+ IB_WR_RDMA_READ))
+ goto ack_done;
+ spin_lock(&dev->pending_lock);
+ if (qp->s_rnr_timeout == 0 &&
+ qp->timerwait.next != LIST_POISON1)
+ list_move_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+ /*
+ * Update the RDMA receive state but do the copy w/o holding the
+ * locks and blocking interrupts. XXX Yet another place that
+ * affects relaxed RDMA order since we don't want s_sge modified.
+ */
+ qp->s_len -= pmtu;
+ qp->s_last_psn = psn;
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ipath_copy_sge(&qp->s_sge, data, pmtu);
+ goto bail;
+
+ case OP(RDMA_READ_RESPONSE_LAST):
+ /* ACKs READ req. */
+ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
+ dev->n_rdma_seq++;
+ ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ goto ack_done;
+ }
+ /* FALLTHROUGH */
+ case OP(RDMA_READ_RESPONSE_ONLY):
+ if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST)))
+ goto ack_done;
+ /*
+ * Get the number of bytes the message was padded by.
+ */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /*
+ * Check that the data size is >= 1 && <= pmtu.
+ * Remember to account for the AETH header (4) and
+ * ICRC (4).
+ */
+ if (unlikely(tlen <= (hdrsize + pad + 8))) {
+ /*
+ * XXX Need to generate an error CQ
+ * entry.
+ */
+ goto ack_done;
+ }
+ tlen -= hdrsize + pad + 8;
+ if (unlikely(tlen != qp->s_len)) {
+ /*
+ * XXX Need to generate an error CQ
+ * entry.
+ */
+ goto ack_done;
+ }
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else {
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ }
+ ipath_copy_sge(&qp->s_sge, data, tlen);
+ if (do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST))) {
+ /*
+ * Change the state so we contimue
+ * processing new requests.
+ */
+ qp->s_state = OP(SEND_LAST);
+ }
+ goto ack_done;
+ }
+
+ack_done:
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+bail:
+ return;
+}
+
+/**
+ * ipath_rc_rcv_error - process an incoming duplicate or error RC packet
+ * @dev: the device this packet came in on
+ * @ohdr: the other headers for this packet
+ * @data: the packet data
+ * @qp: the QP for this packet
+ * @opcode: the opcode for this packet
+ * @psn: the packet sequence number for this packet
+ * @diff: the difference between the PSN and the expected PSN
+ * @header_in_data: true if part of the header data is in the data buffer
+ *
+ * This is called from ipath_rc_rcv() to process an unexpected
+ * incoming RC packet for the given QP.
+ * Called at interrupt level.
+ * Return 1 if no more processing is needed; otherwise return 0 to
+ * schedule a response to be sent and the s_lock unlocked.
+ */
+static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
+ struct ipath_other_headers *ohdr,
+ void *data,
+ struct ipath_qp *qp,
+ u32 opcode,
+ u32 psn,
+ int diff,
+ int header_in_data)
+{
+ struct ib_reth *reth;
+
+ if (diff > 0) {
+ /*
+ * Packet sequence error.
+ * A NAK will ACK earlier sends and RDMA writes.
+ * Don't queue the NAK if a RDMA read, atomic, or
+ * NAK is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if ((qp->s_ack_state >= OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) ||
+ qp->s_nak_state != 0) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_ack_state = OP(SEND_ONLY);
+ qp->s_nak_state = IB_NAK_PSN_ERROR;
+ /* Use the expected PSN. */
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+ }
+
+ /*
+ * Handle a duplicate request. Don't re-execute SEND, RDMA
+ * write or atomic op. Don't NAK errors, just silently drop
+ * the duplicate request. Note that r_sge, r_len, and
+ * r_rcv_len may be in use so don't modify them.
+ *
+ * We are supposed to ACK the earliest duplicate PSN but we
+ * can coalesce an outstanding duplicate ACK. We have to
+ * send the earliest so that RDMA reads can be restarted at
+ * the requester's expected PSN.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE &&
+ ipath_cmp24(psn, qp->s_ack_psn) >= 0) {
+ if (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST)
+ qp->s_ack_psn = psn;
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ switch (opcode) {
+ case OP(RDMA_READ_REQUEST):
+ /*
+ * We have to be careful to not change s_rdma_sge
+ * while ipath_do_rc_send() is using it and not
+ * holding the s_lock.
+ */
+ if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+ qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) {
+ spin_unlock(&qp->s_lock);
+ dev->n_rdma_dup_busy++;
+ goto done;
+ }
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ qp->s_rdma_len = be32_to_cpu(reth->length);
+ if (qp->s_rdma_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+ int ok;
+
+ /*
+ * Address range must be a subset of the original
+ * request and start on pmtu boundaries.
+ */
+ ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+ qp->s_rdma_len, vaddr, rkey,
+ IB_ACCESS_REMOTE_READ);
+ if (unlikely(!ok))
+ goto done;
+ } else {
+ qp->s_rdma_sge.sg_list = NULL;
+ qp->s_rdma_sge.num_sge = 0;
+ qp->s_rdma_sge.sge.mr = NULL;
+ qp->s_rdma_sge.sge.vaddr = NULL;
+ qp->s_rdma_sge.sge.length = 0;
+ qp->s_rdma_sge.sge.sge_length = 0;
+ }
+ break;
+
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ /*
+ * Check for the PSN of the last atomic operations
+ * performed and resend the result if found.
+ */
+ if ((psn & IPS_PSN_MASK) != qp->r_atomic_psn) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_ack_atomic = qp->r_atomic_data;
+ break;
+ }
+ qp->s_ack_state = opcode;
+ qp->s_nak_state = 0;
+ qp->s_ack_psn = psn;
+resched:
+ return 0;
+
+done:
+ return 1;
+}
+
+/**
+ * ipath_rc_rcv - process an incoming RC packet
+ * @dev: the device this packet came in on
+ * @hdr: the header of this packet
+ * @has_grh: true if the header has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP for this packet
+ *
+ * This is called from ipath_qp_rcv() to process an incoming RC packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+ struct ipath_other_headers *ohdr;
+ u32 opcode;
+ u32 hdrsize;
+ u32 psn;
+ u32 pad;
+ unsigned long flags;
+ struct ib_wc wc;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ int diff;
+ struct ib_reth *reth;
+ int header_in_data;
+
+ /* Check for GRH */
+ if (!has_grh) {
+ ohdr = &hdr->u.oth;
+ hdrsize = 8 + 12; /* LRH + BTH */
+ psn = be32_to_cpu(ohdr->bth[2]);
+ header_in_data = 0;
+ } else {
+ ohdr = &hdr->u.l.oth;
+ hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */
+ /*
+ * The header with GRH is 60 bytes and the core driver sets
+ * the eager header buffer size to 56 bytes so the last 4
+ * bytes of the BTH header (PSN) is in the data buffer.
+ */
+ header_in_data =
+ ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+ if (header_in_data) {
+ psn = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ } else
+ psn = be32_to_cpu(ohdr->bth[2]);
+ }
+ /*
+ * The opcode is in the low byte when its in network order
+ * (top byte when in host order).
+ */
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+
+ /*
+ * Process responses (ACKs) before anything else. Note that the
+ * packet sequence number will be for something in the send work
+ * queue rather than the expected receive packet sequence number.
+ * In other words, this QP is the requester.
+ */
+ if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
+ opcode <= OP(ATOMIC_ACKNOWLEDGE)) {
+ ipath_rc_rcv_resp(dev, ohdr, data, tlen, qp, opcode, psn,
+ hdrsize, pmtu, header_in_data);
+ goto bail;
+ }
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+
+ /* Compute 24 bits worth of difference. */
+ diff = ipath_cmp24(psn, qp->r_psn);
+ if (unlikely(diff)) {
+ if (ipath_rc_rcv_error(dev, ohdr, data, qp, opcode,
+ psn, diff, header_in_data))
+ goto done;
+ goto resched;
+ }
+
+ /* Check for opcode sequence errors. */
+ switch (qp->r_state) {
+ case OP(SEND_FIRST):
+ case OP(SEND_MIDDLE):
+ if (opcode == OP(SEND_MIDDLE) ||
+ opcode == OP(SEND_LAST) ||
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+ break;
+ nack_inv:
+ /*
+ * A NAK will ACK earlier sends and RDMA writes. Don't queue the
+ * NAK if a RDMA read, atomic, or NAK is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state >= OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ /* XXX Flush WQEs */
+ qp->state = IB_QPS_ERR;
+ qp->s_ack_state = OP(SEND_ONLY);
+ qp->s_nak_state = IB_NAK_INVALID_REQUEST;
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_MIDDLE):
+ if (opcode == OP(RDMA_WRITE_MIDDLE) ||
+ opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+ break;
+ goto nack_inv;
+
+ case OP(RDMA_READ_REQUEST):
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ /*
+ * Drop all new requests until a response has been sent. A
+ * new request then ACKs the RDMA response we sent. Relaxed
+ * ordering would allow new requests to be processed but we
+ * would need to keep a queue of rwqe's for all that are in
+ * progress. Note that we can't RNR NAK this request since
+ * the RDMA READ or atomic response is already queued to be
+ * sent (unless we implement a response send queue).
+ */
+ goto done;
+
+ default:
+ if (opcode == OP(SEND_MIDDLE) ||
+ opcode == OP(SEND_LAST) ||
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE) ||
+ opcode == OP(RDMA_WRITE_MIDDLE) ||
+ opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+ goto nack_inv;
+ break;
+ }
+
+ wc.imm_data = 0;
+ wc.wc_flags = 0;
+
+ /* OK, process the packet. */
+ switch (opcode) {
+ case OP(SEND_FIRST):
+ if (!ipath_get_rwqe(qp, 0)) {
+ rnr_nak:
+ /*
+ * A RNR NAK will ACK earlier sends and RDMA writes.
+ * Don't queue the NAK if a RDMA read or atomic
+ * is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state >=
+ OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_ack_state = OP(SEND_ONLY);
+ qp->s_nak_state = IB_RNR_NAK | qp->s_min_rnr_timer;
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+ }
+ qp->r_rcv_len = 0;
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ case OP(RDMA_WRITE_MIDDLE):
+ send_middle:
+ /* Check for invalid length PMTU or posted rwqe len. */
+ if (unlikely(tlen != (hdrsize + pmtu + 4)))
+ goto nack_inv;
+ qp->r_rcv_len += pmtu;
+ if (unlikely(qp->r_rcv_len > qp->r_len))
+ goto nack_inv;
+ ipath_copy_sge(&qp->r_sge, data, pmtu);
+ break;
+
+ case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
+ /* consume RWQE */
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ goto send_last_imm;
+
+ case OP(SEND_ONLY):
+ case OP(SEND_ONLY_WITH_IMMEDIATE):
+ if (!ipath_get_rwqe(qp, 0))
+ goto rnr_nak;
+ qp->r_rcv_len = 0;
+ if (opcode == OP(SEND_ONLY))
+ goto send_last;
+ /* FALLTHROUGH */
+ case OP(SEND_LAST_WITH_IMMEDIATE):
+ send_last_imm:
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else {
+ /* Immediate data comes after BTH */
+ wc.imm_data = ohdr->u.imm_data;
+ }
+ hdrsize += 4;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ /* FALLTHROUGH */
+ case OP(SEND_LAST):
+ case OP(RDMA_WRITE_LAST):
+ send_last:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4)))
+ goto nack_inv;
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ wc.byte_len = tlen + qp->r_rcv_len;
+ if (unlikely(wc.byte_len > qp->r_len))
+ goto nack_inv;
+ ipath_copy_sge(&qp->r_sge, data, tlen);
+ atomic_inc(&qp->msn);
+ if (opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_ONLY))
+ break;
+ wc.wr_id = qp->r_wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = IB_WC_RECV;
+ wc.vendor_err = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+ (ohdr->bth[0] &
+ __constant_cpu_to_be32(1 << 23)) != 0);
+ break;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_ONLY):
+ case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+ /* consume RWQE */
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ hdrsize += sizeof(*reth);
+ qp->r_len = be32_to_cpu(reth->length);
+ qp->r_rcv_len = 0;
+ if (qp->r_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+ int ok;
+
+ /* Check rkey & NAK */
+ ok = ipath_rkey_ok(dev, &qp->r_sge,
+ qp->r_len, vaddr, rkey,
+ IB_ACCESS_REMOTE_WRITE);
+ if (unlikely(!ok)) {
+ nack_acc:
+ /*
+ * A NAK will ACK earlier sends and RDMA
+ * writes. Don't queue the NAK if a RDMA
+ * read, atomic, or NAK is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state >=
+ OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state !=
+ IB_OPCODE_ACKNOWLEDGE) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ /* XXX Flush WQEs */
+ qp->state = IB_QPS_ERR;
+ qp->s_ack_state = OP(RDMA_WRITE_ONLY);
+ qp->s_nak_state =
+ IB_NAK_REMOTE_ACCESS_ERROR;
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+ }
+ } else {
+ qp->r_sge.sg_list = NULL;
+ qp->r_sge.sge.mr = NULL;
+ qp->r_sge.sge.vaddr = NULL;
+ 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))
+ goto send_last;
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ goto send_last_imm;
+
+ case OP(RDMA_READ_REQUEST):
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+ qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_rdma_len = be32_to_cpu(reth->length);
+ if (qp->s_rdma_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+ int ok;
+
+ /* Check rkey & NAK */
+ ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+ qp->s_rdma_len, vaddr, rkey,
+ IB_ACCESS_REMOTE_READ);
+ if (unlikely(!ok)) {
+ spin_unlock(&qp->s_lock);
+ goto nack_acc;
+ }
+ /*
+ * Update the next expected PSN. We add 1 later
+ * below, so only add the remainder here.
+ */
+ if (qp->s_rdma_len > pmtu)
+ qp->r_psn += (qp->s_rdma_len - 1) / pmtu;
+ } else {
+ qp->s_rdma_sge.sg_list = NULL;
+ qp->s_rdma_sge.num_sge = 0;
+ qp->s_rdma_sge.sge.mr = NULL;
+ qp->s_rdma_sge.sge.vaddr = NULL;
+ qp->s_rdma_sge.sge.length = 0;
+ qp->s_rdma_sge.sge.sge_length = 0;
+ }
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_READ)))
+ goto nack_acc;
+ /*
+ * We need to increment the MSN here instead of when we
+ * finish sending the result since a duplicate request would
+ * increment it more than once.
+ */
+ atomic_inc(&qp->msn);
+ qp->s_ack_state = opcode;
+ qp->s_nak_state = 0;
+ qp->s_ack_psn = psn;
+ qp->r_psn++;
+ qp->r_state = opcode;
+ goto rdmadone;
+
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD): {
+ struct ib_atomic_eth *ateth;
+ u64 vaddr;
+ u64 sdata;
+ u32 rkey;
+
+ if (!header_in_data)
+ ateth = &ohdr->u.atomic_eth;
+ else {
+ ateth = (struct ib_atomic_eth *)data;
+ data += sizeof(*ateth);
+ }
+ vaddr = be64_to_cpu(ateth->vaddr);
+ if (unlikely(vaddr & (sizeof(u64) - 1)))
+ goto nack_inv;
+ rkey = be32_to_cpu(ateth->rkey);
+ /* Check rkey & NAK */
+ if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge,
+ sizeof(u64), vaddr, rkey,
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto nack_acc;
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto nack_acc;
+ /* Perform atomic OP and save result. */
+ sdata = be64_to_cpu(ateth->swap_data);
+ spin_lock(&dev->pending_lock);
+ qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
+ if (opcode == OP(FETCH_ADD))
+ *(u64 *) qp->r_sge.sge.vaddr =
+ qp->r_atomic_data + sdata;
+ else if (qp->r_atomic_data ==
+ be64_to_cpu(ateth->compare_data))
+ *(u64 *) qp->r_sge.sge.vaddr = sdata;
+ spin_unlock(&dev->pending_lock);
+ atomic_inc(&qp->msn);
+ qp->r_atomic_psn = psn & IPS_PSN_MASK;
+ psn |= 1 << 31;
+ break;
+ }
+
+ default:
+ /* Drop packet for unknown opcodes. */
+ goto done;
+ }
+ qp->r_psn++;
+ qp->r_state = opcode;
+ /* Send an ACK if requested or required. */
+ if (psn & (1 << 31)) {
+ /*
+ * Coalesce ACKs unless there is a RDMA READ or
+ * ATOMIC pending.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state == OP(ACKNOWLEDGE) ||
+ qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST) {
+ qp->s_ack_state = opcode;
+ qp->s_nak_state = 0;
+ qp->s_ack_psn = psn;
+ qp->s_ack_atomic = qp->r_atomic_data;
+ goto resched;
+ }
+ spin_unlock(&qp->s_lock);
+ }
+done:
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ goto bail;
+
+resched:
+ /*
+ * Try to send ACK right away but not if ipath_do_rc_send() is
+ * active.
+ */
+ if (qp->s_hdrwords == 0 &&
+ (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST ||
+ qp->s_ack_state >= IB_OPCODE_COMPARE_SWAP))
+ send_rc_ack(qp);
+
+rdmadone:
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+ /* Call ipath_do_rc_send() in another thread. */
+ tasklet_hi_schedule(&qp->s_task);
+
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
new file mode 100644
index 000000000000..1e59750c5f63
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_REGISTERS_H
+#define _IPATH_REGISTERS_H
+
+/*
+ * This file should only be included by kernel source, and by the diags.
+ * It defines the registers, and their contents, for the InfiniPath HT-400 chip
+ */
+
+/*
+ * These are the InfiniPath register and buffer bit definitions,
+ * that are visible to software, and needed only by the kernel
+ * and diag code. A few, that are visible to protocol and user
+ * code are in ipath_common.h. Some bits are specific
+ * to a given chip implementation, and have been moved to the
+ * chip-specific source file
+ */
+
+/* kr_revision bits */
+#define INFINIPATH_R_CHIPREVMINOR_MASK 0xFF
+#define INFINIPATH_R_CHIPREVMINOR_SHIFT 0
+#define INFINIPATH_R_CHIPREVMAJOR_MASK 0xFF
+#define INFINIPATH_R_CHIPREVMAJOR_SHIFT 8
+#define INFINIPATH_R_ARCH_MASK 0xFF
+#define INFINIPATH_R_ARCH_SHIFT 16
+#define INFINIPATH_R_SOFTWARE_MASK 0xFF
+#define INFINIPATH_R_SOFTWARE_SHIFT 24
+#define INFINIPATH_R_BOARDID_MASK 0xFF
+#define INFINIPATH_R_BOARDID_SHIFT 32
+
+/* kr_control bits */
+#define INFINIPATH_C_FREEZEMODE 0x00000002
+#define INFINIPATH_C_LINKENABLE 0x00000004
+#define INFINIPATH_C_RESET 0x00000001
+
+/* kr_sendctrl bits */
+#define INFINIPATH_S_DISARMPIOBUF_SHIFT 16
+
+#define IPATH_S_ABORT 0
+#define IPATH_S_PIOINTBUFAVAIL 1
+#define IPATH_S_PIOBUFAVAILUPD 2
+#define IPATH_S_PIOENABLE 3
+#define IPATH_S_DISARM 31
+
+#define INFINIPATH_S_ABORT (1U << IPATH_S_ABORT)
+#define INFINIPATH_S_PIOINTBUFAVAIL (1U << IPATH_S_PIOINTBUFAVAIL)
+#define INFINIPATH_S_PIOBUFAVAILUPD (1U << IPATH_S_PIOBUFAVAILUPD)
+#define INFINIPATH_S_PIOENABLE (1U << IPATH_S_PIOENABLE)
+#define INFINIPATH_S_DISARM (1U << IPATH_S_DISARM)
+
+/* kr_rcvctrl bits */
+#define INFINIPATH_R_PORTENABLE_SHIFT 0
+#define INFINIPATH_R_INTRAVAIL_SHIFT 16
+#define INFINIPATH_R_TAILUPD 0x80000000
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_SHIFT 0
+#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+#define INFINIPATH_I_ERROR 0x80000000
+#define INFINIPATH_I_SPIOSENT 0x40000000
+#define INFINIPATH_I_SPIOBUFAVAIL 0x20000000
+#define INFINIPATH_I_GPIO 0x10000000
+
+/* kr_errorstatus, kr_errorclear, kr_errormask bits */
+#define INFINIPATH_E_RFORMATERR 0x0000000000000001ULL
+#define INFINIPATH_E_RVCRC 0x0000000000000002ULL
+#define INFINIPATH_E_RICRC 0x0000000000000004ULL
+#define INFINIPATH_E_RMINPKTLEN 0x0000000000000008ULL
+#define INFINIPATH_E_RMAXPKTLEN 0x0000000000000010ULL
+#define INFINIPATH_E_RLONGPKTLEN 0x0000000000000020ULL
+#define INFINIPATH_E_RSHORTPKTLEN 0x0000000000000040ULL
+#define INFINIPATH_E_RUNEXPCHAR 0x0000000000000080ULL
+#define INFINIPATH_E_RUNSUPVL 0x0000000000000100ULL
+#define INFINIPATH_E_REBP 0x0000000000000200ULL
+#define INFINIPATH_E_RIBFLOW 0x0000000000000400ULL
+#define INFINIPATH_E_RBADVERSION 0x0000000000000800ULL
+#define INFINIPATH_E_RRCVEGRFULL 0x0000000000001000ULL
+#define INFINIPATH_E_RRCVHDRFULL 0x0000000000002000ULL
+#define INFINIPATH_E_RBADTID 0x0000000000004000ULL
+#define INFINIPATH_E_RHDRLEN 0x0000000000008000ULL
+#define INFINIPATH_E_RHDR 0x0000000000010000ULL
+#define INFINIPATH_E_RIBLOSTLINK 0x0000000000020000ULL
+#define INFINIPATH_E_SMINPKTLEN 0x0000000020000000ULL
+#define INFINIPATH_E_SMAXPKTLEN 0x0000000040000000ULL
+#define INFINIPATH_E_SUNDERRUN 0x0000000080000000ULL
+#define INFINIPATH_E_SPKTLEN 0x0000000100000000ULL
+#define INFINIPATH_E_SDROPPEDSMPPKT 0x0000000200000000ULL
+#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL
+#define INFINIPATH_E_SPIOARMLAUNCH 0x0000000800000000ULL
+#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL
+#define INFINIPATH_E_SUNSUPVL 0x0000002000000000ULL
+#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL
+#define INFINIPATH_E_INVALIDADDR 0x0002000000000000ULL
+#define INFINIPATH_E_RESET 0x0004000000000000ULL
+#define INFINIPATH_E_HARDWARE 0x0008000000000000ULL
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+/* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo
+ * RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: eagerTID, 3: expTID
+ * bit 4: flag buffer, 5: datainfo, 6: header info */
+#define INFINIPATH_HWE_TXEMEMPARITYERR_MASK 0xFULL
+#define INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT 40
+#define INFINIPATH_HWE_RXEMEMPARITYERR_MASK 0x7FULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT 44
+#define INFINIPATH_HWE_RXDSYNCMEMPARITYERR 0x0000000400000000ULL
+#define INFINIPATH_HWE_MEMBISTFAILED 0x0040000000000000ULL
+#define INFINIPATH_HWE_IBCBUSTOSPCPARITYERR 0x4000000000000000ULL
+#define INFINIPATH_HWE_IBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+
+/* kr_hwdiagctrl bits */
+#define INFINIPATH_DC_FORCETXEMEMPARITYERR_MASK 0xFULL
+#define INFINIPATH_DC_FORCETXEMEMPARITYERR_SHIFT 40
+#define INFINIPATH_DC_FORCERXEMEMPARITYERR_MASK 0x7FULL
+#define INFINIPATH_DC_FORCERXEMEMPARITYERR_SHIFT 44
+#define INFINIPATH_DC_FORCERXDSYNCMEMPARITYERR 0x0000000400000000ULL
+#define INFINIPATH_DC_COUNTERDISABLE 0x1000000000000000ULL
+#define INFINIPATH_DC_COUNTERWREN 0x2000000000000000ULL
+#define INFINIPATH_DC_FORCEIBCBUSTOSPCPARITYERR 0x4000000000000000ULL
+#define INFINIPATH_DC_FORCEIBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+
+/* kr_ibcctrl bits */
+#define INFINIPATH_IBCC_FLOWCTRLPERIOD_MASK 0xFFULL
+#define INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT 0
+#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_MASK 0xFFULL
+#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8
+#define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL
+#define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1
+#define INFINIPATH_IBCC_LINKINITCMD_POLL 2 /* cycle through TS1/TS2 till OK */
+#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 /* wait for TS1, then go on */
+#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
+#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
+#define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */
+#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */
+#define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */
+#define INFINIPATH_IBCC_LINKCMD_SHIFT 18
+#define INFINIPATH_IBCC_MAXPKTLEN_MASK 0x7FFULL
+#define INFINIPATH_IBCC_MAXPKTLEN_SHIFT 20
+#define INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK 0xFULL
+#define INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT 32
+#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK 0xFULL
+#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT 36
+#define INFINIPATH_IBCC_CREDITSCALE_MASK 0x7ULL
+#define INFINIPATH_IBCC_CREDITSCALE_SHIFT 40
+#define INFINIPATH_IBCC_LOOPBACK 0x8000000000000000ULL
+#define INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE 0x4000000000000000ULL
+
+/* kr_ibcstatus bits */
+#define INFINIPATH_IBCS_LINKTRAININGSTATE_MASK 0xF
+#define INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT 0
+#define INFINIPATH_IBCS_LINKSTATE_MASK 0x7
+#define INFINIPATH_IBCS_LINKSTATE_SHIFT 4
+#define INFINIPATH_IBCS_TXREADY 0x40000000
+#define INFINIPATH_IBCS_TXCREDITOK 0x80000000
+/* link training states (shift by INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */
+#define INFINIPATH_IBCS_LT_STATE_DISABLED 0x00
+#define INFINIPATH_IBCS_LT_STATE_LINKUP 0x01
+#define INFINIPATH_IBCS_LT_STATE_POLLACTIVE 0x02
+#define INFINIPATH_IBCS_LT_STATE_POLLQUIET 0x03
+#define INFINIPATH_IBCS_LT_STATE_SLEEPDELAY 0x04
+#define INFINIPATH_IBCS_LT_STATE_SLEEPQUIET 0x05
+#define INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE 0x08
+#define INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG 0x09
+#define INFINIPATH_IBCS_LT_STATE_CFGWAITRMT 0x0a
+#define INFINIPATH_IBCS_LT_STATE_CFGIDLE 0x0b
+#define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN 0x0c
+#define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT 0x0e
+#define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE 0x0f
+/* link state machine states (shift by INFINIPATH_IBCS_LINKSTATE_SHIFT) */
+#define INFINIPATH_IBCS_L_STATE_DOWN 0x0
+#define INFINIPATH_IBCS_L_STATE_INIT 0x1
+#define INFINIPATH_IBCS_L_STATE_ARM 0x2
+#define INFINIPATH_IBCS_L_STATE_ACTIVE 0x3
+#define INFINIPATH_IBCS_L_STATE_ACT_DEFER 0x4
+
+/* combination link status states that we use with some frequency */
+#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LINKSTATE_MASK \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LT_STATE_LINKUP \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LT_STATE_LINKUP \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LT_STATE_LINKUP \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
+#define INFINIPATH_EXTS_GPIOIN_MASK 0xFFFFULL
+#define INFINIPATH_EXTS_GPIOIN_SHIFT 48
+
+/* kr_extctrl bits */
+#define INFINIPATH_EXTC_GPIOINVERT_MASK 0xFFFFULL
+#define INFINIPATH_EXTC_GPIOINVERT_SHIFT 32
+#define INFINIPATH_EXTC_GPIOOE_MASK 0xFFFFULL
+#define INFINIPATH_EXTC_GPIOOE_SHIFT 48
+#define INFINIPATH_EXTC_SERDESENABLE 0x80000000ULL
+#define INFINIPATH_EXTC_SERDESCONNECT 0x40000000ULL
+#define INFINIPATH_EXTC_SERDESENTRUNKING 0x20000000ULL
+#define INFINIPATH_EXTC_SERDESDISRXFIFO 0x10000000ULL
+#define INFINIPATH_EXTC_SERDESENPLPBK1 0x08000000ULL
+#define INFINIPATH_EXTC_SERDESENPLPBK2 0x04000000ULL
+#define INFINIPATH_EXTC_SERDESENENCDEC 0x02000000ULL
+#define INFINIPATH_EXTC_LED1SECPORT_ON 0x00000020ULL
+#define INFINIPATH_EXTC_LED2SECPORT_ON 0x00000010ULL
+#define INFINIPATH_EXTC_LED1PRIPORT_ON 0x00000008ULL
+#define INFINIPATH_EXTC_LED2PRIPORT_ON 0x00000004ULL
+#define INFINIPATH_EXTC_LEDGBLOK_ON 0x00000002ULL
+#define INFINIPATH_EXTC_LEDGBLERR_OFF 0x00000001ULL
+
+/* kr_mdio bits */
+#define INFINIPATH_MDIO_CLKDIV_MASK 0x7FULL
+#define INFINIPATH_MDIO_CLKDIV_SHIFT 32
+#define INFINIPATH_MDIO_COMMAND_MASK 0x7ULL
+#define INFINIPATH_MDIO_COMMAND_SHIFT 26
+#define INFINIPATH_MDIO_DEVADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_DEVADDR_SHIFT 21
+#define INFINIPATH_MDIO_REGADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_REGADDR_SHIFT 16
+#define INFINIPATH_MDIO_DATA_MASK 0xFFFFULL
+#define INFINIPATH_MDIO_DATA_SHIFT 0
+#define INFINIPATH_MDIO_CMDVALID 0x0000000040000000ULL
+#define INFINIPATH_MDIO_RDDATAVALID 0x0000000080000000ULL
+
+/* kr_partitionkey bits */
+#define INFINIPATH_PKEY_SIZE 16
+#define INFINIPATH_PKEY_MASK 0xFFFF
+#define INFINIPATH_PKEY_DEFAULT_PKEY 0xFFFF
+
+/* kr_serdesconfig0 bits */
+#define INFINIPATH_SERDC0_RESET_MASK 0xfULL /* overal reset bits */
+#define INFINIPATH_SERDC0_RESET_PLL 0x10000000ULL /* pll reset */
+#define INFINIPATH_SERDC0_TXIDLE 0xF000ULL /* tx idle enables (per lane) */
+#define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL /* rx detect enables (per lane) */
+#define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL /* L1 Power down; use with RXDETECT,
+ Otherwise not used on IB side */
+
+/* kr_xgxsconfig bits */
+#define INFINIPATH_XGXS_RESET 0x7ULL
+#define INFINIPATH_XGXS_MDIOADDR_MASK 0xfULL
+#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
+
+#define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */
+
+/* TID entries (memory), HT400-only */
+#define INFINIPATH_RT_VALID 0x8000000000000000ULL
+#define INFINIPATH_RT_ADDR_SHIFT 0
+#define INFINIPATH_RT_BUFSIZE_MASK 0x3FFF
+#define INFINIPATH_RT_BUFSIZE_SHIFT 48
+
+/*
+ * IPATH_PIO_MAXIBHDR is the max IB header size allowed for in our
+ * PIO send buffers. This is well beyond anything currently
+ * defined in the InfiniBand spec.
+ */
+#define IPATH_PIO_MAXIBHDR 128
+
+typedef u64 ipath_err_t;
+
+/* mask of defined bits for various registers */
+extern u64 infinipath_i_bitsextant;
+extern ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
+
+/* masks that are different in various chips, or only exist in some chips */
+extern u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
+
+/*
+ * register bits for selecting i2c direction and values, used for I2C serial
+ * flash
+ */
+extern u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
+extern u64 ipath_gpio_sda, ipath_gpio_scl;
+
+/*
+ * These are the infinipath general register numbers (not offsets).
+ * The kernel registers are used directly, those beyond the kernel
+ * registers are calculated from one of the base registers. The use of
+ * an integer type doesn't allow type-checking as thorough as, say,
+ * an enum but allows for better hiding of chip differences.
+ */
+typedef const u16 ipath_kreg, /* infinipath general registers */
+ ipath_creg, /* infinipath counter registers */
+ ipath_sreg; /* kernel-only, infinipath send registers */
+
+/*
+ * These are the chip registers common to all infinipath chips, and
+ * used both by the kernel and the diagnostics or other user code.
+ * They are all implemented such that 64 bit accesses work.
+ * Some implement no more than 32 bits. Because 64 bit reads
+ * require 2 HT cmds on opteron, we access those with 32 bit
+ * reads for efficiency (they are written as 64 bits, since
+ * the extra 32 bits are nearly free on writes, and it slightly reduces
+ * complexity). The rest are all accessed as 64 bits.
+ */
+struct ipath_kregs {
+ /* These are the 32 bit group */
+ ipath_kreg kr_control;
+ ipath_kreg kr_counterregbase;
+ ipath_kreg kr_intmask;
+ ipath_kreg kr_intstatus;
+ ipath_kreg kr_pagealign;
+ ipath_kreg kr_portcnt;
+ ipath_kreg kr_rcvtidbase;
+ ipath_kreg kr_rcvtidcnt;
+ ipath_kreg kr_rcvegrbase;
+ ipath_kreg kr_rcvegrcnt;
+ ipath_kreg kr_scratch;
+ ipath_kreg kr_sendctrl;
+ ipath_kreg kr_sendpiobufbase;
+ ipath_kreg kr_sendpiobufcnt;
+ ipath_kreg kr_sendpiosize;
+ ipath_kreg kr_sendregbase;
+ ipath_kreg kr_userregbase;
+ /* These are the 64 bit group */
+ ipath_kreg kr_debugport;
+ ipath_kreg kr_debugportselect;
+ ipath_kreg kr_errorclear;
+ ipath_kreg kr_errormask;
+ ipath_kreg kr_errorstatus;
+ ipath_kreg kr_extctrl;
+ ipath_kreg kr_extstatus;
+ ipath_kreg kr_gpio_clear;
+ ipath_kreg kr_gpio_mask;
+ ipath_kreg kr_gpio_out;
+ ipath_kreg kr_gpio_status;
+ ipath_kreg kr_hwdiagctrl;
+ ipath_kreg kr_hwerrclear;
+ ipath_kreg kr_hwerrmask;
+ ipath_kreg kr_hwerrstatus;
+ ipath_kreg kr_ibcctrl;
+ ipath_kreg kr_ibcstatus;
+ ipath_kreg kr_intblocked;
+ ipath_kreg kr_intclear;
+ ipath_kreg kr_interruptconfig;
+ ipath_kreg kr_mdio;
+ ipath_kreg kr_partitionkey;
+ ipath_kreg kr_rcvbthqp;
+ ipath_kreg kr_rcvbufbase;
+ ipath_kreg kr_rcvbufsize;
+ ipath_kreg kr_rcvctrl;
+ ipath_kreg kr_rcvhdrcnt;
+ ipath_kreg kr_rcvhdrentsize;
+ ipath_kreg kr_rcvhdrsize;
+ ipath_kreg kr_rcvintmembase;
+ ipath_kreg kr_rcvintmemsize;
+ ipath_kreg kr_revision;
+ ipath_kreg kr_sendbuffererror;
+ ipath_kreg kr_sendpioavailaddr;
+ ipath_kreg kr_serdesconfig0;
+ ipath_kreg kr_serdesconfig1;
+ ipath_kreg kr_serdesstatus;
+ ipath_kreg kr_txintmembase;
+ ipath_kreg kr_txintmemsize;
+ ipath_kreg kr_xgxsconfig;
+ ipath_kreg kr_ibpllcfg;
+ /* use these two (and the following N ports) only with ipath_k*_kreg64_port();
+ * not *kreg64() */
+ ipath_kreg kr_rcvhdraddr;
+ ipath_kreg kr_rcvhdrtailaddr;
+
+ /* remaining registers are not present on all types of infinipath chips */
+ ipath_kreg kr_rcvpktledcnt;
+ ipath_kreg kr_pcierbuftestreg0;
+ ipath_kreg kr_pcierbuftestreg1;
+ ipath_kreg kr_pcieq0serdesconfig0;
+ ipath_kreg kr_pcieq0serdesconfig1;
+ ipath_kreg kr_pcieq0serdesstatus;
+ ipath_kreg kr_pcieq1serdesconfig0;
+ ipath_kreg kr_pcieq1serdesconfig1;
+ ipath_kreg kr_pcieq1serdesstatus;
+};
+
+struct ipath_cregs {
+ ipath_creg cr_badformatcnt;
+ ipath_creg cr_erricrccnt;
+ ipath_creg cr_errlinkcnt;
+ ipath_creg cr_errlpcrccnt;
+ ipath_creg cr_errpkey;
+ ipath_creg cr_errrcvflowctrlcnt;
+ ipath_creg cr_err_rlencnt;
+ ipath_creg cr_errslencnt;
+ ipath_creg cr_errtidfull;
+ ipath_creg cr_errtidvalid;
+ ipath_creg cr_errvcrccnt;
+ ipath_creg cr_ibstatuschange;
+ ipath_creg cr_intcnt;
+ ipath_creg cr_invalidrlencnt;
+ ipath_creg cr_invalidslencnt;
+ ipath_creg cr_lbflowstallcnt;
+ ipath_creg cr_iblinkdowncnt;
+ ipath_creg cr_iblinkerrrecovcnt;
+ ipath_creg cr_ibsymbolerrcnt;
+ ipath_creg cr_pktrcvcnt;
+ ipath_creg cr_pktrcvflowctrlcnt;
+ ipath_creg cr_pktsendcnt;
+ ipath_creg cr_pktsendflowcnt;
+ ipath_creg cr_portovflcnt;
+ ipath_creg cr_rcvebpcnt;
+ ipath_creg cr_rcvovflcnt;
+ ipath_creg cr_rxdroppktcnt;
+ ipath_creg cr_senddropped;
+ ipath_creg cr_sendstallcnt;
+ ipath_creg cr_sendunderruncnt;
+ ipath_creg cr_unsupvlcnt;
+ ipath_creg cr_wordrcvcnt;
+ ipath_creg cr_wordsendcnt;
+};
+
+#endif /* _IPATH_REGISTERS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
new file mode 100644
index 000000000000..f232e77b78ee
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+
+/*
+ * Convert the AETH RNR timeout code into the number of milliseconds.
+ */
+const u32 ib_ipath_rnr_table[32] = {
+ 656, /* 0 */
+ 1, /* 1 */
+ 1, /* 2 */
+ 1, /* 3 */
+ 1, /* 4 */
+ 1, /* 5 */
+ 1, /* 6 */
+ 1, /* 7 */
+ 1, /* 8 */
+ 1, /* 9 */
+ 1, /* A */
+ 1, /* B */
+ 1, /* C */
+ 1, /* D */
+ 2, /* E */
+ 2, /* F */
+ 3, /* 10 */
+ 4, /* 11 */
+ 6, /* 12 */
+ 8, /* 13 */
+ 11, /* 14 */
+ 16, /* 15 */
+ 21, /* 16 */
+ 31, /* 17 */
+ 41, /* 18 */
+ 62, /* 19 */
+ 82, /* 1A */
+ 123, /* 1B */
+ 164, /* 1C */
+ 246, /* 1D */
+ 328, /* 1E */
+ 492 /* 1F */
+};
+
+/**
+ * ipath_insert_rnr_queue - put QP on the RNR timeout list for the device
+ * @qp: the QP
+ *
+ * XXX Use a simple list for now. We might need a priority
+ * queue if we have lots of QPs waiting for RNR timeouts
+ * but that should be rare.
+ */
+void ipath_insert_rnr_queue(struct ipath_qp *qp)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (list_empty(&dev->rnrwait))
+ list_add(&qp->timerwait, &dev->rnrwait);
+ else {
+ struct list_head *l = &dev->rnrwait;
+ struct ipath_qp *nqp = list_entry(l->next, struct ipath_qp,
+ timerwait);
+
+ while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
+ qp->s_rnr_timeout -= nqp->s_rnr_timeout;
+ l = l->next;
+ if (l->next == &dev->rnrwait)
+ break;
+ nqp = list_entry(l->next, struct ipath_qp,
+ timerwait);
+ }
+ list_add(&qp->timerwait, l);
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+}
+
+/**
+ * ipath_get_rwqe - copy the next RWQE into the QP's RWQE
+ * @qp: the QP
+ * @wr_id_only: update wr_id only, not SGEs
+ *
+ * Return 0 if no RWQE is available, otherwise return 1.
+ *
+ * Called at interrupt level with the QP r_rq.lock held.
+ */
+int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
+{
+ struct ipath_rq *rq;
+ struct ipath_srq *srq;
+ struct ipath_rwqe *wqe;
+ int ret;
+
+ if (!qp->ibqp.srq) {
+ rq = &qp->r_rq;
+ if (unlikely(rq->tail == rq->head)) {
+ ret = 0;
+ goto bail;
+ }
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ qp->r_wr_id = wqe->wr_id;
+ if (!wr_id_only) {
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->num_sge;
+ qp->r_len = wqe->length;
+ }
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ ret = 1;
+ goto bail;
+ }
+
+ srq = to_isrq(qp->ibqp.srq);
+ rq = &srq->rq;
+ spin_lock(&rq->lock);
+ if (unlikely(rq->tail == rq->head)) {
+ spin_unlock(&rq->lock);
+ ret = 0;
+ goto bail;
+ }
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ qp->r_wr_id = wqe->wr_id;
+ if (!wr_id_only) {
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->num_sge;
+ qp->r_len = wqe->length;
+ }
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ if (srq->ibsrq.event_handler) {
+ struct ib_event ev;
+ u32 n;
+
+ if (rq->head < rq->tail)
+ n = rq->size + rq->head - rq->tail;
+ else
+ n = rq->head - rq->tail;
+ if (n < srq->limit) {
+ srq->limit = 0;
+ spin_unlock(&rq->lock);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev,
+ srq->ibsrq.srq_context);
+ } else
+ spin_unlock(&rq->lock);
+ } else
+ spin_unlock(&rq->lock);
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_ruc_loopback - handle UC and RC lookback requests
+ * @sqp: the loopback QP
+ * @wc: the work completion entry
+ *
+ * This is called from ipath_do_uc_send() or ipath_do_rc_send() to
+ * forward a WQE addressed to the same HCA.
+ * Note that although we are single threaded due to the tasklet, we still
+ * have to protect against post_send(). We don't have to worry about
+ * receive interrupts since this is a connected protocol and all packets
+ * will pass through here.
+ */
+void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc)
+{
+ struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
+ struct ipath_qp *qp;
+ struct ipath_swqe *wqe;
+ struct ipath_sge *sge;
+ unsigned long flags;
+ u64 sdata;
+
+ qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn);
+ if (!qp) {
+ dev->n_pkt_drops++;
+ return;
+ }
+
+again:
+ spin_lock_irqsave(&sqp->s_lock, flags);
+
+ if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK)) {
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+ goto done;
+ }
+
+ /* Get the next send request. */
+ if (sqp->s_last == sqp->s_head) {
+ /* Send work queue is empty. */
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+ goto done;
+ }
+
+ /*
+ * We can rely on the entry not changing without the s_lock
+ * being held until we update s_last.
+ */
+ wqe = get_swqe_ptr(sqp, sqp->s_last);
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+
+ wc->wc_flags = 0;
+ wc->imm_data = 0;
+
+ sqp->s_sge.sge = wqe->sg_list[0];
+ sqp->s_sge.sg_list = wqe->sg_list + 1;
+ sqp->s_sge.num_sge = wqe->wr.num_sge;
+ sqp->s_len = wqe->length;
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->imm_data = wqe->wr.imm_data;
+ /* FALLTHROUGH */
+ case IB_WR_SEND:
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ if (!ipath_get_rwqe(qp, 0)) {
+ rnr_nak:
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ /* Handle RNR NAK */
+ if (qp->ibqp.qp_type == IB_QPT_UC)
+ goto send_comp;
+ if (sqp->s_rnr_retry == 0) {
+ wc->status = IB_WC_RNR_RETRY_EXC_ERR;
+ goto err;
+ }
+ if (sqp->s_rnr_retry_cnt < 7)
+ sqp->s_rnr_retry--;
+ dev->n_rnr_naks++;
+ sqp->s_rnr_timeout =
+ ib_ipath_rnr_table[sqp->s_min_rnr_timer];
+ ipath_insert_rnr_queue(sqp);
+ goto done;
+ }
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ break;
+
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->imm_data = wqe->wr.imm_data;
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ /* FALLTHROUGH */
+ case IB_WR_RDMA_WRITE:
+ if (wqe->length == 0)
+ break;
+ if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, wqe->length,
+ wqe->wr.wr.rdma.remote_addr,
+ wqe->wr.wr.rdma.rkey,
+ IB_ACCESS_REMOTE_WRITE))) {
+ acc_err:
+ wc->status = IB_WC_REM_ACCESS_ERR;
+ err:
+ wc->wr_id = wqe->wr.wr_id;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = 0;
+ wc->qp_num = sqp->ibqp.qp_num;
+ wc->src_qp = sqp->remote_qpn;
+ wc->pkey_index = 0;
+ wc->slid = sqp->remote_ah_attr.dlid;
+ wc->sl = sqp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_sqerror_qp(sqp, wc);
+ goto done;
+ }
+ break;
+
+ case IB_WR_RDMA_READ:
+ if (unlikely(!ipath_rkey_ok(dev, &sqp->s_sge, wqe->length,
+ wqe->wr.wr.rdma.remote_addr,
+ wqe->wr.wr.rdma.rkey,
+ IB_ACCESS_REMOTE_READ)))
+ goto acc_err;
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_READ)))
+ goto acc_err;
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->wr.num_sge;
+ break;
+
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, sizeof(u64),
+ wqe->wr.wr.rdma.remote_addr,
+ wqe->wr.wr.rdma.rkey,
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto acc_err;
+ /* Perform atomic OP and save result. */
+ sdata = wqe->wr.wr.atomic.swap;
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
+ if (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+ *(u64 *) qp->r_sge.sge.vaddr =
+ qp->r_atomic_data + sdata;
+ else if (qp->r_atomic_data == wqe->wr.wr.atomic.compare_add)
+ *(u64 *) qp->r_sge.sge.vaddr = sdata;
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+ *(u64 *) sqp->s_sge.sge.vaddr = qp->r_atomic_data;
+ goto send_comp;
+
+ default:
+ goto done;
+ }
+
+ sge = &sqp->s_sge.sge;
+ while (sqp->s_len) {
+ u32 len = sqp->s_len;
+
+ if (len > sge->length)
+ len = sge->length;
+ BUG_ON(len == 0);
+ ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--sqp->s_sge.num_sge)
+ *sge = *sqp->s_sge.sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ sqp->s_len -= len;
+ }
+
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE ||
+ wqe->wr.opcode == IB_WR_RDMA_READ)
+ goto send_comp;
+
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+ wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
+ else
+ wc->opcode = IB_WC_RECV;
+ wc->wr_id = qp->r_wr_id;
+ wc->status = IB_WC_SUCCESS;
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->length;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = qp->remote_qpn;
+ /* XXX do we know which pkey matched? Only needed for GSI. */
+ wc->pkey_index = 0;
+ wc->slid = qp->remote_ah_attr.dlid;
+ wc->sl = qp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc,
+ wqe->wr.send_flags & IB_SEND_SOLICITED);
+
+send_comp:
+ sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
+
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &sqp->s_flags) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = IB_WC_SUCCESS;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->length;
+ wc->qp_num = sqp->ibqp.qp_num;
+ wc->src_qp = 0;
+ wc->pkey_index = 0;
+ wc->slid = 0;
+ wc->sl = 0;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_cq_enter(to_icq(sqp->ibqp.send_cq), wc, 0);
+ }
+
+ /* Update s_last now that we are finished with the SWQE */
+ spin_lock_irqsave(&sqp->s_lock, flags);
+ if (++sqp->s_last >= sqp->s_size)
+ sqp->s_last = 0;
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+ goto again;
+
+done:
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+}
+
+/**
+ * ipath_no_bufs_available - tell the layer driver we need buffers
+ * @qp: the QP that caused the problem
+ * @dev: the device we ran out of buffers on
+ *
+ * Called when we run out of PIO buffers.
+ */
+void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (qp->piowait.next == LIST_POISON1)
+ list_add_tail(&qp->piowait, &dev->piowait);
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+ /*
+ * Note that as soon as ipath_layer_want_buffer() is called and
+ * possibly before it returns, ipath_ib_piobufavail()
+ * 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.
+ */
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+ tasklet_unlock(&qp->s_task);
+ ipath_layer_want_buffer(dev->dd);
+ dev->n_piowait++;
+}
+
+/**
+ * ipath_post_rc_send - post RC and UC sends
+ * @qp: the QP to post on
+ * @wr: the work request to send
+ */
+int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr)
+{
+ struct ipath_swqe *wqe;
+ unsigned long flags;
+ u32 next;
+ int i, j;
+ int acc;
+ int ret;
+
+ /*
+ * Don't allow RDMA reads or atomic operations on UC or
+ * undefined operations.
+ * Make sure buffer is large enough to hold the result for atomics.
+ */
+ if (qp->ibqp.qp_type == IB_QPT_UC) {
+ if ((unsigned) wr->opcode >= IB_WR_RDMA_READ) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ } else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD) {
+ ret = -EINVAL;
+ goto bail;
+ } else if (wr->opcode >= IB_WR_ATOMIC_CMP_AND_SWP &&
+ (wr->num_sge == 0 ||
+ wr->sg_list[0].length < sizeof(u64) ||
+ wr->sg_list[0].addr & (sizeof(u64) - 1))) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ /* IB spec says that num_sge == 0 is OK. */
+ if (wr->num_sge > qp->s_max_sge) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ spin_lock_irqsave(&qp->s_lock, flags);
+ next = qp->s_head + 1;
+ if (next >= qp->s_size)
+ next = 0;
+ if (next == qp->s_last) {
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ wqe = get_swqe_ptr(qp, qp->s_head);
+ wqe->wr = *wr;
+ wqe->ssn = qp->s_ssn++;
+ wqe->sg_list[0].mr = NULL;
+ wqe->sg_list[0].vaddr = NULL;
+ wqe->sg_list[0].length = 0;
+ wqe->sg_list[0].sge_length = 0;
+ wqe->length = 0;
+ acc = wr->opcode >= IB_WR_RDMA_READ ? IB_ACCESS_LOCAL_WRITE : 0;
+ for (i = 0, j = 0; i < wr->num_sge; i++) {
+ if (to_ipd(qp->ibqp.pd)->user && wr->sg_list[i].lkey == 0) {
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(&to_idev(qp->ibqp.device)->lk_table,
+ &wqe->sg_list[j], &wr->sg_list[i],
+ acc)) {
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ret = -EINVAL;
+ goto bail;
+ }
+ wqe->length += wr->sg_list[i].length;
+ j++;
+ }
+ wqe->wr.num_sge = j;
+ qp->s_head = next;
+ /*
+ * Wake up the send tasklet if the QP is not waiting
+ * for an RNR timeout.
+ */
+ next = qp->s_rnr_timeout;
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ if (next == 0) {
+ if (qp->ibqp.qp_type == IB_QPT_UC)
+ ipath_do_uc_send((unsigned long) qp);
+ else
+ ipath_do_rc_send((unsigned long) qp);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
new file mode 100644
index 000000000000..01c4c6c56118
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_post_srq_receive - post a receive on a shared receive queue
+ * @ibsrq: the SRQ to post the receive on
+ * @wr: the list of work requests to post
+ * @bad_wr: the first WR to cause a problem is put here
+ *
+ * This may be called from interrupt context.
+ */
+int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+ struct ipath_ibdev *dev = to_idev(ibsrq->device);
+ unsigned long flags;
+ int ret;
+
+ for (; wr; wr = wr->next) {
+ struct ipath_rwqe *wqe;
+ u32 next;
+ int i, j;
+
+ if (wr->num_sge > srq->rq.max_sge) {
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irqsave(&srq->rq.lock, flags);
+ next = srq->rq.head + 1;
+ if (next >= srq->rq.size)
+ next = 0;
+ if (next == srq->rq.tail) {
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ wqe = get_rwqe_ptr(&srq->rq, srq->rq.head);
+ wqe->wr_id = wr->wr_id;
+ wqe->sg_list[0].mr = NULL;
+ wqe->sg_list[0].vaddr = NULL;
+ wqe->sg_list[0].length = 0;
+ wqe->sg_list[0].sge_length = 0;
+ wqe->length = 0;
+ for (i = 0, j = 0; i < wr->num_sge; i++) {
+ /* Check LKEY */
+ if (to_ipd(srq->ibsrq.pd)->user &&
+ wr->sg_list[i].lkey == 0) {
+ spin_unlock_irqrestore(&srq->rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(&dev->lk_table,
+ &wqe->sg_list[j],
+ &wr->sg_list[i],
+ IB_ACCESS_LOCAL_WRITE)) {
+ spin_unlock_irqrestore(&srq->rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ wqe->length += wr->sg_list[i].length;
+ j++;
+ }
+ wqe->num_sge = j;
+ srq->rq.head = next;
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_create_srq - create a shared receive queue
+ * @ibpd: the protection domain of the SRQ to create
+ * @attr: the attributes of the SRQ
+ * @udata: not used by the InfiniPath verbs driver
+ */
+struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata)
+{
+ struct ipath_srq *srq;
+ u32 sz;
+ struct ib_srq *ret;
+
+ if (srq_init_attr->attr.max_sge < 1) {
+ ret = ERR_PTR(-EINVAL);
+ goto bail;
+ }
+
+ srq = kmalloc(sizeof(*srq), GFP_KERNEL);
+ if (!srq) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of entries.
+ */
+ srq->rq.size = srq_init_attr->attr.max_wr + 1;
+ sz = sizeof(struct ipath_sge) * srq_init_attr->attr.max_sge +
+ sizeof(struct ipath_rwqe);
+ srq->rq.wq = vmalloc(srq->rq.size * sz);
+ if (!srq->rq.wq) {
+ kfree(srq);
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * ib_create_srq() will initialize srq->ibsrq.
+ */
+ spin_lock_init(&srq->rq.lock);
+ srq->rq.head = 0;
+ srq->rq.tail = 0;
+ srq->rq.max_sge = srq_init_attr->attr.max_sge;
+ srq->limit = srq_init_attr->attr.srq_limit;
+
+ ret = &srq->ibsrq;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_modify_srq - modify a shared receive queue
+ * @ibsrq: the SRQ to modify
+ * @attr: the new attributes of the SRQ
+ * @attr_mask: indicates which attributes to modify
+ */
+int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+ unsigned long flags;
+ int ret;
+
+ if (attr_mask & IB_SRQ_LIMIT) {
+ spin_lock_irqsave(&srq->rq.lock, flags);
+ srq->limit = attr->srq_limit;
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ }
+ if (attr_mask & IB_SRQ_MAX_WR) {
+ u32 size = attr->max_wr + 1;
+ struct ipath_rwqe *wq, *p;
+ u32 n;
+ u32 sz;
+
+ if (attr->max_sge < srq->rq.max_sge) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ sz = sizeof(struct ipath_rwqe) +
+ attr->max_sge * sizeof(struct ipath_sge);
+ wq = vmalloc(size * sz);
+ if (!wq) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irqsave(&srq->rq.lock, flags);
+ if (srq->rq.head < srq->rq.tail)
+ n = srq->rq.size + srq->rq.head - srq->rq.tail;
+ else
+ n = srq->rq.head - srq->rq.tail;
+ if (size <= n || size <= srq->limit) {
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ vfree(wq);
+ ret = -EINVAL;
+ goto bail;
+ }
+ n = 0;
+ p = wq;
+ while (srq->rq.tail != srq->rq.head) {
+ struct ipath_rwqe *wqe;
+ int i;
+
+ wqe = get_rwqe_ptr(&srq->rq, srq->rq.tail);
+ p->wr_id = wqe->wr_id;
+ p->length = wqe->length;
+ p->num_sge = wqe->num_sge;
+ for (i = 0; i < wqe->num_sge; i++)
+ p->sg_list[i] = wqe->sg_list[i];
+ n++;
+ p = (struct ipath_rwqe *)((char *) p + sz);
+ if (++srq->rq.tail >= srq->rq.size)
+ srq->rq.tail = 0;
+ }
+ vfree(srq->rq.wq);
+ srq->rq.wq = wq;
+ srq->rq.size = size;
+ srq->rq.head = n;
+ srq->rq.tail = 0;
+ srq->rq.max_sge = attr->max_sge;
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+
+ attr->max_wr = srq->rq.size - 1;
+ attr->max_sge = srq->rq.max_sge;
+ attr->srq_limit = srq->limit;
+ return 0;
+}
+
+/**
+ * ipath_destroy_srq - destroy a shared receive queue
+ * @ibsrq: the SRQ to destroy
+ */
+int ipath_destroy_srq(struct ib_srq *ibsrq)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+
+ vfree(srq->rq.wq);
+ kfree(srq);
+
+ return 0;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
new file mode 100644
index 000000000000..fe209137ee74
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+
+struct infinipath_stats ipath_stats;
+
+/**
+ * ipath_snap_cntr - snapshot a chip counter
+ * @dd: the infinipath device
+ * @creg: the counter to snapshot
+ *
+ * called from add_timer and user counter read calls, to deal with
+ * counters that wrap in "human time". The words sent and received, and
+ * the packets sent and received are all that we worry about. For now,
+ * at least, we don't worry about error counters, because if they wrap
+ * that quickly, we probably don't care. We may eventually just make this
+ * handle all the counters. word counters can wrap in about 20 seconds
+ * of full bandwidth traffic, packet counters in a few hours.
+ */
+
+u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
+{
+ u32 val, reg64 = 0;
+ u64 val64;
+ unsigned long t0, t1;
+ u64 ret;
+
+ t0 = jiffies;
+ /* If fast increment counters are only 32 bits, snapshot them,
+ * and maintain them as 64bit values in the driver */
+ if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) &&
+ (creg == dd->ipath_cregs->cr_wordsendcnt ||
+ creg == dd->ipath_cregs->cr_wordrcvcnt ||
+ creg == dd->ipath_cregs->cr_pktsendcnt ||
+ creg == dd->ipath_cregs->cr_pktrcvcnt)) {
+ val64 = ipath_read_creg(dd, creg);
+ val = val64 == ~0ULL ? ~0U : 0;
+ reg64 = 1;
+ } else /* val64 just to keep gcc quiet... */
+ val64 = val = ipath_read_creg32(dd, creg);
+ /*
+ * See if a second has passed. This is just a way to detect things
+ * that are quite broken. Normally this should take just a few
+ * cycles (the check is for long enough that we don't care if we get
+ * pre-empted.) An Opteron HT O read timeout is 4 seconds with
+ * normal NB values
+ */
+ t1 = jiffies;
+ if (time_before(t0 + HZ, t1) && val == -1) {
+ ipath_dev_err(dd, "Error! Read counter 0x%x timed out\n",
+ creg);
+ ret = 0ULL;
+ goto bail;
+ }
+ if (reg64) {
+ ret = val64;
+ goto bail;
+ }
+
+ if (creg == dd->ipath_cregs->cr_wordsendcnt) {
+ if (val != dd->ipath_lastsword) {
+ dd->ipath_sword += val - dd->ipath_lastsword;
+ 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;
+ dd->ipath_lastrword = val;
+ }
+ val64 = dd->ipath_rword;
+ } else if (creg == dd->ipath_cregs->cr_pktsendcnt) {
+ if (val != dd->ipath_lastspkts) {
+ dd->ipath_spkts += val - dd->ipath_lastspkts;
+ dd->ipath_lastspkts = val;
+ }
+ val64 = dd->ipath_spkts;
+ } else if (creg == dd->ipath_cregs->cr_pktrcvcnt) {
+ if (val != dd->ipath_lastrpkts) {
+ dd->ipath_rpkts += val - dd->ipath_lastrpkts;
+ dd->ipath_lastrpkts = val;
+ }
+ val64 = dd->ipath_rpkts;
+ } else
+ val64 = (u64) val;
+
+ ret = val64;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_qcheck - print delta of egrfull/hdrqfull errors for kernel ports
+ * @dd: the infinipath device
+ *
+ * print the delta of egrfull/hdrqfull errors for kernel ports no more than
+ * every 5 seconds. User processes are printed at close, but kernel doesn't
+ * close, so... Separate routine so may call from other places someday, and
+ * so function name when printed by _IPATH_INFO is meaningfull
+ */
+static void ipath_qcheck(struct ipath_devdata *dd)
+{
+ static u64 last_tot_hdrqfull;
+ size_t blen = 0;
+ char buf[128];
+
+ *buf = 0;
+ if (dd->ipath_pd[0]->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+ blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
+ dd->ipath_pd[0]->port_hdrqfull -
+ dd->ipath_p0_hdrqfull);
+ dd->ipath_p0_hdrqfull = dd->ipath_pd[0]->port_hdrqfull;
+ }
+ if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
+ blen += snprintf(buf + blen, sizeof buf - blen,
+ "%srcvegrfull %llu",
+ blen ? ", " : "",
+ (unsigned long long)
+ (ipath_stats.sps_etidfull -
+ dd->ipath_last_tidfull));
+ dd->ipath_last_tidfull = ipath_stats.sps_etidfull;
+ }
+
+ /*
+ * this is actually the number of hdrq full interrupts, not actual
+ * events, but at the moment that's mostly what I'm interested in.
+ * Actual count, etc. is in the counters, if needed. For production
+ * users this won't ordinarily be printed.
+ */
+
+ if ((ipath_debug & (__IPATH_PKTDBG | __IPATH_DBG)) &&
+ ipath_stats.sps_hdrqfull != last_tot_hdrqfull) {
+ blen += snprintf(buf + blen, sizeof buf - blen,
+ "%shdrqfull %llu (all ports)",
+ blen ? ", " : "",
+ (unsigned long long)
+ (ipath_stats.sps_hdrqfull -
+ last_tot_hdrqfull));
+ last_tot_hdrqfull = ipath_stats.sps_hdrqfull;
+ }
+ if (blen)
+ ipath_dbg("%s\n", buf);
+
+ if (dd->ipath_port0head != (u32)
+ le64_to_cpu(*dd->ipath_hdrqtailptr)) {
+ if (dd->ipath_lastport0rcv_cnt ==
+ ipath_stats.sps_port0pkts) {
+ ipath_cdbg(PKT, "missing rcv interrupts? "
+ "port0 hd=%llx tl=%x; port0pkts %llx\n",
+ (unsigned long long)
+ le64_to_cpu(*dd->ipath_hdrqtailptr),
+ dd->ipath_port0head,
+ (unsigned long long)
+ ipath_stats.sps_port0pkts);
+ ipath_kreceive(dd);
+ }
+ dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
+ }
+}
+
+/**
+ * ipath_get_faststats - get word counters from chip before they overflow
+ * @opaque - contains a pointer to the infinipath device ipath_devdata
+ *
+ * called from add_timer
+ */
+void ipath_get_faststats(unsigned long opaque)
+{
+ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
+ u32 val;
+ static unsigned cnt;
+
+ /*
+ * don't access the chip while running diags, or memory diags can
+ * fail
+ */
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT) ||
+ ipath_diag_inuse)
+ /* but re-arm the timer, for diags case; won't hurt other */
+ goto done;
+
+ 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);
+ }
+
+ ipath_qcheck(dd);
+
+ /*
+ * deal with repeat error suppression. Doesn't really matter if
+ * last error was almost a full interval ago, or just a few usecs
+ * ago; still won't get more than 2 per interval. We may want
+ * longer intervals for this eventually, could do with mod, counter
+ * or separate timer. Also see code in ipath_handle_errors() and
+ * ipath_handle_hwerrors().
+ */
+
+ if (dd->ipath_lasterror)
+ dd->ipath_lasterror = 0;
+ if (dd->ipath_lasthwerror)
+ dd->ipath_lasthwerror = 0;
+ if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs)
+ && time_after(jiffies, dd->ipath_unmasktime)) {
+ char ebuf[256];
+ ipath_decode_err(ebuf, sizeof ebuf,
+ (dd->ipath_maskederrs & ~dd->
+ ipath_ignorederrs));
+ if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+ ipath_dev_err(dd, "Re-enabling masked errors "
+ "(%s)\n", ebuf);
+ else {
+ /*
+ * rcvegrfull and rcvhdrqfull are "normal", for some
+ * types of processes (mostly benchmarks) that send
+ * huge numbers of messages, while not processing
+ * them. So only complain about these at debug
+ * level.
+ */
+ ipath_dbg("Disabling frequent queue full errors "
+ "(%s)\n", ebuf);
+ }
+ dd->ipath_maskederrs = dd->ipath_ignorederrs;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ }
+
+ /* limit qfull messages to ~one per minute per port */
+ if ((++cnt & 0x10)) {
+ for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
+ val--) {
+ if (dd->ipath_lastegrheads[val] != -1)
+ dd->ipath_lastegrheads[val] = -1;
+ if (dd->ipath_lastrcvhdrqtails[val] != -1)
+ dd->ipath_lastrcvhdrqtails[val] = -1;
+ }
+ }
+
+ if (dd->ipath_nosma_bufs) {
+ dd->ipath_nosma_secs += 5;
+ if (dd->ipath_nosma_secs >= 30) {
+ ipath_cdbg(SMA, "No SMA bufs avail %u seconds; "
+ "cancelling pending sends\n",
+ dd->ipath_nosma_secs);
+ /*
+ * issue an abort as well, in case we have a packet
+ * stuck in launch fifo. This could corrupt an
+ * outgoing user packet in the worst case,
+ * but this is a pretty catastrophic, anyway.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_ABORT);
+ ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
+ dd->ipath_piobcnt2k +
+ dd->ipath_piobcnt4k -
+ dd->ipath_lastport_piobuf);
+ /* start again, if necessary */
+ dd->ipath_nosma_secs = 0;
+ } else
+ ipath_cdbg(SMA, "No SMA bufs avail %u tries, "
+ "after %u seconds\n",
+ dd->ipath_nosma_bufs,
+ dd->ipath_nosma_secs);
+ }
+
+done:
+ mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
new file mode 100644
index 000000000000..32acd8048b49
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/ctype.h>
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+/**
+ * ipath_parse_ushort - parse an unsigned short value in an arbitrary base
+ * @str: the string containing the number
+ * @valp: where to put the result
+ *
+ * returns the number of bytes consumed, or negative value on error
+ */
+int ipath_parse_ushort(const char *str, unsigned short *valp)
+{
+ unsigned long val;
+ char *end;
+ int ret;
+
+ if (!isdigit(str[0])) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ val = simple_strtoul(str, &end, 0);
+
+ if (val > 0xffff) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ *valp = val;
+
+ ret = end + 1 - str;
+ if (ret == 0)
+ ret = -EINVAL;
+
+bail:
+ return ret;
+}
+
+static ssize_t show_version(struct device_driver *dev, char *buf)
+{
+ /* The string printed here is already newline-terminated. */
+ return scnprintf(buf, PAGE_SIZE, "%s", ipath_core_version);
+}
+
+static ssize_t show_num_units(struct device_driver *dev, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ ipath_count_units(NULL, NULL, NULL));
+}
+
+#define DRIVER_STAT(name, attr) \
+ static ssize_t show_stat_##name(struct device_driver *dev, \
+ char *buf) \
+ { \
+ return scnprintf( \
+ buf, PAGE_SIZE, "%llu\n", \
+ (unsigned long long) ipath_stats.sps_ ##attr); \
+ } \
+ static DRIVER_ATTR(name, S_IRUGO, show_stat_##name, NULL)
+
+DRIVER_STAT(intrs, ints);
+DRIVER_STAT(err_intrs, errints);
+DRIVER_STAT(errs, errs);
+DRIVER_STAT(pkt_errs, pkterrs);
+DRIVER_STAT(crc_errs, crcerrs);
+DRIVER_STAT(hw_errs, hwerrs);
+DRIVER_STAT(ib_link, iblink);
+DRIVER_STAT(port0_pkts, port0pkts);
+DRIVER_STAT(ether_spkts, ether_spkts);
+DRIVER_STAT(ether_rpkts, ether_rpkts);
+DRIVER_STAT(sma_spkts, sma_spkts);
+DRIVER_STAT(sma_rpkts, sma_rpkts);
+DRIVER_STAT(hdrq_full, hdrqfull);
+DRIVER_STAT(etid_full, etidfull);
+DRIVER_STAT(no_piobufs, nopiobufs);
+DRIVER_STAT(ports, ports);
+DRIVER_STAT(pkey0, pkeys[0]);
+DRIVER_STAT(pkey1, pkeys[1]);
+DRIVER_STAT(pkey2, pkeys[2]);
+DRIVER_STAT(pkey3, pkeys[3]);
+/* XXX fix the following when dynamic table of devices used */
+DRIVER_STAT(lid0, lid[0]);
+DRIVER_STAT(lid1, lid[1]);
+DRIVER_STAT(lid2, lid[2]);
+DRIVER_STAT(lid3, lid[3]);
+
+DRIVER_STAT(nports, nports);
+DRIVER_STAT(null_intr, nullintr);
+DRIVER_STAT(max_pkts_call, maxpkts_call);
+DRIVER_STAT(avg_pkts_call, avgpkts_call);
+DRIVER_STAT(page_locks, pagelocks);
+DRIVER_STAT(page_unlocks, pageunlocks);
+DRIVER_STAT(krdrops, krdrops);
+/* XXX fix the following when dynamic table of devices used */
+DRIVER_STAT(mlid0, mlid[0]);
+DRIVER_STAT(mlid1, mlid[1]);
+DRIVER_STAT(mlid2, mlid[2]);
+DRIVER_STAT(mlid3, mlid[3]);
+
+static struct attribute *driver_stat_attributes[] = {
+ &driver_attr_intrs.attr,
+ &driver_attr_err_intrs.attr,
+ &driver_attr_errs.attr,
+ &driver_attr_pkt_errs.attr,
+ &driver_attr_crc_errs.attr,
+ &driver_attr_hw_errs.attr,
+ &driver_attr_ib_link.attr,
+ &driver_attr_port0_pkts.attr,
+ &driver_attr_ether_spkts.attr,
+ &driver_attr_ether_rpkts.attr,
+ &driver_attr_sma_spkts.attr,
+ &driver_attr_sma_rpkts.attr,
+ &driver_attr_hdrq_full.attr,
+ &driver_attr_etid_full.attr,
+ &driver_attr_no_piobufs.attr,
+ &driver_attr_ports.attr,
+ &driver_attr_pkey0.attr,
+ &driver_attr_pkey1.attr,
+ &driver_attr_pkey2.attr,
+ &driver_attr_pkey3.attr,
+ &driver_attr_lid0.attr,
+ &driver_attr_lid1.attr,
+ &driver_attr_lid2.attr,
+ &driver_attr_lid3.attr,
+ &driver_attr_nports.attr,
+ &driver_attr_null_intr.attr,
+ &driver_attr_max_pkts_call.attr,
+ &driver_attr_avg_pkts_call.attr,
+ &driver_attr_page_locks.attr,
+ &driver_attr_page_unlocks.attr,
+ &driver_attr_krdrops.attr,
+ &driver_attr_mlid0.attr,
+ &driver_attr_mlid1.attr,
+ &driver_attr_mlid2.attr,
+ &driver_attr_mlid3.attr,
+ NULL
+};
+
+static struct attribute_group driver_stat_attr_group = {
+ .name = "stats",
+ .attrs = driver_stat_attributes
+};
+
+static ssize_t show_status(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+
+ if (!dd->ipath_statusp) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
+ (unsigned long long) *(dd->ipath_statusp));
+
+bail:
+ return ret;
+}
+
+static const char *ipath_status_str[] = {
+ "Initted",
+ "Disabled",
+ "Admin_Disabled",
+ "OIB_SMA",
+ "SMA",
+ "Present",
+ "IB_link_up",
+ "IB_configured",
+ "NoIBcable",
+ "Fatal_Hardware_Error",
+ NULL,
+};
+
+static ssize_t show_status_str(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int i, any;
+ u64 s;
+ ssize_t ret;
+
+ if (!dd->ipath_statusp) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ s = *(dd->ipath_statusp);
+ *buf = '\0';
+ for (any = i = 0; s && ipath_status_str[i]; i++) {
+ if (s & 1) {
+ if (any && strlcat(buf, " ", PAGE_SIZE) >=
+ PAGE_SIZE)
+ /* overflow */
+ break;
+ if (strlcat(buf, ipath_status_str[i],
+ PAGE_SIZE) >= PAGE_SIZE)
+ break;
+ any = 1;
+ }
+ s >>= 1;
+ }
+ if (any)
+ strlcat(buf, "\n", PAGE_SIZE);
+
+ ret = strlen(buf);
+
+bail:
+ return ret;
+}
+
+static ssize_t show_boardversion(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ /* The string printed here is already newline-terminated. */
+ return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
+}
+
+static ssize_t show_lid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);
+}
+
+static ssize_t store_lid(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ u16 lid;
+ int ret;
+
+ ret = ipath_parse_ushort(buf, &lid);
+ if (ret < 0)
+ goto invalid;
+
+ if (lid == 0 || lid >= 0xc000) {
+ ret = -EINVAL;
+ goto invalid;
+ }
+
+ ipath_set_sps_lid(dd, lid, 0);
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid LID\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_mlid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);
+}
+
+static ssize_t store_mlid(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int unit;
+ u16 mlid;
+ int ret;
+
+ ret = ipath_parse_ushort(buf, &mlid);
+ if (ret < 0)
+ goto invalid;
+
+ unit = dd->ipath_unit;
+
+ dd->ipath_mlid = mlid;
+ ipath_stats.sps_mlid[unit] = mlid;
+ ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST);
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid MLID\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_guid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ u8 *guid;
+
+ guid = (u8 *) & (dd->ipath_guid);
+
+ return scnprintf(buf, PAGE_SIZE,
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ guid[0], guid[1], guid[2], guid[3],
+ guid[4], guid[5], guid[6], guid[7]);
+}
+
+static ssize_t store_guid(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+ unsigned short guid[8];
+ __be64 nguid;
+ u8 *ng;
+ int i;
+
+ if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
+ &guid[0], &guid[1], &guid[2], &guid[3],
+ &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
+ goto invalid;
+
+ ng = (u8 *) &nguid;
+
+ for (i = 0; i < 8; i++) {
+ if (guid[i] > 0xff)
+ goto invalid;
+ ng[i] = guid[i];
+ }
+
+ dd->ipath_guid = nguid;
+ dd->ipath_nguid = 1;
+
+ ret = strlen(buf);
+ goto bail;
+
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid GUID\n");
+ ret = -EINVAL;
+
+bail:
+ return ret;
+}
+
+static ssize_t show_nguid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
+}
+
+static ssize_t show_serial(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ buf[sizeof dd->ipath_serial] = '\0';
+ memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static ssize_t show_unit(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
+}
+
+#define DEVICE_COUNTER(name, attr) \
+ static ssize_t show_counter_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ struct ipath_devdata *dd = dev_get_drvdata(dev); \
+ return scnprintf(\
+ buf, PAGE_SIZE, "%llu\n", (unsigned long long) \
+ ipath_snap_cntr( \
+ dd, offsetof(struct infinipath_counters, \
+ attr) / sizeof(u64))); \
+ } \
+ static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);
+
+DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);
+DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);
+DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);
+DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);
+DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);
+DEVICE_COUNTER(lb_ints, LBIntCnt);
+DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);
+DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);
+DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);
+DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);
+DEVICE_COUNTER(rx_dwords, RxDwordCnt);
+DEVICE_COUNTER(rx_ebps, RxEBPCnt);
+DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);
+DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);
+DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);
+DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);
+DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);
+DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);
+DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);
+DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt);
+DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt);
+DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt);
+DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt);
+DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt);
+DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt);
+DEVICE_COUNTER(tx_dwords, TxDwordCnt);
+DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt);
+DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt);
+DEVICE_COUNTER(tx_len_errs, TxLenErrCnt);
+DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt);
+DEVICE_COUNTER(tx_underruns, TxUnderrunCnt);
+DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt);
+
+static struct attribute *dev_counter_attributes[] = {
+ &dev_attr_ib_link_downeds.attr,
+ &dev_attr_ib_link_err_recoveries.attr,
+ &dev_attr_ib_status_changes.attr,
+ &dev_attr_ib_symbol_errs.attr,
+ &dev_attr_lb_flow_stalls.attr,
+ &dev_attr_lb_ints.attr,
+ &dev_attr_rx_bad_formats.attr,
+ &dev_attr_rx_buf_ovfls.attr,
+ &dev_attr_rx_data_pkts.attr,
+ &dev_attr_rx_dropped_pkts.attr,
+ &dev_attr_rx_dwords.attr,
+ &dev_attr_rx_ebps.attr,
+ &dev_attr_rx_flow_ctrl_errs.attr,
+ &dev_attr_rx_flow_pkts.attr,
+ &dev_attr_rx_icrc_errs.attr,
+ &dev_attr_rx_len_errs.attr,
+ &dev_attr_rx_link_problems.attr,
+ &dev_attr_rx_lpcrc_errs.attr,
+ &dev_attr_rx_max_min_len_errs.attr,
+ &dev_attr_rx_p0_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p1_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p2_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p3_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p4_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p5_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p6_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p7_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p8_hdr_egr_ovfls.attr,
+ &dev_attr_rx_pkey_mismatches.attr,
+ &dev_attr_rx_tid_full_errs.attr,
+ &dev_attr_rx_tid_valid_errs.attr,
+ &dev_attr_rx_vcrc_errs.attr,
+ &dev_attr_tx_data_pkts.attr,
+ &dev_attr_tx_dropped_pkts.attr,
+ &dev_attr_tx_dwords.attr,
+ &dev_attr_tx_flow_pkts.attr,
+ &dev_attr_tx_flow_stalls.attr,
+ &dev_attr_tx_len_errs.attr,
+ &dev_attr_tx_max_min_len_errs.attr,
+ &dev_attr_tx_underruns.attr,
+ &dev_attr_tx_unsup_vl_errs.attr,
+ NULL
+};
+
+static struct attribute_group dev_counter_attr_group = {
+ .name = "counters",
+ .attrs = dev_counter_attributes
+};
+
+static ssize_t store_reset(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int ret;
+
+ if (count < 5 || memcmp(buf, "reset", 5)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (dd->ipath_flags & IPATH_DISABLED) {
+ /*
+ * post-reset init would re-enable interrupts, etc.
+ * so don't allow reset on disabled devices. Not
+ * perfect error, but about the best choice.
+ */
+ dev_info(dev,"Unit %d is disabled, can't reset\n",
+ dd->ipath_unit);
+ ret = -EINVAL;
+ }
+ ret = ipath_reset_device(dd->ipath_unit);
+bail:
+ return ret<0 ? ret : count;
+}
+
+static ssize_t store_link_state(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int ret, r;
+ u16 state;
+
+ ret = ipath_parse_ushort(buf, &state);
+ if (ret < 0)
+ goto invalid;
+
+ r = ipath_layer_set_linkstate(dd, state);
+ if (r < 0) {
+ ret = r;
+ goto bail;
+ }
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid link state\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_mtu(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu);
+}
+
+static ssize_t store_mtu(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+ u16 mtu = 0;
+ int r;
+
+ ret = ipath_parse_ushort(buf, &mtu);
+ if (ret < 0)
+ goto invalid;
+
+ r = ipath_layer_set_mtu(dd, mtu);
+ if (r < 0)
+ ret = r;
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid MTU\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_enabled(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1);
+}
+
+static ssize_t store_enabled(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+ u16 enable = 0;
+
+ ret = ipath_parse_ushort(buf, &enable);
+ if (ret < 0) {
+ ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
+ goto bail;
+ }
+
+ if (enable) {
+ if (!(dd->ipath_flags & IPATH_DISABLED))
+ goto bail;
+
+ dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
+ /* same as post-reset */
+ ret = ipath_init_chip(dd, 1);
+ if (ret)
+ ipath_dev_err(dd, "Failed to enable unit %d\n",
+ dd->ipath_unit);
+ else {
+ dd->ipath_flags &= ~IPATH_DISABLED;
+ *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
+ }
+ }
+ else if (!(dd->ipath_flags & IPATH_DISABLED)) {
+ dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
+ ipath_shutdown_device(dd);
+ dd->ipath_flags |= IPATH_DISABLED;
+ *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
+ }
+
+bail:
+ return ret;
+}
+
+static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
+static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
+
+static struct attribute *driver_attributes[] = {
+ &driver_attr_num_units.attr,
+ &driver_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group driver_attr_group = {
+ .attrs = driver_attributes
+};
+
+static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
+static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
+static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state);
+static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
+static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
+static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
+static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
+static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
+static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+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 struct attribute *dev_attributes[] = {
+ &dev_attr_guid.attr,
+ &dev_attr_lid.attr,
+ &dev_attr_link_state.attr,
+ &dev_attr_mlid.attr,
+ &dev_attr_mtu.attr,
+ &dev_attr_nguid.attr,
+ &dev_attr_serial.attr,
+ &dev_attr_status.attr,
+ &dev_attr_status_str.attr,
+ &dev_attr_boardversion.attr,
+ &dev_attr_unit.attr,
+ &dev_attr_enabled.attr,
+ NULL
+};
+
+static struct attribute_group dev_attr_group = {
+ .attrs = dev_attributes
+};
+
+/**
+ * ipath_expose_reset - create a device reset file
+ * @dev: the device structure
+ *
+ * Only expose a file that lets us reset the device after someone
+ * enters diag mode. A device reset is quite likely to crash the
+ * machine entirely, so we don't want to normally make it
+ * available.
+ */
+int ipath_expose_reset(struct device *dev)
+{
+ return device_create_file(dev, &dev_attr_reset);
+}
+
+int ipath_driver_create_group(struct device_driver *drv)
+{
+ int ret;
+
+ ret = sysfs_create_group(&drv->kobj, &driver_attr_group);
+ if (ret)
+ goto bail;
+
+ ret = sysfs_create_group(&drv->kobj, &driver_stat_attr_group);
+ if (ret)
+ sysfs_remove_group(&drv->kobj, &driver_attr_group);
+
+bail:
+ return ret;
+}
+
+void ipath_driver_remove_group(struct device_driver *drv)
+{
+ sysfs_remove_group(&drv->kobj, &driver_stat_attr_group);
+ sysfs_remove_group(&drv->kobj, &driver_attr_group);
+}
+
+int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
+{
+ int ret;
+ char unit[5];
+
+ ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
+ if (ret)
+ goto bail;
+
+ ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group);
+ if (ret)
+ goto bail_attrs;
+
+ snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+ ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, unit);
+ if (ret == 0)
+ goto bail;
+
+ sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+bail_attrs:
+ sysfs_remove_group(&dev->kobj, &dev_attr_group);
+bail:
+ return ret;
+}
+
+void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
+{
+ char unit[5];
+
+ snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+ sysfs_remove_link(&dev->driver->kobj, unit);
+
+ sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+ sysfs_remove_group(&dev->kobj, &dev_attr_group);
+
+ device_remove_file(dev, &dev_attr_reset);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
new file mode 100644
index 000000000000..0d6dbc0a541e
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* cut down ridiculously long IB macro names */
+#define OP(x) IB_OPCODE_UC_##x
+
+static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
+ struct ib_wc *wc)
+{
+ if (++qp->s_last == qp->s_size)
+ qp->s_last = 0;
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = IB_WC_SUCCESS;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->length;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = qp->remote_qpn;
+ wc->pkey_index = 0;
+ wc->slid = qp->remote_ah_attr.dlid;
+ wc->sl = qp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 0);
+ }
+ wqe = get_swqe_ptr(qp, qp->s_last);
+}
+
+/**
+ * ipath_do_uc_send - do a send on a UC queue
+ * @data: contains a pointer to the QP to send on
+ *
+ * Process entries in the send work queue until the queue is exhausted.
+ * Only allow one CPU to send a packet per QP (tasklet).
+ * Otherwise, after we drop the QP lock, two threads could send
+ * packets out of order.
+ * This is similar to ipath_do_rc_send() below except we don't have
+ * timeouts or resends.
+ */
+void ipath_do_uc_send(unsigned long data)
+{
+ struct ipath_qp *qp = (struct ipath_qp *)data;
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_swqe *wqe;
+ unsigned long flags;
+ u16 lrh0;
+ u32 hwords;
+ u32 nwords;
+ u32 extra_bytes;
+ u32 bth0;
+ u32 bth2;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 len;
+ struct ipath_other_headers *ohdr;
+ struct ib_wc wc;
+
+ if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
+ goto bail;
+
+ if (unlikely(qp->remote_ah_attr.dlid ==
+ ipath_layer_get_lid(dev->dd))) {
+ /* Pass in an uninitialized ib_wc to save stack space. */
+ ipath_ruc_loopback(qp, &wc);
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+ goto bail;
+ }
+
+ ohdr = &qp->s_hdr.u.oth;
+ if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
+ ohdr = &qp->s_hdr.u.l.oth;
+
+again:
+ /* Check for a constructed packet to be sent. */
+ if (qp->s_hdrwords != 0) {
+ /*
+ * If no PIO bufs are available, return.
+ * An interrupt will call ipath_ib_piobufavail()
+ * when one is available.
+ */
+ if (ipath_verbs_send(dev->dd, qp->s_hdrwords,
+ (u32 *) &qp->s_hdr,
+ qp->s_cur_size,
+ qp->s_cur_sge)) {
+ ipath_no_bufs_available(qp, dev);
+ goto bail;
+ }
+ dev->n_unicast_xmit++;
+ /* Record that we sent the packet and s_hdr is empty. */
+ qp->s_hdrwords = 0;
+ }
+
+ lrh0 = IPS_LRH_BTH;
+ /* header size in 32-bit words LRH+BTH = (8+12)/4. */
+ hwords = 5;
+
+ /*
+ * The lock is needed to synchronize between
+ * setting qp->s_ack_state and post_send().
+ */
+ spin_lock_irqsave(&qp->s_lock, flags);
+
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK))
+ goto done;
+
+ bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+
+ /* Send a request. */
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ switch (qp->s_state) {
+ default:
+ /*
+ * Signal the completion of the last send (if there is
+ * one).
+ */
+ if (qp->s_last != qp->s_tail)
+ complete_last_send(qp, wqe, &wc);
+
+ /* Check if send work queue is empty. */
+ if (qp->s_tail == qp->s_head)
+ goto done;
+ /*
+ * Start a new request.
+ */
+ qp->s_psn = wqe->psn = qp->s_next_psn;
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+ qp->s_sge.num_sge = wqe->wr.num_sge;
+ qp->s_len = len = wqe->length;
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ if (len > pmtu) {
+ qp->s_state = OP(SEND_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_ONLY);
+ else {
+ qp->s_state =
+ OP(SEND_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(len);
+ hwords += sizeof(struct ib_reth) / 4;
+ if (len > pmtu) {
+ qp->s_state = OP(RDMA_WRITE_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_ONLY);
+ else {
+ qp->s_state =
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the RETH */
+ ohdr->u.rc.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ break;
+
+ default:
+ goto done;
+ }
+ if (++qp->s_tail >= qp->s_size)
+ qp->s_tail = 0;
+ break;
+
+ case OP(SEND_FIRST):
+ qp->s_state = OP(SEND_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ len = qp->s_len;
+ if (len > pmtu) {
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_LAST);
+ else {
+ qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ break;
+
+ case OP(RDMA_WRITE_FIRST):
+ qp->s_state = OP(RDMA_WRITE_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_MIDDLE):
+ len = qp->s_len;
+ if (len > pmtu) {
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_LAST);
+ else {
+ qp->s_state =
+ OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ break;
+ }
+ bth2 = qp->s_next_psn++ & IPS_PSN_MASK;
+ qp->s_len -= len;
+ bth0 |= qp->s_state << 24;
+
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ /* Construct the header. */
+ extra_bytes = (4 - len) & 3;
+ nwords = (len + extra_bytes) >> 2;
+ if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+ /* Header size in 32-bit words. */
+ hwords += 10;
+ lrh0 = IPS_LRH_GRH;
+ qp->s_hdr.u.l.grh.version_tclass_flow =
+ cpu_to_be32((6 << 28) |
+ (qp->remote_ah_attr.grh.traffic_class
+ << 20) |
+ qp->remote_ah_attr.grh.flow_label);
+ qp->s_hdr.u.l.grh.paylen =
+ cpu_to_be16(((hwords - 12) + nwords +
+ SIZE_OF_CRC) << 2);
+ /* next_hdr is defined by C8-7 in ch. 8.4.1 */
+ qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+ qp->s_hdr.u.l.grh.hop_limit =
+ qp->remote_ah_attr.grh.hop_limit;
+ /* The SGID is 32-bit aligned. */
+ qp->s_hdr.u.l.grh.sgid.global.subnet_prefix =
+ dev->gid_prefix;
+ qp->s_hdr.u.l.grh.sgid.global.interface_id =
+ ipath_layer_get_guid(dev->dd);
+ qp->s_hdr.u.l.grh.dgid = qp->remote_ah_attr.grh.dgid;
+ }
+ qp->s_hdrwords = hwords;
+ qp->s_cur_sge = &qp->s_sge;
+ qp->s_cur_size = len;
+ lrh0 |= qp->remote_ah_attr.sl << 4;
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ /* DEST LID */
+ qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC);
+ qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+ bth0 |= extra_bytes << 20;
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(bth2);
+
+ /* Check for more work to do. */
+ goto again;
+
+done:
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+
+bail:
+ return;
+}
+
+/**
+ * ipath_uc_rcv - handle an incoming UC packet
+ * @dev: the device the packet came in on
+ * @hdr: the header of the packet
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the length of the packet
+ * @qp: the QP for this packet.
+ *
+ * This is called from ipath_qp_rcv() to process an incoming UC packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+ struct ipath_other_headers *ohdr;
+ int opcode;
+ u32 hdrsize;
+ u32 psn;
+ u32 pad;
+ unsigned long flags;
+ struct ib_wc wc;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ struct ib_reth *reth;
+ int header_in_data;
+
+ /* Check for GRH */
+ if (!has_grh) {
+ ohdr = &hdr->u.oth;
+ hdrsize = 8 + 12; /* LRH + BTH */
+ psn = be32_to_cpu(ohdr->bth[2]);
+ header_in_data = 0;
+ } else {
+ ohdr = &hdr->u.l.oth;
+ hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */
+ /*
+ * The header with GRH is 60 bytes and the
+ * core driver sets the eager header buffer
+ * size to 56 bytes so the last 4 bytes of
+ * the BTH header (PSN) is in the data buffer.
+ */
+ header_in_data =
+ ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+ if (header_in_data) {
+ psn = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ } else
+ psn = be32_to_cpu(ohdr->bth[2]);
+ }
+ /*
+ * The opcode is in the low byte when its in network order
+ * (top byte when in host order).
+ */
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+
+ wc.imm_data = 0;
+ wc.wc_flags = 0;
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+
+ /* Compare the PSN verses the expected PSN. */
+ if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) {
+ /*
+ * Handle a sequence error.
+ * Silently drop any current message.
+ */
+ qp->r_psn = psn;
+ inv:
+ qp->r_state = OP(SEND_LAST);
+ switch (opcode) {
+ case OP(SEND_FIRST):
+ case OP(SEND_ONLY):
+ case OP(SEND_ONLY_WITH_IMMEDIATE):
+ goto send_first;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_ONLY):
+ case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+ goto rdma_first;
+
+ default:
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ }
+
+ /* Check for opcode sequence errors. */
+ switch (qp->r_state) {
+ case OP(SEND_FIRST):
+ case OP(SEND_MIDDLE):
+ if (opcode == OP(SEND_MIDDLE) ||
+ opcode == OP(SEND_LAST) ||
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+ break;
+ goto inv;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_MIDDLE):
+ if (opcode == OP(RDMA_WRITE_MIDDLE) ||
+ opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+ break;
+ goto inv;
+
+ default:
+ if (opcode == OP(SEND_FIRST) ||
+ opcode == OP(SEND_ONLY) ||
+ opcode == OP(SEND_ONLY_WITH_IMMEDIATE) ||
+ opcode == OP(RDMA_WRITE_FIRST) ||
+ opcode == OP(RDMA_WRITE_ONLY) ||
+ opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+ break;
+ goto inv;
+ }
+
+ /* OK, process the packet. */
+ switch (opcode) {
+ case OP(SEND_FIRST):
+ case OP(SEND_ONLY):
+ case OP(SEND_ONLY_WITH_IMMEDIATE):
+ send_first:
+ if (qp->r_reuse_sge) {
+ qp->r_reuse_sge = 0;
+ qp->r_sge = qp->s_rdma_sge;
+ } else if (!ipath_get_rwqe(qp, 0)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Save the WQE so we can reuse it in case of an error. */
+ qp->s_rdma_sge = qp->r_sge;
+ qp->r_rcv_len = 0;
+ if (opcode == OP(SEND_ONLY))
+ goto send_last;
+ else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
+ goto send_last_imm;
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ /* Check for invalid length PMTU or posted rwqe len. */
+ if (unlikely(tlen != (hdrsize + pmtu + 4))) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ qp->r_rcv_len += pmtu;
+ if (unlikely(qp->r_rcv_len > qp->r_len)) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ ipath_copy_sge(&qp->r_sge, data, pmtu);
+ break;
+
+ case OP(SEND_LAST_WITH_IMMEDIATE):
+ send_last_imm:
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else {
+ /* Immediate data comes after BTH */
+ wc.imm_data = ohdr->u.imm_data;
+ }
+ hdrsize += 4;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ /* FALLTHROUGH */
+ case OP(SEND_LAST):
+ send_last:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ wc.byte_len = tlen + qp->r_rcv_len;
+ if (unlikely(wc.byte_len > qp->r_len)) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* XXX Need to free SGEs */
+ last_imm:
+ ipath_copy_sge(&qp->r_sge, data, tlen);
+ wc.wr_id = qp->r_wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = IB_WC_RECV;
+ wc.vendor_err = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+ (ohdr->bth[0] &
+ __constant_cpu_to_be32(1 << 23)) != 0);
+ break;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_ONLY):
+ case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */
+ rdma_first:
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ hdrsize += sizeof(*reth);
+ qp->r_len = be32_to_cpu(reth->length);
+ qp->r_rcv_len = 0;
+ if (qp->r_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+
+ /* Check rkey */
+ if (unlikely(!ipath_rkey_ok(
+ dev, &qp->r_sge, qp->r_len,
+ vaddr, rkey,
+ IB_ACCESS_REMOTE_WRITE))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ } else {
+ qp->r_sge.sg_list = NULL;
+ qp->r_sge.sge.mr = NULL;
+ qp->r_sge.sge.vaddr = NULL;
+ qp->r_sge.sge.length = 0;
+ qp->r_sge.sge.sge_length = 0;
+ }
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_WRITE))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ if (opcode == OP(RDMA_WRITE_ONLY))
+ goto rdma_last;
+ else if (opcode ==
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+ goto rdma_last_imm;
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_MIDDLE):
+ /* Check for invalid length PMTU or posted rwqe len. */
+ if (unlikely(tlen != (hdrsize + pmtu + 4))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ qp->r_rcv_len += pmtu;
+ if (unlikely(qp->r_rcv_len > qp->r_len)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ ipath_copy_sge(&qp->r_sge, data, pmtu);
+ break;
+
+ case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
+ rdma_last_imm:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ if (qp->r_reuse_sge) {
+ qp->r_reuse_sge = 0;
+ } else if (!ipath_get_rwqe(qp, 1)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else {
+ /* Immediate data comes after BTH */
+ wc.imm_data = ohdr->u.imm_data;
+ }
+ hdrsize += 4;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ wc.byte_len = 0;
+ goto last_imm;
+
+ case OP(RDMA_WRITE_LAST):
+ rdma_last:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ ipath_copy_sge(&qp->r_sge, data, tlen);
+ break;
+
+ default:
+ /* Drop packet for unknown opcodes. */
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ qp->r_psn++;
+ qp->r_state = opcode;
+done:
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
new file mode 100644
index 000000000000..01cfb30ee160
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_smi.h>
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/**
+ * ipath_ud_loopback - handle send on loopback QPs
+ * @sqp: the QP
+ * @ss: the SGE state
+ * @length: the length of the data to send
+ * @wr: the work request
+ * @wc: the work completion entry
+ *
+ * This is called from ipath_post_ud_send() to forward a WQE addressed
+ * to the same HCA.
+ */
+static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
+ u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
+{
+ struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
+ struct ipath_qp *qp;
+ struct ib_ah_attr *ah_attr;
+ unsigned long flags;
+ struct ipath_rq *rq;
+ struct ipath_srq *srq;
+ struct ipath_sge_state rsge;
+ struct ipath_sge *sge;
+ struct ipath_rwqe *wqe;
+
+ qp = ipath_lookup_qpn(&dev->qp_table, wr->wr.ud.remote_qpn);
+ if (!qp)
+ return;
+
+ /*
+ * Check that the qkey matches (except for QP0, see 9.6.1.4.1).
+ * Qkeys with the high order bit set mean use the
+ * qkey from the QP context instead of the WR (see 10.2.5).
+ */
+ if (unlikely(qp->ibqp.qp_num &&
+ ((int) wr->wr.ud.remote_qkey < 0
+ ? qp->qkey : wr->wr.ud.remote_qkey) != qp->qkey)) {
+ /* XXX OK to lose a count once in a while. */
+ dev->qkey_violations++;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+
+ /*
+ * A GRH is expected to preceed the data even if not
+ * present on the wire.
+ */
+ wc->byte_len = length + sizeof(struct ib_grh);
+
+ if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->imm_data = wr->imm_data;
+ } else {
+ wc->wc_flags = 0;
+ wc->imm_data = 0;
+ }
+
+ /*
+ * Get the next work request entry to find where to put the data.
+ * Note that it is safe to drop the lock after changing rq->tail
+ * since ipath_post_receive() won't fill the empty slot.
+ */
+ if (qp->ibqp.srq) {
+ srq = to_isrq(qp->ibqp.srq);
+ rq = &srq->rq;
+ } else {
+ srq = NULL;
+ rq = &qp->r_rq;
+ }
+ spin_lock_irqsave(&rq->lock, flags);
+ if (rq->tail == rq->head) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Silently drop packets which are too big. */
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ if (wc->byte_len > wqe->length) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ wc->wr_id = wqe->wr_id;
+ rsge.sge = wqe->sg_list[0];
+ rsge.sg_list = wqe->sg_list + 1;
+ rsge.num_sge = wqe->num_sge;
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ if (srq && srq->ibsrq.event_handler) {
+ u32 n;
+
+ if (rq->head < rq->tail)
+ n = rq->size + rq->head - rq->tail;
+ else
+ n = rq->head - rq->tail;
+ if (n < srq->limit) {
+ struct ib_event ev;
+
+ srq->limit = 0;
+ spin_unlock_irqrestore(&rq->lock, flags);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev,
+ srq->ibsrq.srq_context);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ ah_attr = &to_iah(wr->wr.ud.ah)->attr;
+ if (ah_attr->ah_flags & IB_AH_GRH) {
+ ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh));
+ wc->wc_flags |= IB_WC_GRH;
+ } else
+ ipath_skip_sge(&rsge, sizeof(struct ib_grh));
+ sge = &ss->sge;
+ while (length) {
+ u32 len = sge->length;
+
+ if (len > length)
+ len = length;
+ BUG_ON(len == 0);
+ ipath_copy_sge(&rsge, sge->vaddr, len);
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ length -= len;
+ }
+ wc->status = IB_WC_SUCCESS;
+ wc->opcode = IB_WC_RECV;
+ wc->vendor_err = 0;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = sqp->ibqp.qp_num;
+ /* XXX do we know which pkey matched? Only needed for GSI. */
+ wc->pkey_index = 0;
+ wc->slid = ipath_layer_get_lid(dev->dd) |
+ (ah_attr->src_path_bits &
+ ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1));
+ wc->sl = ah_attr->sl;
+ wc->dlid_path_bits =
+ ah_attr->dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc,
+ wr->send_flags & IB_SEND_SOLICITED);
+
+done:
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+}
+
+/**
+ * ipath_post_ud_send - post a UD send on QP
+ * @qp: the QP
+ * @wr: the work request
+ *
+ * Note that we actually send the data as it is posted instead of putting
+ * the request into a ring buffer. If we wanted to use a ring buffer,
+ * we would need to save a reference to the destination address in the SWQE.
+ */
+int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_other_headers *ohdr;
+ struct ib_ah_attr *ah_attr;
+ struct ipath_sge_state ss;
+ struct ipath_sge *sg_list;
+ struct ib_wc wc;
+ u32 hwords;
+ u32 nwords;
+ u32 len;
+ u32 extra_bytes;
+ u32 bth0;
+ u16 lrh0;
+ u16 lid;
+ int i;
+ int ret;
+
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) {
+ ret = 0;
+ goto bail;
+ }
+
+ /* IB spec says that num_sge == 0 is OK. */
+ if (wr->num_sge > qp->s_max_sge) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (wr->num_sge > 1) {
+ sg_list = kmalloc((qp->s_max_sge - 1) * sizeof(*sg_list),
+ GFP_ATOMIC);
+ if (!sg_list) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ } else
+ sg_list = NULL;
+
+ /* Check the buffer to send. */
+ ss.sg_list = sg_list;
+ ss.sge.mr = NULL;
+ ss.sge.vaddr = NULL;
+ ss.sge.length = 0;
+ ss.sge.sge_length = 0;
+ ss.num_sge = 0;
+ len = 0;
+ for (i = 0; i < wr->num_sge; i++) {
+ /* Check LKEY */
+ if (to_ipd(qp->ibqp.pd)->user && wr->sg_list[i].lkey == 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(&dev->lk_table, ss.num_sge ?
+ sg_list + ss.num_sge - 1 : &ss.sge,
+ &wr->sg_list[i], 0)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ len += wr->sg_list[i].length;
+ ss.num_sge++;
+ }
+ extra_bytes = (4 - len) & 3;
+ nwords = (len + extra_bytes) >> 2;
+
+ /* Construct the header. */
+ ah_attr = &to_iah(wr->wr.ud.ah)->attr;
+ if (ah_attr->dlid == 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE) {
+ if (ah_attr->dlid != IPS_PERMISSIVE_LID)
+ dev->n_multicast_xmit++;
+ else
+ dev->n_unicast_xmit++;
+ } else {
+ dev->n_unicast_xmit++;
+ lid = ah_attr->dlid &
+ ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ if (unlikely(lid == ipath_layer_get_lid(dev->dd))) {
+ /*
+ * Pass in an uninitialized ib_wc to save stack
+ * space.
+ */
+ ipath_ud_loopback(qp, &ss, len, wr, &wc);
+ goto done;
+ }
+ }
+ if (ah_attr->ah_flags & IB_AH_GRH) {
+ /* Header size in 32-bit words. */
+ hwords = 17;
+ lrh0 = IPS_LRH_GRH;
+ ohdr = &qp->s_hdr.u.l.oth;
+ qp->s_hdr.u.l.grh.version_tclass_flow =
+ cpu_to_be32((6 << 28) |
+ (ah_attr->grh.traffic_class << 20) |
+ ah_attr->grh.flow_label);
+ qp->s_hdr.u.l.grh.paylen =
+ cpu_to_be16(((wr->opcode ==
+ IB_WR_SEND_WITH_IMM ? 6 : 5) +
+ nwords + SIZE_OF_CRC) << 2);
+ /* next_hdr is defined by C8-7 in ch. 8.4.1 */
+ qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+ qp->s_hdr.u.l.grh.hop_limit = ah_attr->grh.hop_limit;
+ /* The SGID is 32-bit aligned. */
+ qp->s_hdr.u.l.grh.sgid.global.subnet_prefix =
+ dev->gid_prefix;
+ qp->s_hdr.u.l.grh.sgid.global.interface_id =
+ ipath_layer_get_guid(dev->dd);
+ qp->s_hdr.u.l.grh.dgid = ah_attr->grh.dgid;
+ /*
+ * Don't worry about sending to locally attached multicast
+ * QPs. It is unspecified by the spec. what happens.
+ */
+ } else {
+ /* Header size in 32-bit words. */
+ hwords = 7;
+ lrh0 = IPS_LRH_BTH;
+ ohdr = &qp->s_hdr.u.oth;
+ }
+ if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+ ohdr->u.ud.imm_data = wr->imm_data;
+ wc.imm_data = wr->imm_data;
+ hwords += 1;
+ bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+ } else if (wr->opcode == IB_WR_SEND) {
+ wc.imm_data = 0;
+ bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
+ } else {
+ ret = -EINVAL;
+ goto bail;
+ }
+ lrh0 |= ah_attr->sl << 4;
+ if (qp->ibqp.qp_type == IB_QPT_SMI)
+ lrh0 |= 0xF000; /* Set VL (see ch. 13.5.3.1) */
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */
+ qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC);
+ lid = ipath_layer_get_lid(dev->dd);
+ if (lid) {
+ lid |= ah_attr->src_path_bits &
+ ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ qp->s_hdr.lrh[3] = cpu_to_be16(lid);
+ } else
+ qp->s_hdr.lrh[3] = IB_LID_PERMISSIVE;
+ if (wr->send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ bth0 |= extra_bytes << 20;
+ bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPS_DEFAULT_P_KEY :
+ ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ /*
+ * Use the multicast QP if the destination LID is a multicast LID.
+ */
+ ohdr->bth[1] = ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&
+ ah_attr->dlid != IPS_PERMISSIVE_LID ?
+ __constant_cpu_to_be32(IPS_MULTICAST_QPN) :
+ cpu_to_be32(wr->wr.ud.remote_qpn);
+ /* XXX Could lose a PSN count but not worth locking */
+ ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPS_PSN_MASK);
+ /*
+ * Qkeys with the high order bit set mean use the
+ * qkey from the QP context instead of the WR (see 10.2.5).
+ */
+ ohdr->u.ud.deth[0] = cpu_to_be32((int)wr->wr.ud.remote_qkey < 0 ?
+ qp->qkey : wr->wr.ud.remote_qkey);
+ ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
+ if (ipath_verbs_send(dev->dd, hwords, (u32 *) &qp->s_hdr,
+ len, &ss))
+ dev->n_no_piobuf++;
+
+done:
+ /* Queue the completion status entry. */
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+ (wr->send_flags & IB_SEND_SIGNALED)) {
+ wc.wr_id = wr->wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.vendor_err = 0;
+ wc.opcode = IB_WC_SEND;
+ wc.byte_len = len;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = 0;
+ wc.wc_flags = 0;
+ /* XXX initialize other fields? */
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
+ }
+ kfree(sg_list);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_ud_rcv - receive an incoming UD packet
+ * @dev: the device the packet came in on
+ * @hdr: the packet header
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP the packet came on
+ *
+ * This is called from ipath_qp_rcv() to process an incoming UD packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+ struct ipath_other_headers *ohdr;
+ int opcode;
+ u32 hdrsize;
+ u32 pad;
+ unsigned long flags;
+ struct ib_wc wc;
+ u32 qkey;
+ u32 src_qp;
+ struct ipath_rq *rq;
+ struct ipath_srq *srq;
+ struct ipath_rwqe *wqe;
+ u16 dlid;
+ int header_in_data;
+
+ /* Check for GRH */
+ if (!has_grh) {
+ ohdr = &hdr->u.oth;
+ hdrsize = 8 + 12 + 8; /* LRH + BTH + DETH */
+ qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
+ src_qp = be32_to_cpu(ohdr->u.ud.deth[1]);
+ header_in_data = 0;
+ } else {
+ ohdr = &hdr->u.l.oth;
+ hdrsize = 8 + 40 + 12 + 8; /* LRH + GRH + BTH + DETH */
+ /*
+ * The header with GRH is 68 bytes and the core driver sets
+ * the eager header buffer size to 56 bytes so the last 12
+ * bytes of the IB header is in the data buffer.
+ */
+ header_in_data =
+ ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+ if (header_in_data) {
+ qkey = be32_to_cpu(((__be32 *) data)[1]);
+ src_qp = be32_to_cpu(((__be32 *) data)[2]);
+ data += 12;
+ } else {
+ qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
+ src_qp = be32_to_cpu(ohdr->u.ud.deth[1]);
+ }
+ }
+ src_qp &= IPS_QPN_MASK;
+
+ /*
+ * Check that the permissive LID is only used on QP0
+ * and the QKEY matches (see 9.6.1.4.1 and 9.6.1.5.1).
+ */
+ if (qp->ibqp.qp_num) {
+ if (unlikely(hdr->lrh[1] == IB_LID_PERMISSIVE ||
+ hdr->lrh[3] == IB_LID_PERMISSIVE)) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ if (unlikely(qkey != qp->qkey)) {
+ /* XXX OK to lose a count once in a while. */
+ dev->qkey_violations++;
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ } else if (hdr->lrh[1] == IB_LID_PERMISSIVE ||
+ hdr->lrh[3] == IB_LID_PERMISSIVE) {
+ struct ib_smp *smp = (struct ib_smp *) data;
+
+ if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ }
+
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ /* Drop incomplete packets. */
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ tlen -= hdrsize + pad + 4;
+
+ /* Drop invalid MAD packets (see 13.5.3.1). */
+ if (unlikely((qp->ibqp.qp_num == 0 &&
+ (tlen != 256 ||
+ (be16_to_cpu(hdr->lrh[0]) >> 12) != 15)) ||
+ (qp->ibqp.qp_num == 1 &&
+ (tlen != 256 ||
+ (be16_to_cpu(hdr->lrh[0]) >> 12) == 15)))) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+
+ /*
+ * A GRH is expected to preceed the data even if not
+ * present on the wire.
+ */
+ wc.byte_len = tlen + sizeof(struct ib_grh);
+
+ /*
+ * The opcode is in the low byte when its in network order
+ * (top byte when in host order).
+ */
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+ if (qp->ibqp.qp_num > 1 &&
+ opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else
+ wc.imm_data = ohdr->u.ud.imm_data;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ hdrsize += sizeof(u32);
+ } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
+ wc.imm_data = 0;
+ wc.wc_flags = 0;
+ } else {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+
+ /*
+ * Get the next work request entry to find where to put the data.
+ * Note that it is safe to drop the lock after changing rq->tail
+ * since ipath_post_receive() won't fill the empty slot.
+ */
+ if (qp->ibqp.srq) {
+ srq = to_isrq(qp->ibqp.srq);
+ rq = &srq->rq;
+ } else {
+ srq = NULL;
+ rq = &qp->r_rq;
+ }
+ spin_lock_irqsave(&rq->lock, flags);
+ if (rq->tail == rq->head) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ /* Silently drop packets which are too big. */
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ if (wc.byte_len > wqe->length) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ wc.wr_id = wqe->wr_id;
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->num_sge;
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ if (srq && srq->ibsrq.event_handler) {
+ u32 n;
+
+ if (rq->head < rq->tail)
+ n = rq->size + rq->head - rq->tail;
+ else
+ n = rq->head - rq->tail;
+ if (n < srq->limit) {
+ struct ib_event ev;
+
+ srq->limit = 0;
+ spin_unlock_irqrestore(&rq->lock, flags);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev,
+ srq->ibsrq.srq_context);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ if (has_grh) {
+ ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh,
+ sizeof(struct ib_grh));
+ wc.wc_flags |= IB_WC_GRH;
+ } else
+ ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh));
+ ipath_copy_sge(&qp->r_sge, data,
+ wc.byte_len - sizeof(struct ib_grh));
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = IB_WC_RECV;
+ wc.vendor_err = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = src_qp;
+ /* XXX do we know which pkey matched? Only needed for GSI. */
+ wc.pkey_index = 0;
+ wc.slid = be16_to_cpu(hdr->lrh[3]);
+ wc.sl = (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF;
+ dlid = be16_to_cpu(hdr->lrh[1]);
+ /*
+ * Save the LMC lower bits if the destination LID is a unicast LID.
+ */
+ wc.dlid_path_bits = dlid >= IPS_MULTICAST_LID_BASE ? 0 :
+ dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+ (ohdr->bth[0] &
+ __constant_cpu_to_be32(1 << 23)) != 0);
+
+bail:;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
new file mode 100644
index 000000000000..2bb08afc86d0
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/mm.h>
+#include <linux/device.h>
+
+#include "ipath_kernel.h"
+
+static void __ipath_release_user_pages(struct page **p, size_t num_pages,
+ int dirty)
+{
+ size_t i;
+
+ for (i = 0; i < num_pages; i++) {
+ ipath_cdbg(MM, "%lu/%lu put_page %p\n", (unsigned long) i,
+ (unsigned long) num_pages, p[i]);
+ if (dirty)
+ set_page_dirty_lock(p[i]);
+ put_page(p[i]);
+ }
+}
+
+/* call with current->mm->mmap_sem held */
+static int __get_user_pages(unsigned long start_page, size_t num_pages,
+ struct page **p, struct vm_area_struct **vma)
+{
+ unsigned long lock_limit;
+ size_t got;
+ int ret;
+
+#if 0
+ /*
+ * XXX - causes MPI programs to fail, haven't had time to check
+ * yet
+ */
+ if (!capable(CAP_IPC_LOCK)) {
+ ret = -EPERM;
+ goto bail;
+ }
+#endif
+
+ lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >>
+ PAGE_SHIFT;
+
+ if (num_pages > lock_limit) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ ipath_cdbg(VERBOSE, "pin %lx pages from vaddr %lx\n",
+ (unsigned long) num_pages, start_page);
+
+ for (got = 0; got < num_pages; got += ret) {
+ ret = get_user_pages(current, current->mm,
+ start_page + got * PAGE_SIZE,
+ num_pages - got, 1, 1,
+ p + got, vma);
+ if (ret < 0)
+ goto bail_release;
+ }
+
+ current->mm->locked_vm += num_pages;
+
+ ret = 0;
+ goto bail;
+
+bail_release:
+ __ipath_release_user_pages(p, got, 0);
+bail:
+ return ret;
+}
+
+/**
+ * ipath_get_user_pages - lock user pages into memory
+ * @start_page: the start page
+ * @num_pages: the number of pages
+ * @p: the output page structures
+ *
+ * This function takes a given start page (page aligned user virtual
+ * address) and pins it and the following specified number of pages. For
+ * now, num_pages is always 1, but that will probably change at some point
+ * (because caller is doing expected sends on a single virtually contiguous
+ * buffer, so we can do all pages at once).
+ */
+int ipath_get_user_pages(unsigned long start_page, size_t num_pages,
+ struct page **p)
+{
+ int ret;
+
+ down_write(&current->mm->mmap_sem);
+
+ ret = __get_user_pages(start_page, num_pages, p, NULL);
+
+ up_write(&current->mm->mmap_sem);
+
+ return ret;
+}
+
+/**
+ * ipath_get_user_pages_nocopy - lock a single page for I/O and mark shared
+ * @start_page: the page to lock
+ * @p: the output page structure
+ *
+ * This is similar to ipath_get_user_pages, but it's always one page, and we
+ * mark the page as locked for I/O, and shared. This is used for the user
+ * process page that contains the destination address for the rcvhdrq tail
+ * update, so we need to have the vma. If we don't do this, the page can be
+ * taken away from us on fork, even if the child never touches it, and then
+ * the user process never sees the tail register updates.
+ */
+int ipath_get_user_pages_nocopy(unsigned long page, struct page **p)
+{
+ struct vm_area_struct *vma;
+ int ret;
+
+ down_write(&current->mm->mmap_sem);
+
+ ret = __get_user_pages(page, 1, p, &vma);
+
+ up_write(&current->mm->mmap_sem);
+
+ return ret;
+}
+
+void ipath_release_user_pages(struct page **p, size_t num_pages)
+{
+ down_write(&current->mm->mmap_sem);
+
+ __ipath_release_user_pages(p, num_pages, 1);
+
+ current->mm->locked_vm -= num_pages;
+
+ up_write(&current->mm->mmap_sem);
+}
+
+struct ipath_user_pages_work {
+ struct work_struct work;
+ struct mm_struct *mm;
+ unsigned long num_pages;
+};
+
+static void user_pages_account(void *ptr)
+{
+ struct ipath_user_pages_work *work = ptr;
+
+ down_write(&work->mm->mmap_sem);
+ work->mm->locked_vm -= work->num_pages;
+ up_write(&work->mm->mmap_sem);
+ mmput(work->mm);
+ kfree(work);
+}
+
+void ipath_release_user_pages_on_close(struct page **p, size_t num_pages)
+{
+ struct ipath_user_pages_work *work;
+ struct mm_struct *mm;
+
+ __ipath_release_user_pages(p, num_pages, 1);
+
+ mm = get_task_mm(current);
+ if (!mm)
+ goto bail;
+
+ work = kmalloc(sizeof(*work), GFP_KERNEL);
+ if (!work)
+ goto bail_mm;
+
+ goto bail;
+
+ INIT_WORK(&work->work, user_pages_account, work);
+ work->mm = mm;
+ work->num_pages = num_pages;
+
+bail_mm:
+ mmput(mm);
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
new file mode 100644
index 000000000000..8d2558a01f35
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -0,0 +1,1222 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_mad.h>
+#include <rdma/ib_user_verbs.h>
+#include <linux/utsname.h>
+
+#include "ipath_kernel.h"
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* Not static, because we don't want the compiler removing it */
+const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR;
+
+static unsigned int ib_ipath_qp_table_size = 251;
+module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO);
+MODULE_PARM_DESC(qp_table_size, "QP table size");
+
+unsigned int ib_ipath_lkey_table_size = 12;
+module_param_named(lkey_table_size, ib_ipath_lkey_table_size, uint,
+ S_IRUGO);
+MODULE_PARM_DESC(lkey_table_size,
+ "LKEY table size in bits (2^n, 1 <= n <= 23)");
+
+unsigned int ib_ipath_debug; /* debug mask */
+module_param_named(debug, ib_ipath_debug, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "Verbs debug mask");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("PathScale <support@pathscale.com>");
+MODULE_DESCRIPTION("Pathscale InfiniPath driver");
+
+const int ib_ipath_state_ops[IB_QPS_ERR + 1] = {
+ [IB_QPS_RESET] = 0,
+ [IB_QPS_INIT] = IPATH_POST_RECV_OK,
+ [IB_QPS_RTR] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK,
+ [IB_QPS_RTS] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK |
+ IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK,
+ [IB_QPS_SQD] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK |
+ IPATH_POST_SEND_OK,
+ [IB_QPS_SQE] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK,
+ [IB_QPS_ERR] = 0,
+};
+
+/*
+ * Translate ib_wr_opcode into ib_wc_opcode.
+ */
+const enum ib_wc_opcode ib_ipath_wc_opcode[] = {
+ [IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE,
+ [IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE,
+ [IB_WR_SEND] = IB_WC_SEND,
+ [IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
+ [IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
+ [IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
+ [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD
+};
+
+/*
+ * System image GUID.
+ */
+static __be64 sys_image_guid;
+
+/**
+ * ipath_copy_sge - copy data to SGE memory
+ * @ss: the SGE state
+ * @data: the data to copy
+ * @length: the length of the data
+ */
+void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length)
+{
+ struct ipath_sge *sge = &ss->sge;
+
+ while (length) {
+ u32 len = sge->length;
+
+ BUG_ON(len == 0);
+ if (len > length)
+ len = length;
+ memcpy(sge->vaddr, data, len);
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ data += len;
+ length -= len;
+ }
+}
+
+/**
+ * ipath_skip_sge - skip over SGE memory - XXX almost dup of prev func
+ * @ss: the SGE state
+ * @length: the number of bytes to skip
+ */
+void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
+{
+ struct ipath_sge *sge = &ss->sge;
+
+ while (length > sge->sge_length) {
+ length -= sge->sge_length;
+ ss->sge = *ss->sg_list++;
+ }
+ while (length) {
+ u32 len = sge->length;
+
+ BUG_ON(len == 0);
+ if (len > length)
+ len = length;
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ length -= len;
+ }
+}
+
+/**
+ * ipath_post_send - post a send on a QP
+ * @ibqp: the QP to post the send on
+ * @wr: the list of work requests to post
+ * @bad_wr: the first bad WR is put here
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ int err = 0;
+
+ /* Check that state is OK to post send. */
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK)) {
+ *bad_wr = wr;
+ err = -EINVAL;
+ goto bail;
+ }
+
+ for (; wr; wr = wr->next) {
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_UC:
+ case IB_QPT_RC:
+ err = ipath_post_rc_send(qp, wr);
+ break;
+
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ err = ipath_post_ud_send(qp, wr);
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+ if (err) {
+ *bad_wr = wr;
+ break;
+ }
+ }
+
+bail:
+ return err;
+}
+
+/**
+ * ipath_post_receive - post a receive on a QP
+ * @ibqp: the QP to post the receive on
+ * @wr: the WR to post
+ * @bad_wr: the first bad WR is put here
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ unsigned long flags;
+ int ret;
+
+ /* Check that state is OK to post receive. */
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK)) {
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ for (; wr; wr = wr->next) {
+ struct ipath_rwqe *wqe;
+ u32 next;
+ int i, j;
+
+ if (wr->num_sge > qp->r_rq.max_sge) {
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ next = qp->r_rq.head + 1;
+ if (next >= qp->r_rq.size)
+ next = 0;
+ if (next == qp->r_rq.tail) {
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ wqe = get_rwqe_ptr(&qp->r_rq, qp->r_rq.head);
+ wqe->wr_id = wr->wr_id;
+ wqe->sg_list[0].mr = NULL;
+ wqe->sg_list[0].vaddr = NULL;
+ wqe->sg_list[0].length = 0;
+ wqe->sg_list[0].sge_length = 0;
+ wqe->length = 0;
+ for (i = 0, j = 0; i < wr->num_sge; i++) {
+ /* Check LKEY */
+ if (to_ipd(qp->ibqp.pd)->user &&
+ wr->sg_list[i].lkey == 0) {
+ spin_unlock_irqrestore(&qp->r_rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(
+ &to_idev(qp->ibqp.device)->lk_table,
+ &wqe->sg_list[j], &wr->sg_list[i],
+ IB_ACCESS_LOCAL_WRITE)) {
+ spin_unlock_irqrestore(&qp->r_rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ wqe->length += wr->sg_list[i].length;
+ j++;
+ }
+ wqe->num_sge = j;
+ qp->r_rq.head = next;
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_qp_rcv - processing an incoming packet on a QP
+ * @dev: the device the packet came on
+ * @hdr: the packet header
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP the packet came on
+ *
+ * This is called from ipath_ib_rcv() to process an incoming packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+static void ipath_qp_rcv(struct ipath_ibdev *dev,
+ struct ipath_ib_header *hdr, int has_grh,
+ void *data, u32 tlen, struct ipath_qp *qp)
+{
+ /* Check for valid receive state. */
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) {
+ dev->n_pkt_drops++;
+ return;
+ }
+
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ ipath_ud_rcv(dev, hdr, has_grh, data, tlen, qp);
+ break;
+
+ case IB_QPT_RC:
+ ipath_rc_rcv(dev, hdr, has_grh, data, tlen, qp);
+ break;
+
+ case IB_QPT_UC:
+ ipath_uc_rcv(dev, hdr, has_grh, data, tlen, qp);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * ipath_ib_rcv - process and incoming packet
+ * @arg: the device pointer
+ * @rhdr: the header of the packet
+ * @data: the packet data
+ * @tlen: the packet length
+ *
+ * This is called from ipath_kreceive() to process an incoming packet at
+ * interrupt level. Tlen is the length of the header + data + CRC in bytes.
+ */
+static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ipath_ib_header *hdr = rhdr;
+ struct ipath_other_headers *ohdr;
+ struct ipath_qp *qp;
+ u32 qp_num;
+ int lnh;
+ u8 opcode;
+ u16 lid;
+
+ if (unlikely(dev == NULL))
+ goto bail;
+
+ if (unlikely(tlen < 24)) { /* LRH+BTH+CRC */
+ dev->rcv_errors++;
+ goto bail;
+ }
+
+ /* Check for a valid destination LID (see ch. 7.11.1). */
+ lid = be16_to_cpu(hdr->lrh[1]);
+ if (lid < IPS_MULTICAST_LID_BASE) {
+ lid &= ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ if (unlikely(lid != ipath_layer_get_lid(dev->dd))) {
+ dev->rcv_errors++;
+ goto bail;
+ }
+ }
+
+ /* Check for GRH */
+ lnh = be16_to_cpu(hdr->lrh[0]) & 3;
+ if (lnh == IPS_LRH_BTH)
+ ohdr = &hdr->u.oth;
+ else if (lnh == IPS_LRH_GRH)
+ ohdr = &hdr->u.l.oth;
+ else {
+ dev->rcv_errors++;
+ goto bail;
+ }
+
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+ dev->opstats[opcode].n_bytes += tlen;
+ dev->opstats[opcode].n_packets++;
+
+ /* Get the destination QP number. */
+ qp_num = be32_to_cpu(ohdr->bth[1]) & IPS_QPN_MASK;
+ if (qp_num == IPS_MULTICAST_QPN) {
+ struct ipath_mcast *mcast;
+ struct ipath_mcast_qp *p;
+
+ mcast = ipath_mcast_find(&hdr->u.l.grh.dgid);
+ if (mcast == NULL) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ dev->n_multicast_rcv++;
+ list_for_each_entry_rcu(p, &mcast->qp_list, list)
+ ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,
+ tlen, p->qp);
+ /*
+ * Notify ipath_multicast_detach() if it is waiting for us
+ * to finish.
+ */
+ if (atomic_dec_return(&mcast->refcount) <= 1)
+ wake_up(&mcast->wait);
+ } else {
+ qp = ipath_lookup_qpn(&dev->qp_table, qp_num);
+ if (qp) {
+ dev->n_unicast_rcv++;
+ ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,
+ tlen, qp);
+ /*
+ * Notify ipath_destroy_qp() if it is waiting
+ * for us to finish.
+ */
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+ } else
+ dev->n_pkt_drops++;
+ }
+
+bail:;
+}
+
+/**
+ * ipath_ib_timer - verbs timer
+ * @arg: the device pointer
+ *
+ * This is called from ipath_do_rcv_timer() at interrupt level to check for
+ * QPs which need retransmits and to collect performance numbers.
+ */
+static void ipath_ib_timer(void *arg)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ipath_qp *resend = NULL;
+ struct ipath_qp *rnr = NULL;
+ struct list_head *last;
+ struct ipath_qp *qp;
+ unsigned long flags;
+
+ if (dev == NULL)
+ return;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ /* Start filling the next pending queue. */
+ if (++dev->pending_index >= ARRAY_SIZE(dev->pending))
+ dev->pending_index = 0;
+ /* Save any requests still in the new queue, they have timed out. */
+ last = &dev->pending[dev->pending_index];
+ while (!list_empty(last)) {
+ qp = list_entry(last->next, struct ipath_qp, timerwait);
+ if (last->next == LIST_POISON1 ||
+ last->next != &qp->timerwait ||
+ qp->timerwait.prev != last) {
+ INIT_LIST_HEAD(last);
+ } else {
+ list_del(&qp->timerwait);
+ qp->timerwait.prev = (struct list_head *) resend;
+ resend = qp;
+ atomic_inc(&qp->refcount);
+ }
+ }
+ last = &dev->rnrwait;
+ if (!list_empty(last)) {
+ qp = list_entry(last->next, struct ipath_qp, timerwait);
+ if (--qp->s_rnr_timeout == 0) {
+ do {
+ if (last->next == LIST_POISON1 ||
+ last->next != &qp->timerwait ||
+ qp->timerwait.prev != last) {
+ INIT_LIST_HEAD(last);
+ break;
+ }
+ list_del(&qp->timerwait);
+ qp->timerwait.prev =
+ (struct list_head *) rnr;
+ rnr = qp;
+ if (list_empty(last))
+ break;
+ qp = list_entry(last->next, struct ipath_qp,
+ timerwait);
+ } while (qp->s_rnr_timeout == 0);
+ }
+ }
+ /*
+ * We should only be in the started state if pma_sample_start != 0
+ */
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_STARTED &&
+ --dev->pma_sample_start == 0) {
+ dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_RUNNING;
+ ipath_layer_snapshot_counters(dev->dd, &dev->ipath_sword,
+ &dev->ipath_rword,
+ &dev->ipath_spkts,
+ &dev->ipath_rpkts,
+ &dev->ipath_xmit_wait);
+ }
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_RUNNING) {
+ if (dev->pma_sample_interval == 0) {
+ u64 ta, tb, tc, td, te;
+
+ dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_DONE;
+ ipath_layer_snapshot_counters(dev->dd, &ta, &tb,
+ &tc, &td, &te);
+
+ dev->ipath_sword = ta - dev->ipath_sword;
+ dev->ipath_rword = tb - dev->ipath_rword;
+ dev->ipath_spkts = tc - dev->ipath_spkts;
+ dev->ipath_rpkts = td - dev->ipath_rpkts;
+ dev->ipath_xmit_wait = te - dev->ipath_xmit_wait;
+ }
+ else
+ dev->pma_sample_interval--;
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ /* XXX What if timer fires again while this is running? */
+ for (qp = resend; qp != NULL;
+ qp = (struct ipath_qp *) qp->timerwait.prev) {
+ struct ib_wc wc;
+
+ spin_lock_irqsave(&qp->s_lock, flags);
+ if (qp->s_last != qp->s_tail && qp->state == IB_QPS_RTS) {
+ dev->n_timeouts++;
+ ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ }
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ /* Notify ipath_destroy_qp() if it is waiting. */
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+ }
+ for (qp = rnr; qp != NULL;
+ qp = (struct ipath_qp *) qp->timerwait.prev)
+ tasklet_hi_schedule(&qp->s_task);
+}
+
+/**
+ * ipath_ib_piobufavail - callback when a PIO buffer is available
+ * @arg: the device pointer
+ *
+ * This is called from ipath_intr() at interrupt level when a PIO buffer is
+ * available after ipath_verbs_send() returned an error that no buffers were
+ * available. Return 0 if we consumed all the PIO buffers and we still have
+ * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
+ * return one).
+ */
+static int ipath_ib_piobufavail(void *arg)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ipath_qp *qp;
+ unsigned long flags;
+
+ if (dev == NULL)
+ goto bail;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ while (!list_empty(&dev->piowait)) {
+ qp = list_entry(dev->piowait.next, struct ipath_qp,
+ piowait);
+ list_del(&qp->piowait);
+ tasklet_hi_schedule(&qp->s_task);
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+bail:
+ return 1;
+}
+
+static int ipath_query_device(struct ib_device *ibdev,
+ struct ib_device_attr *props)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ u32 vendor, boardrev, majrev, minrev;
+
+ memset(props, 0, sizeof(*props));
+
+ props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
+ IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
+ IB_DEVICE_SYS_IMAGE_GUID;
+ ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+ &majrev, &minrev);
+ props->vendor_id = vendor;
+ props->vendor_part_id = boardrev;
+ props->hw_ver = boardrev << 16 | majrev << 8 | minrev;
+
+ props->sys_image_guid = dev->sys_image_guid;
+
+ props->max_mr_size = ~0ull;
+ props->max_qp = 0xffff;
+ props->max_qp_wr = 0xffff;
+ props->max_sge = 255;
+ props->max_cq = 0xffff;
+ props->max_cqe = 0xffff;
+ props->max_mr = 0xffff;
+ props->max_pd = 0xffff;
+ props->max_qp_rd_atom = 1;
+ props->max_qp_init_rd_atom = 1;
+ /* props->max_res_rd_atom */
+ props->max_srq = 0xffff;
+ props->max_srq_wr = 0xffff;
+ props->max_srq_sge = 255;
+ /* props->local_ca_ack_delay */
+ props->atomic_cap = IB_ATOMIC_HCA;
+ props->max_pkeys = ipath_layer_get_npkeys(dev->dd);
+ props->max_mcast_grp = 0xffff;
+ props->max_mcast_qp_attach = 0xffff;
+ props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
+ props->max_mcast_grp;
+
+ return 0;
+}
+
+const u8 ipath_cvt_physportstate[16] = {
+ [INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,
+ [INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,
+ [INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,
+ [INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,
+ [INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,
+ [INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,
+ [INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,
+};
+
+static int ipath_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ enum ib_mtu mtu;
+ u16 lid = ipath_layer_get_lid(dev->dd);
+ u64 ibcstat;
+
+ memset(props, 0, sizeof(*props));
+ props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+ props->lmc = dev->mkeyprot_resv_lmc & 7;
+ props->sm_lid = dev->sm_lid;
+ props->sm_sl = dev->sm_sl;
+ ibcstat = ipath_layer_get_lastibcstat(dev->dd);
+ props->state = ((ibcstat >> 4) & 0x3) + 1;
+ /* See phys_state_show() */
+ props->phys_state = ipath_cvt_physportstate[
+ ipath_layer_get_lastibcstat(dev->dd) & 0xf];
+ props->port_cap_flags = dev->port_cap_flags;
+ props->gid_tbl_len = 1;
+ props->max_msg_sz = 4096;
+ props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd);
+ props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) -
+ dev->n_pkey_violations;
+ props->qkey_viol_cntr = dev->qkey_violations;
+ props->active_width = IB_WIDTH_4X;
+ /* See rate_show() */
+ props->active_speed = 1; /* Regular 10Mbs speed. */
+ props->max_vl_num = 1; /* VLCap = VL0 */
+ props->init_type_reply = 0;
+
+ props->max_mtu = IB_MTU_4096;
+ switch (ipath_layer_get_ibmtu(dev->dd)) {
+ case 4096:
+ mtu = IB_MTU_4096;
+ break;
+ case 2048:
+ mtu = IB_MTU_2048;
+ break;
+ case 1024:
+ mtu = IB_MTU_1024;
+ break;
+ case 512:
+ mtu = IB_MTU_512;
+ break;
+ case 256:
+ mtu = IB_MTU_256;
+ break;
+ default:
+ mtu = IB_MTU_2048;
+ }
+ props->active_mtu = mtu;
+ props->subnet_timeout = dev->subnet_timeout;
+
+ return 0;
+}
+
+static int ipath_modify_device(struct ib_device *device,
+ int device_modify_mask,
+ struct ib_device_modify *device_modify)
+{
+ int ret;
+
+ if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID |
+ IB_DEVICE_MODIFY_NODE_DESC)) {
+ ret = -EOPNOTSUPP;
+ goto bail;
+ }
+
+ if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC)
+ memcpy(device->node_desc, device_modify->node_desc, 64);
+
+ if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID)
+ to_idev(device)->sys_image_guid =
+ cpu_to_be64(device_modify->sys_image_guid);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int ipath_modify_port(struct ib_device *ibdev,
+ u8 port, int port_modify_mask,
+ struct ib_port_modify *props)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+
+ dev->port_cap_flags |= props->set_port_cap_mask;
+ dev->port_cap_flags &= ~props->clr_port_cap_mask;
+ if (port_modify_mask & IB_PORT_SHUTDOWN)
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
+ if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR)
+ dev->qkey_violations = 0;
+ return 0;
+}
+
+static int ipath_query_gid(struct ib_device *ibdev, u8 port,
+ int index, union ib_gid *gid)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ if (index >= 1) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ gid->global.subnet_prefix = dev->gid_prefix;
+ gid->global.interface_id = ipath_layer_get_guid(dev->dd);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct ipath_pd *pd;
+ struct ib_pd *ret;
+
+ pd = kmalloc(sizeof *pd, GFP_KERNEL);
+ if (!pd) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /* ib_alloc_pd() will initialize pd->ibpd. */
+ pd->user = udata != NULL;
+
+ ret = &pd->ibpd;
+
+bail:
+ return ret;
+}
+
+static int ipath_dealloc_pd(struct ib_pd *ibpd)
+{
+ struct ipath_pd *pd = to_ipd(ibpd);
+
+ kfree(pd);
+
+ return 0;
+}
+
+/**
+ * ipath_create_ah - create an address handle
+ * @pd: the protection domain
+ * @ah_attr: the attributes of the AH
+ *
+ * This may be called from interrupt context.
+ */
+static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
+ struct ib_ah_attr *ah_attr)
+{
+ struct ipath_ah *ah;
+ struct ib_ah *ret;
+
+ /* A multicast address requires a GRH (see ch. 8.4.1). */
+ if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&
+ ah_attr->dlid != IPS_PERMISSIVE_LID &&
+ !(ah_attr->ah_flags & IB_AH_GRH)) {
+ ret = ERR_PTR(-EINVAL);
+ goto bail;
+ }
+
+ ah = kmalloc(sizeof *ah, GFP_ATOMIC);
+ if (!ah) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /* ib_create_ah() will initialize ah->ibah. */
+ ah->attr = *ah_attr;
+
+ ret = &ah->ibah;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_destroy_ah - destroy an address handle
+ * @ibah: the AH to destroy
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_destroy_ah(struct ib_ah *ibah)
+{
+ struct ipath_ah *ah = to_iah(ibah);
+
+ kfree(ah);
+
+ return 0;
+}
+
+static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
+{
+ struct ipath_ah *ah = to_iah(ibah);
+
+ *ah_attr = ah->attr;
+
+ return 0;
+}
+
+static int ipath_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+ u16 *pkey)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ if (index >= ipath_layer_get_npkeys(dev->dd)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ *pkey = ipath_layer_get_pkey(dev->dd, index);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+
+/**
+ * ipath_alloc_ucontext - allocate a ucontest
+ * @ibdev: the infiniband device
+ * @udata: not used by the InfiniPath driver
+ */
+
+static struct ib_ucontext *ipath_alloc_ucontext(struct ib_device *ibdev,
+ struct ib_udata *udata)
+{
+ struct ipath_ucontext *context;
+ struct ib_ucontext *ret;
+
+ context = kmalloc(sizeof *context, GFP_KERNEL);
+ if (!context) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ ret = &context->ibucontext;
+
+bail:
+ return ret;
+}
+
+static int ipath_dealloc_ucontext(struct ib_ucontext *context)
+{
+ kfree(to_iucontext(context));
+ return 0;
+}
+
+static int ipath_verbs_register_sysfs(struct ib_device *dev);
+
+/**
+ * ipath_register_ib_device - register our device with the infiniband core
+ * @unit: the device number to register
+ * @dd: the device data structure
+ * Return the allocated ipath_ibdev pointer or NULL on error.
+ */
+static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
+{
+ struct ipath_ibdev *idev;
+ struct ib_device *dev;
+ int ret;
+
+ idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
+ if (idev == NULL)
+ goto bail;
+
+ dev = &idev->ibdev;
+
+ /* Only need to initialize non-zero fields. */
+ spin_lock_init(&idev->qp_table.lock);
+ spin_lock_init(&idev->lk_table.lock);
+ idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+ /* Set the prefix to the default value (see ch. 4.1.1) */
+ idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL);
+
+ ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size);
+ if (ret)
+ goto err_qp;
+
+ /*
+ * The top ib_ipath_lkey_table_size bits are used to index the
+ * table. The lower 8 bits can be owned by the user (copied from
+ * the LKEY). The remaining bits act as a generation number or tag.
+ */
+ idev->lk_table.max = 1 << ib_ipath_lkey_table_size;
+ idev->lk_table.table = kzalloc(idev->lk_table.max *
+ sizeof(*idev->lk_table.table),
+ GFP_KERNEL);
+ if (idev->lk_table.table == NULL) {
+ ret = -ENOMEM;
+ goto err_lk;
+ }
+ spin_lock_init(&idev->pending_lock);
+ INIT_LIST_HEAD(&idev->pending[0]);
+ INIT_LIST_HEAD(&idev->pending[1]);
+ INIT_LIST_HEAD(&idev->pending[2]);
+ INIT_LIST_HEAD(&idev->piowait);
+ INIT_LIST_HEAD(&idev->rnrwait);
+ idev->pending_index = 0;
+ idev->port_cap_flags =
+ IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP;
+ idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA;
+ idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA;
+ idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS;
+ idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS;
+ idev->pma_counter_select[5] = IB_PMA_PORT_XMIT_WAIT;
+ idev->link_width_enabled = 3; /* 1x or 4x */
+
+ /*
+ * The system image GUID is supposed to be the same for all
+ * IB HCAs in a single system but since there can be other
+ * device types in the system, we can't be sure this is unique.
+ */
+ if (!sys_image_guid)
+ sys_image_guid = ipath_layer_get_guid(dd);
+ idev->sys_image_guid = sys_image_guid;
+ idev->ib_unit = unit;
+ idev->dd = dd;
+
+ strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX);
+ dev->node_guid = ipath_layer_get_guid(dd);
+ dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION;
+ dev->uverbs_cmd_mask =
+ (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
+ (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
+ (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_AH) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_AH) |
+ (1ull << IB_USER_VERBS_CMD_REG_MR) |
+ (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
+ (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
+ (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
+ (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
+ (1ull << IB_USER_VERBS_CMD_POST_SEND) |
+ (1ull << IB_USER_VERBS_CMD_POST_RECV) |
+ (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) |
+ (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
+ dev->node_type = IB_NODE_CA;
+ dev->phys_port_cnt = 1;
+ dev->dma_device = ipath_layer_get_device(dd);
+ dev->class_dev.dev = dev->dma_device;
+ dev->query_device = ipath_query_device;
+ dev->modify_device = ipath_modify_device;
+ dev->query_port = ipath_query_port;
+ dev->modify_port = ipath_modify_port;
+ dev->query_pkey = ipath_query_pkey;
+ dev->query_gid = ipath_query_gid;
+ dev->alloc_ucontext = ipath_alloc_ucontext;
+ dev->dealloc_ucontext = ipath_dealloc_ucontext;
+ dev->alloc_pd = ipath_alloc_pd;
+ dev->dealloc_pd = ipath_dealloc_pd;
+ dev->create_ah = ipath_create_ah;
+ dev->destroy_ah = ipath_destroy_ah;
+ dev->query_ah = ipath_query_ah;
+ dev->create_srq = ipath_create_srq;
+ dev->modify_srq = ipath_modify_srq;
+ dev->query_srq = ipath_query_srq;
+ dev->destroy_srq = ipath_destroy_srq;
+ dev->create_qp = ipath_create_qp;
+ dev->modify_qp = ipath_modify_qp;
+ dev->query_qp = ipath_query_qp;
+ dev->destroy_qp = ipath_destroy_qp;
+ dev->post_send = ipath_post_send;
+ dev->post_recv = ipath_post_receive;
+ dev->post_srq_recv = ipath_post_srq_receive;
+ dev->create_cq = ipath_create_cq;
+ dev->destroy_cq = ipath_destroy_cq;
+ dev->resize_cq = ipath_resize_cq;
+ dev->poll_cq = ipath_poll_cq;
+ dev->req_notify_cq = ipath_req_notify_cq;
+ dev->get_dma_mr = ipath_get_dma_mr;
+ dev->reg_phys_mr = ipath_reg_phys_mr;
+ dev->reg_user_mr = ipath_reg_user_mr;
+ dev->dereg_mr = ipath_dereg_mr;
+ dev->alloc_fmr = ipath_alloc_fmr;
+ dev->map_phys_fmr = ipath_map_phys_fmr;
+ dev->unmap_fmr = ipath_unmap_fmr;
+ dev->dealloc_fmr = ipath_dealloc_fmr;
+ dev->attach_mcast = ipath_multicast_attach;
+ dev->detach_mcast = ipath_multicast_detach;
+ dev->process_mad = ipath_process_mad;
+
+ snprintf(dev->node_desc, sizeof(dev->node_desc),
+ IPATH_IDSTR " %s kernel_SMA", system_utsname.nodename);
+
+ ret = ib_register_device(dev);
+ if (ret)
+ goto err_reg;
+
+ if (ipath_verbs_register_sysfs(dev))
+ goto err_class;
+
+ ipath_layer_enable_timer(dd);
+
+ goto bail;
+
+err_class:
+ ib_unregister_device(dev);
+err_reg:
+ kfree(idev->lk_table.table);
+err_lk:
+ kfree(idev->qp_table.table);
+err_qp:
+ ib_dealloc_device(dev);
+ _VERBS_ERROR("ib_ipath%d cannot register verbs (%d)!\n",
+ unit, -ret);
+ idev = NULL;
+
+bail:
+ return idev;
+}
+
+static void ipath_unregister_ib_device(void *arg)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ib_device *ibdev = &dev->ibdev;
+
+ ipath_layer_disable_timer(dev->dd);
+
+ ib_unregister_device(ibdev);
+
+ if (!list_empty(&dev->pending[0]) ||
+ !list_empty(&dev->pending[1]) ||
+ !list_empty(&dev->pending[2]))
+ _VERBS_ERROR("ipath%d pending list not empty!\n",
+ dev->ib_unit);
+ if (!list_empty(&dev->piowait))
+ _VERBS_ERROR("ipath%d piowait list not empty!\n",
+ dev->ib_unit);
+ if (!list_empty(&dev->rnrwait))
+ _VERBS_ERROR("ipath%d rnrwait list not empty!\n",
+ dev->ib_unit);
+ if (!ipath_mcast_tree_empty())
+ _VERBS_ERROR("ipath%d multicast table memory leak!\n",
+ dev->ib_unit);
+ /*
+ * Note that ipath_unregister_ib_device() can be called before all
+ * the QPs are destroyed!
+ */
+ ipath_free_all_qps(&dev->qp_table);
+ kfree(dev->qp_table.table);
+ kfree(dev->lk_table.table);
+ ib_dealloc_device(ibdev);
+}
+
+static int __init ipath_verbs_init(void)
+{
+ return ipath_verbs_register(ipath_register_ib_device,
+ ipath_unregister_ib_device,
+ ipath_ib_piobufavail, ipath_ib_rcv,
+ ipath_ib_timer);
+}
+
+static void __exit ipath_verbs_cleanup(void)
+{
+ ipath_verbs_unregister();
+}
+
+static ssize_t show_rev(struct class_device *cdev, char *buf)
+{
+ struct ipath_ibdev *dev =
+ container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+ int vendor, boardrev, majrev, minrev;
+
+ ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+ &majrev, &minrev);
+ return sprintf(buf, "%d.%d\n", majrev, minrev);
+}
+
+static ssize_t show_hca(struct class_device *cdev, char *buf)
+{
+ struct ipath_ibdev *dev =
+ container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+ int ret;
+
+ ret = ipath_layer_get_boardname(dev->dd, buf, 128);
+ if (ret < 0)
+ goto bail;
+ strcat(buf, "\n");
+ ret = strlen(buf);
+
+bail:
+ return ret;
+}
+
+static ssize_t show_stats(struct class_device *cdev, char *buf)
+{
+ struct ipath_ibdev *dev =
+ container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+ int i;
+ int len;
+
+ len = sprintf(buf,
+ "RC resends %d\n"
+ "RC QACKs %d\n"
+ "RC ACKs %d\n"
+ "RC SEQ NAKs %d\n"
+ "RC RDMA seq %d\n"
+ "RC RNR NAKs %d\n"
+ "RC OTH NAKs %d\n"
+ "RC timeouts %d\n"
+ "RC RDMA dup %d\n"
+ "piobuf wait %d\n"
+ "no piobuf %d\n"
+ "PKT drops %d\n"
+ "WQE errs %d\n",
+ dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+ dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+ dev->n_other_naks, dev->n_timeouts,
+ dev->n_rdma_dup_busy, dev->n_piowait,
+ dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
+ for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+ const struct ipath_opcode_stats *si = &dev->opstats[i];
+
+ if (!si->n_packets && !si->n_bytes)
+ continue;
+ len += sprintf(buf + len, "%02x %llu/%llu\n", i,
+ (unsigned long long) si->n_packets,
+ (unsigned long long) si->n_bytes);
+ }
+ return len;
+}
+
+static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+
+static struct class_device_attribute *ipath_class_attributes[] = {
+ &class_device_attr_hw_rev,
+ &class_device_attr_hca_type,
+ &class_device_attr_board_id,
+ &class_device_attr_stats
+};
+
+static int ipath_verbs_register_sysfs(struct ib_device *dev)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+ if (class_device_create_file(&dev->class_dev,
+ ipath_class_attributes[i])) {
+ ret = 1;
+ goto bail;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+module_init(ipath_verbs_init);
+module_exit(ipath_verbs_cleanup);
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
new file mode 100644
index 000000000000..fcafbc7c9e71
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -0,0 +1,692 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IPATH_VERBS_H
+#define IPATH_VERBS_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <rdma/ib_pack.h>
+
+#include "ipath_layer.h"
+#include "verbs_debug.h"
+
+#define QPN_MAX (1 << 24)
+#define QPNMAP_ENTRIES (QPN_MAX / PAGE_SIZE / BITS_PER_BYTE)
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IPATH_UVERBS_ABI_VERSION 1
+
+/*
+ * Define an ib_cq_notify value that is not valid so we know when CQ
+ * notifications are armed.
+ */
+#define IB_CQ_NONE (IB_CQ_NEXT_COMP + 1)
+
+#define IB_RNR_NAK 0x20
+#define IB_NAK_PSN_ERROR 0x60
+#define IB_NAK_INVALID_REQUEST 0x61
+#define IB_NAK_REMOTE_ACCESS_ERROR 0x62
+#define IB_NAK_REMOTE_OPERATIONAL_ERROR 0x63
+#define IB_NAK_INVALID_RD_REQUEST 0x64
+
+#define IPATH_POST_SEND_OK 0x01
+#define IPATH_POST_RECV_OK 0x02
+#define IPATH_PROCESS_RECV_OK 0x04
+#define IPATH_PROCESS_SEND_OK 0x08
+
+/* IB Performance Manager status values */
+#define IB_PMA_SAMPLE_STATUS_DONE 0x00
+#define IB_PMA_SAMPLE_STATUS_STARTED 0x01
+#define IB_PMA_SAMPLE_STATUS_RUNNING 0x02
+
+/* Mandatory IB performance counter select values. */
+#define IB_PMA_PORT_XMIT_DATA __constant_htons(0x0001)
+#define IB_PMA_PORT_RCV_DATA __constant_htons(0x0002)
+#define IB_PMA_PORT_XMIT_PKTS __constant_htons(0x0003)
+#define IB_PMA_PORT_RCV_PKTS __constant_htons(0x0004)
+#define IB_PMA_PORT_XMIT_WAIT __constant_htons(0x0005)
+
+struct ib_reth {
+ __be64 vaddr;
+ __be32 rkey;
+ __be32 length;
+} __attribute__ ((packed));
+
+struct ib_atomic_eth {
+ __be64 vaddr;
+ __be32 rkey;
+ __be64 swap_data;
+ __be64 compare_data;
+} __attribute__ ((packed));
+
+struct ipath_other_headers {
+ __be32 bth[3];
+ union {
+ struct {
+ __be32 deth[2];
+ __be32 imm_data;
+ } ud;
+ struct {
+ struct ib_reth reth;
+ __be32 imm_data;
+ } rc;
+ struct {
+ __be32 aeth;
+ __be64 atomic_ack_eth;
+ } at;
+ __be32 imm_data;
+ __be32 aeth;
+ struct ib_atomic_eth atomic_eth;
+ } u;
+} __attribute__ ((packed));
+
+/*
+ * Note that UD packets with a GRH header are 8+40+12+8 = 68 bytes
+ * long (72 w/ imm_data). Only the first 56 bytes of the IB header
+ * will be in the eager header buffer. The remaining 12 or 16 bytes
+ * are in the data buffer.
+ */
+struct ipath_ib_header {
+ __be16 lrh[4];
+ union {
+ struct {
+ struct ib_grh grh;
+ struct ipath_other_headers oth;
+ } l;
+ struct ipath_other_headers oth;
+ } u;
+} __attribute__ ((packed));
+
+/*
+ * There is one struct ipath_mcast for each multicast GID.
+ * All attached QPs are then stored as a list of
+ * struct ipath_mcast_qp.
+ */
+struct ipath_mcast_qp {
+ struct list_head list;
+ struct ipath_qp *qp;
+};
+
+struct ipath_mcast {
+ struct rb_node rb_node;
+ union ib_gid mgid;
+ struct list_head qp_list;
+ wait_queue_head_t wait;
+ atomic_t refcount;
+};
+
+/* Memory region */
+struct ipath_mr {
+ struct ib_mr ibmr;
+ struct ipath_mregion mr; /* must be last */
+};
+
+/* Fast memory region */
+struct ipath_fmr {
+ struct ib_fmr ibfmr;
+ u8 page_shift;
+ struct ipath_mregion mr; /* must be last */
+};
+
+/* Protection domain */
+struct ipath_pd {
+ struct ib_pd ibpd;
+ int user; /* non-zero if created from user space */
+};
+
+/* Address Handle */
+struct ipath_ah {
+ struct ib_ah ibah;
+ struct ib_ah_attr attr;
+};
+
+/*
+ * Quick description of our CQ/QP locking scheme:
+ *
+ * We have one global lock that protects dev->cq/qp_table. Each
+ * struct ipath_cq/qp also has its own lock. An individual qp lock
+ * may be taken inside of an individual cq lock. Both cqs attached to
+ * a qp may be locked, with the send cq locked first. No other
+ * nesting should be done.
+ *
+ * Each struct ipath_cq/qp also has an atomic_t ref count. The
+ * pointer from the cq/qp_table to the struct counts as one reference.
+ * This reference also is good for access through the consumer API, so
+ * modifying the CQ/QP etc doesn't need to take another reference.
+ * Access because of a completion being polled does need a reference.
+ *
+ * Finally, each struct ipath_cq/qp has a wait_queue_head_t for the
+ * destroy function to sleep on.
+ *
+ * This means that access from the consumer API requires nothing but
+ * taking the struct's lock.
+ *
+ * Access because of a completion event should go as follows:
+ * - lock cq/qp_table and look up struct
+ * - increment ref count in struct
+ * - drop cq/qp_table lock
+ * - lock struct, do your thing, and unlock struct
+ * - decrement ref count; if zero, wake up waiters
+ *
+ * To destroy a CQ/QP, we can do the following:
+ * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock
+ * - decrement ref count
+ * - wait_event until ref count is zero
+ *
+ * It is the consumer's responsibilty to make sure that no QP
+ * operations (WQE posting or state modification) are pending when the
+ * QP is destroyed. Also, the consumer must make sure that calls to
+ * qp_modify are serialized.
+ *
+ * Possible optimizations (wait for profile data to see if/where we
+ * have locks bouncing between CPUs):
+ * - split cq/qp table lock into n separate (cache-aligned) locks,
+ * indexed (say) by the page in the table
+ */
+
+struct ipath_cq {
+ struct ib_cq ibcq;
+ struct tasklet_struct comptask;
+ spinlock_t lock;
+ u8 notify;
+ u8 triggered;
+ u32 head; /* new records added to the head */
+ u32 tail; /* poll_cq() reads from here. */
+ struct ib_wc *queue; /* this is actually ibcq.cqe + 1 */
+};
+
+/*
+ * Send work request queue entry.
+ * The size of the sg_list is determined when the QP is created and stored
+ * in qp->s_max_sge.
+ */
+struct ipath_swqe {
+ struct ib_send_wr wr; /* don't use wr.sg_list */
+ u32 psn; /* first packet sequence number */
+ u32 lpsn; /* last packet sequence number */
+ u32 ssn; /* send sequence number */
+ u32 length; /* total length of data in sg_list */
+ struct ipath_sge sg_list[0];
+};
+
+/*
+ * Receive work request queue entry.
+ * The size of the sg_list is determined when the QP is created and stored
+ * in qp->r_max_sge.
+ */
+struct ipath_rwqe {
+ u64 wr_id;
+ u32 length; /* total length of data in sg_list */
+ u8 num_sge;
+ struct ipath_sge sg_list[0];
+};
+
+struct ipath_rq {
+ spinlock_t lock;
+ u32 head; /* new work requests posted to the head */
+ u32 tail; /* receives pull requests from here. */
+ u32 size; /* size of RWQE array */
+ u8 max_sge;
+ struct ipath_rwqe *wq; /* RWQE array */
+};
+
+struct ipath_srq {
+ struct ib_srq ibsrq;
+ struct ipath_rq rq;
+ /* send signal when number of RWQEs < limit */
+ u32 limit;
+};
+
+/*
+ * Variables prefixed with s_ are for the requester (sender).
+ * Variables prefixed with r_ are for the responder (receiver).
+ * Variables prefixed with ack_ are for responder replies.
+ *
+ * Common variables are protected by both r_rq.lock and s_lock in that order
+ * which only happens in modify_qp() or changing the QP 'state'.
+ */
+struct ipath_qp {
+ struct ib_qp ibqp;
+ struct ipath_qp *next; /* link list for QPN hash table */
+ struct list_head piowait; /* link for wait PIO buf */
+ struct list_head timerwait; /* link for waiting for timeouts */
+ struct ib_ah_attr remote_ah_attr;
+ struct ipath_ib_header s_hdr; /* next packet header to send */
+ atomic_t refcount;
+ wait_queue_head_t wait;
+ struct tasklet_struct s_task;
+ struct ipath_sge_state *s_cur_sge;
+ struct ipath_sge_state s_sge; /* current send request data */
+ /* current RDMA read send data */
+ struct ipath_sge_state s_rdma_sge;
+ struct ipath_sge_state r_sge; /* current receive data */
+ spinlock_t s_lock;
+ unsigned long s_flags;
+ u32 s_hdrwords; /* size of s_hdr in 32 bit words */
+ u32 s_cur_size; /* size of send packet in bytes */
+ u32 s_len; /* total length of s_sge */
+ u32 s_rdma_len; /* total length of s_rdma_sge */
+ u32 s_next_psn; /* PSN for next request */
+ u32 s_last_psn; /* last response PSN processed */
+ u32 s_psn; /* current packet sequence number */
+ u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */
+ u32 s_ack_psn; /* PSN for next ACK or RDMA_READ */
+ u64 s_ack_atomic; /* data for atomic ACK */
+ u64 r_wr_id; /* ID for current receive WQE */
+ u64 r_atomic_data; /* data for last atomic op */
+ u32 r_atomic_psn; /* PSN of last atomic op */
+ u32 r_len; /* total length of r_sge */
+ u32 r_rcv_len; /* receive data len processed */
+ u32 r_psn; /* expected rcv packet sequence number */
+ u8 state; /* QP state */
+ u8 s_state; /* opcode of last packet sent */
+ u8 s_ack_state; /* opcode of packet to ACK */
+ u8 s_nak_state; /* non-zero if NAK is pending */
+ u8 r_state; /* opcode of last packet received */
+ u8 r_reuse_sge; /* for UC receive errors */
+ u8 r_sge_inx; /* current index into sg_list */
+ u8 s_max_sge; /* size of s_wq->sg_list */
+ u8 qp_access_flags;
+ u8 s_retry_cnt; /* number of times to retry */
+ u8 s_rnr_retry_cnt;
+ u8 s_min_rnr_timer;
+ u8 s_retry; /* requester retry counter */
+ u8 s_rnr_retry; /* requester RNR retry counter */
+ u8 s_pkey_index; /* PKEY index to use */
+ enum ib_mtu path_mtu;
+ atomic_t msn; /* message sequence number */
+ u32 remote_qpn;
+ u32 qkey; /* QKEY for this QP (for UD or RD) */
+ u32 s_size; /* send work queue size */
+ u32 s_head; /* new entries added here */
+ u32 s_tail; /* next entry to process */
+ u32 s_cur; /* current work queue entry */
+ u32 s_last; /* last un-ACK'ed entry */
+ u32 s_ssn; /* SSN of tail entry */
+ u32 s_lsn; /* limit sequence number (credit) */
+ struct ipath_swqe *s_wq; /* send work queue */
+ struct ipath_rq r_rq; /* receive work queue */
+};
+
+/*
+ * Bit definitions for s_flags.
+ */
+#define IPATH_S_BUSY 0
+#define IPATH_S_SIGNAL_REQ_WR 1
+
+/*
+ * Since struct ipath_swqe is not a fixed size, we can't simply index into
+ * struct ipath_qp.s_wq. This function does the array index computation.
+ */
+static inline struct ipath_swqe *get_swqe_ptr(struct ipath_qp *qp,
+ unsigned n)
+{
+ return (struct ipath_swqe *)((char *)qp->s_wq +
+ (sizeof(struct ipath_swqe) +
+ qp->s_max_sge *
+ sizeof(struct ipath_sge)) * n);
+}
+
+/*
+ * Since struct ipath_rwqe is not a fixed size, we can't simply index into
+ * struct ipath_rq.wq. This function does the array index computation.
+ */
+static inline struct ipath_rwqe *get_rwqe_ptr(struct ipath_rq *rq,
+ unsigned n)
+{
+ return (struct ipath_rwqe *)
+ ((char *) rq->wq +
+ (sizeof(struct ipath_rwqe) +
+ rq->max_sge * sizeof(struct ipath_sge)) * n);
+}
+
+/*
+ * QPN-map pages start out as NULL, they get allocated upon
+ * first use and are never deallocated. This way,
+ * large bitmaps are not allocated unless large numbers of QPs are used.
+ */
+struct qpn_map {
+ atomic_t n_free;
+ void *page;
+};
+
+struct ipath_qp_table {
+ spinlock_t lock;
+ u32 last; /* last QP number allocated */
+ u32 max; /* size of the hash table */
+ u32 nmaps; /* size of the map table */
+ struct ipath_qp **table;
+ /* bit map of free numbers */
+ struct qpn_map map[QPNMAP_ENTRIES];
+};
+
+struct ipath_lkey_table {
+ spinlock_t lock;
+ u32 next; /* next unused index (speeds search) */
+ u32 gen; /* generation count */
+ u32 max; /* size of the table */
+ struct ipath_mregion **table;
+};
+
+struct ipath_opcode_stats {
+ u64 n_packets; /* number of packets */
+ u64 n_bytes; /* total number of bytes */
+};
+
+struct ipath_ibdev {
+ struct ib_device ibdev;
+ struct list_head dev_list;
+ struct ipath_devdata *dd;
+ int ib_unit; /* This is the device number */
+ u16 sm_lid; /* in host order */
+ u8 sm_sl;
+ u8 mkeyprot_resv_lmc;
+ /* non-zero when timer is set */
+ unsigned long mkey_lease_timeout;
+
+ /* The following fields are really per port. */
+ struct ipath_qp_table qp_table;
+ struct ipath_lkey_table lk_table;
+ struct list_head pending[3]; /* FIFO of QPs waiting for ACKs */
+ struct list_head piowait; /* list for wait PIO buf */
+ /* list of QPs waiting for RNR timer */
+ struct list_head rnrwait;
+ spinlock_t pending_lock;
+ __be64 sys_image_guid; /* in network order */
+ __be64 gid_prefix; /* in network order */
+ __be64 mkey;
+ u64 ipath_sword; /* total dwords sent (sample result) */
+ u64 ipath_rword; /* total dwords received (sample result) */
+ u64 ipath_spkts; /* total packets sent (sample result) */
+ u64 ipath_rpkts; /* total packets received (sample result) */
+ /* # of ticks no data sent (sample result) */
+ u64 ipath_xmit_wait;
+ u64 rcv_errors; /* # of packets with SW detected rcv errs */
+ u64 n_unicast_xmit; /* total unicast packets sent */
+ u64 n_unicast_rcv; /* total unicast packets received */
+ u64 n_multicast_xmit; /* total multicast packets sent */
+ u64 n_multicast_rcv; /* total multicast packets received */
+ u64 n_symbol_error_counter; /* starting count for PMA */
+ u64 n_link_error_recovery_counter; /* starting count for PMA */
+ u64 n_link_downed_counter; /* starting count for PMA */
+ u64 n_port_rcv_errors; /* starting count for PMA */
+ u64 n_port_rcv_remphys_errors; /* starting count for PMA */
+ u64 n_port_xmit_discards; /* starting count for PMA */
+ u64 n_port_xmit_data; /* starting count for PMA */
+ u64 n_port_rcv_data; /* starting count for PMA */
+ u64 n_port_xmit_packets; /* starting count for PMA */
+ u64 n_port_rcv_packets; /* starting count for PMA */
+ u32 n_pkey_violations; /* starting count for PMA */
+ u32 n_rc_resends;
+ u32 n_rc_acks;
+ u32 n_rc_qacks;
+ u32 n_seq_naks;
+ u32 n_rdma_seq;
+ u32 n_rnr_naks;
+ u32 n_other_naks;
+ u32 n_timeouts;
+ u32 n_pkt_drops;
+ u32 n_wqe_errs;
+ u32 n_rdma_dup_busy;
+ u32 n_piowait;
+ u32 n_no_piobuf;
+ u32 port_cap_flags;
+ u32 pma_sample_start;
+ u32 pma_sample_interval;
+ __be16 pma_counter_select[5];
+ u16 pma_tag;
+ u16 qkey_violations;
+ u16 mkey_violations;
+ u16 mkey_lease_period;
+ u16 pending_index; /* which pending queue is active */
+ u8 pma_sample_status;
+ u8 subnet_timeout;
+ u8 link_width_enabled;
+ u8 vl_high_limit;
+ struct ipath_opcode_stats opstats[128];
+};
+
+struct ipath_ucontext {
+ struct ib_ucontext ibucontext;
+};
+
+static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
+{
+ return container_of(ibmr, struct ipath_mr, ibmr);
+}
+
+static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr)
+{
+ return container_of(ibfmr, struct ipath_fmr, ibfmr);
+}
+
+static inline struct ipath_pd *to_ipd(struct ib_pd *ibpd)
+{
+ return container_of(ibpd, struct ipath_pd, ibpd);
+}
+
+static inline struct ipath_ah *to_iah(struct ib_ah *ibah)
+{
+ return container_of(ibah, struct ipath_ah, ibah);
+}
+
+static inline struct ipath_cq *to_icq(struct ib_cq *ibcq)
+{
+ return container_of(ibcq, struct ipath_cq, ibcq);
+}
+
+static inline struct ipath_srq *to_isrq(struct ib_srq *ibsrq)
+{
+ return container_of(ibsrq, struct ipath_srq, ibsrq);
+}
+
+static inline struct ipath_qp *to_iqp(struct ib_qp *ibqp)
+{
+ return container_of(ibqp, struct ipath_qp, ibqp);
+}
+
+static inline struct ipath_ibdev *to_idev(struct ib_device *ibdev)
+{
+ return container_of(ibdev, struct ipath_ibdev, ibdev);
+}
+
+int ipath_process_mad(struct ib_device *ibdev,
+ int mad_flags,
+ u8 port_num,
+ struct ib_wc *in_wc,
+ struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad);
+
+static inline struct ipath_ucontext *to_iucontext(struct ib_ucontext
+ *ibucontext)
+{
+ return container_of(ibucontext, struct ipath_ucontext, ibucontext);
+}
+
+/*
+ * Compare the lower 24 bits of the two values.
+ * Returns an integer <, ==, or > than zero.
+ */
+static inline int ipath_cmp24(u32 a, u32 b)
+{
+ return (((int) a) - ((int) b)) << 8;
+}
+
+struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid);
+
+int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
+
+int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
+
+int ipath_mcast_tree_empty(void);
+
+__be32 ipath_compute_aeth(struct ipath_qp *qp);
+
+struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn);
+
+struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
+
+int ipath_destroy_qp(struct ib_qp *ibqp);
+
+int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask);
+
+int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_qp_init_attr *init_attr);
+
+void ipath_free_all_qps(struct ipath_qp_table *qpt);
+
+int ipath_init_qp_table(struct ipath_ibdev *idev, int size);
+
+void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
+
+void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
+
+void ipath_do_rc_send(unsigned long data);
+
+void ipath_do_uc_send(unsigned long data);
+
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+ u32 len, u64 vaddr, u32 rkey, int acc);
+
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+ struct ib_sge *sge, int acc);
+
+void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length);
+
+void ipath_skip_sge(struct ipath_sge_state *ss, u32 length);
+
+int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr);
+
+void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc);
+
+int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr);
+
+void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+int ipath_alloc_lkey(struct ipath_lkey_table *rkt,
+ struct ipath_mregion *mr);
+
+void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey);
+
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+ struct ib_sge *sge, int acc);
+
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+ u32 len, u64 vaddr, u32 rkey, int acc);
+
+int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
+
+struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata);
+
+int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask);
+
+int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr);
+
+int ipath_destroy_srq(struct ib_srq *ibsrq);
+
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+
+int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
+
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+ struct ib_ucontext *context,
+ struct ib_udata *udata);
+
+int ipath_destroy_cq(struct ib_cq *ibcq);
+
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify);
+
+int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata);
+
+struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc);
+
+struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
+ struct ib_phys_buf *buffer_list,
+ int num_phys_buf, int acc, u64 *iova_start);
+
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+ int mr_access_flags,
+ struct ib_udata *udata);
+
+int ipath_dereg_mr(struct ib_mr *ibmr);
+
+struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
+ struct ib_fmr_attr *fmr_attr);
+
+int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
+ int list_len, u64 iova);
+
+int ipath_unmap_fmr(struct list_head *fmr_list);
+
+int ipath_dealloc_fmr(struct ib_fmr *ibfmr);
+
+void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev);
+
+void ipath_insert_rnr_queue(struct ipath_qp *qp);
+
+int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only);
+
+void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc);
+
+extern const enum ib_wc_opcode ib_ipath_wc_opcode[];
+
+extern const u8 ipath_cvt_physportstate[];
+
+extern const int ib_ipath_state_ops[];
+
+extern unsigned int ib_ipath_lkey_table_size;
+
+extern const u32 ib_ipath_rnr_table[];
+
+#endif /* IPATH_VERBS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
new file mode 100644
index 000000000000..10b31d2c4f20
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+
+#include "ipath_verbs.h"
+
+/*
+ * Global table of GID to attached QPs.
+ * The table is global to all ipath devices since a send from one QP/device
+ * needs to be locally routed to any locally attached QPs on the same
+ * or different device.
+ */
+static struct rb_root mcast_tree;
+static DEFINE_SPINLOCK(mcast_lock);
+
+/**
+ * ipath_mcast_qp_alloc - alloc a struct to link a QP to mcast GID struct
+ * @qp: the QP to link
+ */
+static struct ipath_mcast_qp *ipath_mcast_qp_alloc(struct ipath_qp *qp)
+{
+ struct ipath_mcast_qp *mqp;
+
+ mqp = kmalloc(sizeof *mqp, GFP_KERNEL);
+ if (!mqp)
+ goto bail;
+
+ mqp->qp = qp;
+ atomic_inc(&qp->refcount);
+
+bail:
+ return mqp;
+}
+
+static void ipath_mcast_qp_free(struct ipath_mcast_qp *mqp)
+{
+ struct ipath_qp *qp = mqp->qp;
+
+ /* Notify ipath_destroy_qp() if it is waiting. */
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+
+ kfree(mqp);
+}
+
+/**
+ * ipath_mcast_alloc - allocate the multicast GID structure
+ * @mgid: the multicast GID
+ *
+ * A list of QPs will be attached to this structure.
+ */
+static struct ipath_mcast *ipath_mcast_alloc(union ib_gid *mgid)
+{
+ struct ipath_mcast *mcast;
+
+ mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
+ if (!mcast)
+ goto bail;
+
+ mcast->mgid = *mgid;
+ INIT_LIST_HEAD(&mcast->qp_list);
+ init_waitqueue_head(&mcast->wait);
+ atomic_set(&mcast->refcount, 0);
+
+bail:
+ return mcast;
+}
+
+static void ipath_mcast_free(struct ipath_mcast *mcast)
+{
+ struct ipath_mcast_qp *p, *tmp;
+
+ list_for_each_entry_safe(p, tmp, &mcast->qp_list, list)
+ ipath_mcast_qp_free(p);
+
+ kfree(mcast);
+}
+
+/**
+ * ipath_mcast_find - search the global table for the given multicast GID
+ * @mgid: the multicast GID to search for
+ *
+ * Returns NULL if not found.
+ *
+ * The caller is responsible for decrementing the reference count if found.
+ */
+struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid)
+{
+ struct rb_node *n;
+ unsigned long flags;
+ struct ipath_mcast *mcast;
+
+ spin_lock_irqsave(&mcast_lock, flags);
+ n = mcast_tree.rb_node;
+ while (n) {
+ int ret;
+
+ mcast = rb_entry(n, struct ipath_mcast, rb_node);
+
+ ret = memcmp(mgid->raw, mcast->mgid.raw,
+ sizeof(union ib_gid));
+ if (ret < 0)
+ n = n->rb_left;
+ else if (ret > 0)
+ n = n->rb_right;
+ else {
+ atomic_inc(&mcast->refcount);
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ goto bail;
+ }
+ }
+ spin_unlock_irqrestore(&mcast_lock, flags);
+
+ mcast = NULL;
+
+bail:
+ return mcast;
+}
+
+/**
+ * ipath_mcast_add - insert mcast GID into table and attach QP struct
+ * @mcast: the mcast GID table
+ * @mqp: the QP to attach
+ *
+ * Return zero if both were added. Return EEXIST if the GID was already in
+ * the table but the QP was added. Return ESRCH if the QP was already
+ * attached and neither structure was added.
+ */
+static int ipath_mcast_add(struct ipath_mcast *mcast,
+ struct ipath_mcast_qp *mqp)
+{
+ struct rb_node **n = &mcast_tree.rb_node;
+ struct rb_node *pn = NULL;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&mcast_lock, flags);
+
+ while (*n) {
+ struct ipath_mcast *tmcast;
+ struct ipath_mcast_qp *p;
+
+ pn = *n;
+ tmcast = rb_entry(pn, struct ipath_mcast, rb_node);
+
+ ret = memcmp(mcast->mgid.raw, tmcast->mgid.raw,
+ sizeof(union ib_gid));
+ if (ret < 0) {
+ n = &pn->rb_left;
+ continue;
+ }
+ if (ret > 0) {
+ n = &pn->rb_right;
+ continue;
+ }
+
+ /* Search the QP list to see if this is already there. */
+ list_for_each_entry_rcu(p, &tmcast->qp_list, list) {
+ if (p->qp == mqp->qp) {
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ ret = ESRCH;
+ goto bail;
+ }
+ }
+ list_add_tail_rcu(&mqp->list, &tmcast->qp_list);
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ ret = EEXIST;
+ goto bail;
+ }
+
+ list_add_tail_rcu(&mqp->list, &mcast->qp_list);
+
+ atomic_inc(&mcast->refcount);
+ rb_link_node(&mcast->rb_node, pn, n);
+ rb_insert_color(&mcast->rb_node, &mcast_tree);
+
+ spin_unlock_irqrestore(&mcast_lock, flags);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ struct ipath_mcast *mcast;
+ struct ipath_mcast_qp *mqp;
+ int ret;
+
+ /*
+ * Allocate data structures since its better to do this outside of
+ * spin locks and it will most likely be needed.
+ */
+ mcast = ipath_mcast_alloc(gid);
+ if (mcast == NULL) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ mqp = ipath_mcast_qp_alloc(qp);
+ if (mqp == NULL) {
+ ipath_mcast_free(mcast);
+ ret = -ENOMEM;
+ goto bail;
+ }
+ switch (ipath_mcast_add(mcast, mqp)) {
+ case ESRCH:
+ /* Neither was used: can't attach the same QP twice. */
+ ipath_mcast_qp_free(mqp);
+ ipath_mcast_free(mcast);
+ ret = -EINVAL;
+ goto bail;
+ case EEXIST: /* The mcast wasn't used */
+ ipath_mcast_free(mcast);
+ break;
+ default:
+ break;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ struct ipath_mcast *mcast = NULL;
+ struct ipath_mcast_qp *p, *tmp;
+ struct rb_node *n;
+ unsigned long flags;
+ int last = 0;
+ int ret;
+
+ spin_lock_irqsave(&mcast_lock, flags);
+
+ /* Find the GID in the mcast table. */
+ n = mcast_tree.rb_node;
+ while (1) {
+ if (n == NULL) {
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ ret = 0;
+ goto bail;
+ }
+
+ mcast = rb_entry(n, struct ipath_mcast, rb_node);
+ ret = memcmp(gid->raw, mcast->mgid.raw,
+ sizeof(union ib_gid));
+ if (ret < 0)
+ n = n->rb_left;
+ else if (ret > 0)
+ n = n->rb_right;
+ else
+ break;
+ }
+
+ /* Search the QP list. */
+ list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) {
+ if (p->qp != qp)
+ continue;
+ /*
+ * We found it, so remove it, but don't poison the forward
+ * link until we are sure there are no list walkers.
+ */
+ list_del_rcu(&p->list);
+
+ /* If this was the last attached QP, remove the GID too. */
+ if (list_empty(&mcast->qp_list)) {
+ rb_erase(&mcast->rb_node, &mcast_tree);
+ last = 1;
+ }
+ break;
+ }
+
+ spin_unlock_irqrestore(&mcast_lock, flags);
+
+ if (p) {
+ /*
+ * Wait for any list walkers to finish before freeing the
+ * list element.
+ */
+ wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
+ ipath_mcast_qp_free(p);
+ }
+ if (last) {
+ atomic_dec(&mcast->refcount);
+ wait_event(mcast->wait, !atomic_read(&mcast->refcount));
+ ipath_mcast_free(mcast);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_mcast_tree_empty(void)
+{
+ return mcast_tree.rb_node == NULL;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
new file mode 100644
index 000000000000..adc5322f15c1
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file is conditionally built on x86_64 only. Otherwise weak symbol
+ * versions of the functions exported from here are used.
+ */
+
+#include <linux/pci.h>
+#include <asm/mtrr.h>
+#include <asm/processor.h>
+
+#include "ipath_kernel.h"
+
+/**
+ * ipath_enable_wc - enable write combining for MMIO writes to the device
+ * @dd: infinipath device
+ *
+ * This routine is x86_64-specific; it twiddles the CPU's MTRRs to enable
+ * write combining.
+ */
+int ipath_enable_wc(struct ipath_devdata *dd)
+{
+ int ret = 0;
+ u64 pioaddr, piolen;
+ unsigned bits;
+ const unsigned long addr = pci_resource_start(dd->pcidev, 0);
+ const size_t len = pci_resource_len(dd->pcidev, 0);
+
+ /*
+ * Set the PIO buffers to be WCCOMB, so we get HT bursts to the
+ * chip. Linux (possibly the hardware) requires it to be on a power
+ * 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.
+ */
+ pioaddr = addr + dd->ipath_piobufbase;
+ piolen = (dd->ipath_piobcnt2k +
+ dd->ipath_piobcnt4k) *
+ ALIGN(dd->ipath_piobcnt2k +
+ dd->ipath_piobcnt4k, dd->ipath_palign);
+
+ for (bits = 0; !(piolen & (1ULL << bits)); bits++)
+ /* do nothing */ ;
+
+ if (piolen != (1ULL << bits)) {
+ piolen >>= bits;
+ while (piolen >>= 1)
+ bits++;
+ piolen = 1ULL << (bits + 1);
+ }
+ if (pioaddr & (piolen - 1)) {
+ u64 atmp;
+ ipath_dbg("pioaddr %llx not on right boundary for size "
+ "%llx, fixing\n",
+ (unsigned long long) pioaddr,
+ (unsigned long long) piolen);
+ atmp = pioaddr & ~(piolen - 1);
+ if (atmp < addr || (atmp + piolen) > (addr + len)) {
+ ipath_dev_err(dd, "No way to align address/size "
+ "(%llx/%llx), no WC mtrr\n",
+ (unsigned long long) atmp,
+ (unsigned long long) piolen << 1);
+ ret = -ENODEV;
+ } else {
+ ipath_dbg("changing WC base from %llx to %llx, "
+ "len from %llx to %llx\n",
+ (unsigned long long) pioaddr,
+ (unsigned long long) atmp,
+ (unsigned long long) piolen,
+ (unsigned long long) piolen << 1);
+ pioaddr = atmp;
+ piolen <<= 1;
+ }
+ }
+
+ if (!ret) {
+ int cookie;
+ ipath_cdbg(VERBOSE, "Setting mtrr for chip to WC "
+ "(addr %llx, len=0x%llx)\n",
+ (unsigned long long) pioaddr,
+ (unsigned long long) piolen);
+ cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 0);
+ if (cookie < 0) {
+ {
+ dev_info(&dd->pcidev->dev,
+ "mtrr_add() WC for PIO bufs "
+ "failed (%d)\n",
+ cookie);
+ ret = -EINVAL;
+ }
+ } else {
+ ipath_cdbg(VERBOSE, "Set mtrr for chip to WC, "
+ "cookie is %d\n", cookie);
+ dd->ipath_wc_cookie = cookie;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * ipath_disable_wc - disable write combining for MMIO writes to the device
+ * @dd: infinipath device
+ */
+void ipath_disable_wc(struct ipath_devdata *dd)
+{
+ if (dd->ipath_wc_cookie) {
+ ipath_cdbg(VERBOSE, "undoing WCCOMB on pio buffers\n");
+ mtrr_del(dd->ipath_wc_cookie, 0, 0);
+ dd->ipath_wc_cookie = 0;
+ }
+}
+
+/**
+ * ipath_unordered_wc - indicate whether write combining is ordered
+ *
+ * Because our performance depends on our ability to do write combining mmio
+ * writes in the most efficient way, we need to know if we are on an Intel
+ * or AMD x86_64 processor. AMD x86_64 processors flush WC buffers out in
+ * the order completed, and so no special flushing is required to get
+ * correct ordering. Intel processors, however, will flush write buffers
+ * out in "random" orders, and so explicit ordering is needed at times.
+ */
+int ipath_unordered_wc(void)
+{
+ return boot_cpu_data.x86_vendor != X86_VENDOR_AMD;
+}
diff --git a/drivers/infiniband/hw/ipath/ips_common.h b/drivers/infiniband/hw/ipath/ips_common.h
new file mode 100644
index 000000000000..410a764dfcef
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ips_common.h
@@ -0,0 +1,263 @@
+#ifndef IPS_COMMON_H
+#define IPS_COMMON_H
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_common.h"
+
+struct ipath_header {
+ /*
+ * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset -
+ * 14 bits before ECO change ~28 Dec 03. After that, Vers 4,
+ * Port 3, TID 11, offset 14.
+ */
+ __le32 ver_port_tid_offset;
+ __le16 chksum;
+ __le16 pkt_flags;
+};
+
+struct ips_message_header {
+ __be16 lrh[4];
+ __be32 bth[3];
+ /* fields below this point are in host byte order */
+ struct ipath_header iph;
+ __u8 sub_opcode;
+ __u8 flags;
+ __u16 src_rank;
+ /* 24 bits. The upper 8 bit is available for other use */
+ union {
+ struct {
+ unsigned ack_seq_num:24;
+ unsigned port:4;
+ unsigned unused:4;
+ };
+ __u32 ack_seq_num_org;
+ };
+ __u8 expected_tid_session_id;
+ __u8 tinylen; /* to aid MPI */
+ union {
+ __u16 tag; /* to aid MPI */
+ __u16 mqhdr; /* for PSM MQ */
+ };
+ union {
+ __u32 mpi[4]; /* to aid MPI */
+ __u32 data[4];
+ __u64 mq[2]; /* for PSM MQ */
+ struct {
+ __u16 mtu;
+ __u8 major_ver;
+ __u8 minor_ver;
+ __u32 not_used; //free
+ __u32 run_id;
+ __u32 client_ver;
+ };
+ };
+};
+
+struct ether_header {
+ __be16 lrh[4];
+ __be32 bth[3];
+ struct ipath_header iph;
+ __u8 sub_opcode;
+ __u8 cmd;
+ __be16 lid;
+ __u16 mac[3];
+ __u8 frag_num;
+ __u8 seq_num;
+ __le32 len;
+ /* MUST be of word size due to PIO write requirements */
+ __u32 csum;
+ __le16 csum_offset;
+ __le16 flags;
+ __u16 first_2_bytes;
+ __u8 unused[2]; /* currently unused */
+};
+
+/*
+ * The PIO buffer used for sending infinipath messages must only be written
+ * in 32-bit words, all the data must be written, and no writes can occur
+ * after the last word is written (which transfers "ownership" of the buffer
+ * to the chip and triggers the message to be sent).
+ * Since the Linux sk_buff structure can be recursive, non-aligned, and
+ * any number of bytes in each segment, we use the following structure
+ * to keep information about the overall state of the copy operation.
+ * This is used to save the information needed to store the checksum
+ * in the right place before sending the last word to the hardware and
+ * to buffer the last 0-3 bytes of non-word sized segments.
+ */
+struct copy_data_s {
+ struct ether_header *hdr;
+ /* addr of PIO buf to write csum to */
+ __u32 __iomem *csum_pio;
+ __u32 __iomem *to; /* addr of PIO buf to write data to */
+ __u32 device; /* which device to allocate PIO bufs from */
+ __s32 error; /* set if there is an error. */
+ __s32 extra; /* amount of data saved in u.buf below */
+ __u32 len; /* total length to send in bytes */
+ __u32 flen; /* frament length in words */
+ __u32 csum; /* partial IP checksum */
+ __u32 pos; /* position for partial checksum */
+ __u32 offset; /* offset to where data currently starts */
+ __s32 checksum_calc; /* set to 1 when csum has been calculated */
+ struct sk_buff *skb;
+ union {
+ __u32 w;
+ __u8 buf[4];
+ } u;
+};
+
+/* IB - LRH header consts */
+#define IPS_LRH_GRH 0x0003 /* 1. word of IB LRH - next header: GRH */
+#define IPS_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */
+
+#define IPS_OFFSET 0
+
+/*
+ * defines the cut-off point between the header queue and eager/expected
+ * TID queue
+ */
+#define NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE \
+ ((sizeof(struct ips_message_header) - \
+ offsetof(struct ips_message_header, iph)) >> 2)
+
+/* OpCodes */
+#define OPCODE_IPS 0xC0
+#define OPCODE_ITH4X 0xC1
+
+/* OpCode 30 is use by stand-alone test programs */
+#define OPCODE_RAW_DATA 0xDE
+/* last OpCode (31) is reserved for test */
+#define OPCODE_TEST 0xDF
+
+/* sub OpCodes - ips */
+#define OPCODE_SEQ_DATA 0x01
+#define OPCODE_SEQ_CTRL 0x02
+
+#define OPCODE_SEQ_MQ_DATA 0x03
+#define OPCODE_SEQ_MQ_CTRL 0x04
+
+#define OPCODE_ACK 0x10
+#define OPCODE_NAK 0x11
+
+#define OPCODE_ERR_CHK 0x20
+#define OPCODE_ERR_CHK_PLS 0x21
+
+#define OPCODE_STARTUP 0x30
+#define OPCODE_STARTUP_ACK 0x31
+#define OPCODE_STARTUP_NAK 0x32
+
+#define OPCODE_STARTUP_EXT 0x34
+#define OPCODE_STARTUP_ACK_EXT 0x35
+#define OPCODE_STARTUP_NAK_EXT 0x36
+
+#define OPCODE_TIDS_RELEASE 0x40
+#define OPCODE_TIDS_RELEASE_CONFIRM 0x41
+
+#define OPCODE_CLOSE 0x50
+#define OPCODE_CLOSE_ACK 0x51
+/*
+ * like OPCODE_CLOSE, but no complaint if other side has already closed.
+ * Used when doing abort(), MPI_Abort(), etc.
+ */
+#define OPCODE_ABORT 0x52
+
+/* sub OpCodes - ith4x */
+#define OPCODE_ENCAP 0x81
+#define OPCODE_LID_ARP 0x82
+
+/* Receive Header Queue: receive type (from infinipath) */
+#define RCVHQ_RCV_TYPE_EXPECTED 0
+#define RCVHQ_RCV_TYPE_EAGER 1
+#define RCVHQ_RCV_TYPE_NON_KD 2
+#define RCVHQ_RCV_TYPE_ERROR 3
+
+/* misc. */
+#define SIZE_OF_CRC 1
+
+#define EAGER_TID_ID INFINIPATH_I_TID_MASK
+
+#define IPS_DEFAULT_P_KEY 0xFFFF
+
+#define IPS_PERMISSIVE_LID 0xFFFF
+#define IPS_MULTICAST_LID_BASE 0xC000
+
+#define IPS_AETH_CREDIT_SHIFT 24
+#define IPS_AETH_CREDIT_MASK 0x1F
+#define IPS_AETH_CREDIT_INVAL 0x1F
+
+#define IPS_PSN_MASK 0xFFFFFF
+#define IPS_MSN_MASK 0xFFFFFF
+#define IPS_QPN_MASK 0xFFFFFF
+#define IPS_MULTICAST_QPN 0xFFFFFF
+
+/* functions for extracting fields from rcvhdrq entries */
+static inline __u32 ips_get_hdr_err_flags(const __le32 * rbuf)
+{
+ return __le32_to_cpu(rbuf[1]);
+}
+
+static inline __u32 ips_get_index(const __le32 * rbuf)
+{
+ return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_EGRINDEX_SHIFT)
+ & INFINIPATH_RHF_EGRINDEX_MASK;
+}
+
+static inline __u32 ips_get_rcv_type(const __le32 * rbuf)
+{
+ return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_RCVTYPE_SHIFT)
+ & INFINIPATH_RHF_RCVTYPE_MASK;
+}
+
+static inline __u32 ips_get_length_in_bytes(const __le32 * rbuf)
+{
+ return ((__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_LENGTH_SHIFT)
+ & INFINIPATH_RHF_LENGTH_MASK) << 2;
+}
+
+static inline void *ips_get_first_protocol_header(const __u32 * rbuf)
+{
+ return (void *)&rbuf[2];
+}
+
+static inline struct ips_message_header *ips_get_ips_header(const __u32 *
+ rbuf)
+{
+ return (struct ips_message_header *)&rbuf[2];
+}
+
+static inline __u32 ips_get_ipath_ver(__le32 hdrword)
+{
+ return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT)
+ & INFINIPATH_I_VERS_MASK;
+}
+
+#endif /* IPS_COMMON_H */
diff --git a/drivers/infiniband/hw/ipath/verbs_debug.h b/drivers/infiniband/hw/ipath/verbs_debug.h
new file mode 100644
index 000000000000..40d693cf3f94
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/verbs_debug.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _VERBS_DEBUG_H
+#define _VERBS_DEBUG_H
+
+/*
+ * This file contains tracing code for the ib_ipath kernel module.
+ */
+#ifndef _VERBS_DEBUGGING /* tracing enabled or not */
+#define _VERBS_DEBUGGING 1
+#endif
+
+extern unsigned ib_ipath_debug;
+
+#define _VERBS_ERROR(fmt,...) \
+ do { \
+ printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_UNIT_ERROR(unit,fmt,...) \
+ do { \
+ printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \
+ } while(0)
+
+#if _VERBS_DEBUGGING
+
+/*
+ * Mask values for debugging. The scheme allows us to compile out any
+ * of the debug tracing stuff, and if compiled in, to enable or
+ * disable dynamically.
+ * This can be set at modprobe time also:
+ * modprobe ib_path ib_ipath_debug=3
+ */
+
+#define __VERBS_INFO 0x1 /* generic low verbosity stuff */
+#define __VERBS_DBG 0x2 /* generic debug */
+#define __VERBS_VDBG 0x4 /* verbose debug */
+#define __VERBS_SMADBG 0x8000 /* sma packet debug */
+
+#define _VERBS_INFO(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_INFO)) \
+ printk(KERN_INFO "%s: " fmt,"ib_ipath", \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_DBG(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_DBG)) \
+ printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_VDBG(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_VDBG)) \
+ printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_SMADBG(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_SMADBG)) \
+ printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#else /* ! _VERBS_DEBUGGING */
+
+#define _VERBS_INFO(fmt,...)
+#define _VERBS_DBG(fmt,...)
+#define _VERBS_VDBG(fmt,...)
+#define _VERBS_SMADBG(fmt,...)
+
+#endif /* _VERBS_DEBUGGING */
+
+#endif /* _VERBS_DEBUG_H */
diff --git a/drivers/infiniband/hw/mthca/Kconfig b/drivers/infiniband/hw/mthca/Kconfig
index e88be85b3d5c..9aa5a4468a75 100644
--- a/drivers/infiniband/hw/mthca/Kconfig
+++ b/drivers/infiniband/hw/mthca/Kconfig
@@ -7,10 +7,11 @@ config INFINIBAND_MTHCA
("Tavor") and the MT25208 PCI Express HCA ("Arbel").
config INFINIBAND_MTHCA_DEBUG
- bool "Verbose debugging output"
+ bool "Verbose debugging output" if EMBEDDED
depends on INFINIBAND_MTHCA
- default n
+ default y
---help---
- This option causes the mthca driver produce a bunch of debug
- messages. Select this is you are developing the driver or
- trying to diagnose a problem.
+ This option causes debugging code to be compiled into the
+ mthca driver. The output can be turned on via the
+ debug_level module parameter (which can also be set after
+ the driver is loaded through sysfs).
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index 47ec5a7cba0b..e388d95d0cf1 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -1,7 +1,3 @@
-ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
-
obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index bc5bdcbe51b5..b12aa03be251 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -42,6 +42,20 @@
#include "mthca_dev.h"
+enum {
+ MTHCA_RATE_TAVOR_FULL = 0,
+ MTHCA_RATE_TAVOR_1X = 1,
+ MTHCA_RATE_TAVOR_4X = 2,
+ MTHCA_RATE_TAVOR_1X_DDR = 3
+};
+
+enum {
+ MTHCA_RATE_MEMFREE_FULL = 0,
+ MTHCA_RATE_MEMFREE_QUARTER = 1,
+ MTHCA_RATE_MEMFREE_EIGHTH = 2,
+ MTHCA_RATE_MEMFREE_HALF = 3
+};
+
struct mthca_av {
__be32 port_pd;
u8 reserved1;
@@ -55,6 +69,90 @@ struct mthca_av {
__be32 dgid[4];
};
+static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate)
+{
+ switch (mthca_rate) {
+ case MTHCA_RATE_MEMFREE_EIGHTH:
+ return mult_to_ib_rate(port_rate >> 3);
+ case MTHCA_RATE_MEMFREE_QUARTER:
+ return mult_to_ib_rate(port_rate >> 2);
+ case MTHCA_RATE_MEMFREE_HALF:
+ return mult_to_ib_rate(port_rate >> 1);
+ case MTHCA_RATE_MEMFREE_FULL:
+ default:
+ return mult_to_ib_rate(port_rate);
+ }
+}
+
+static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate)
+{
+ switch (mthca_rate) {
+ case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS;
+ case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS;
+ case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS;
+ default: return port_rate;
+ }
+}
+
+enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port)
+{
+ if (mthca_is_memfree(dev)) {
+ /* Handle old Arbel FW */
+ if (dev->limits.stat_rate_support == 0x3 && mthca_rate)
+ return IB_RATE_2_5_GBPS;
+
+ return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]);
+ } else
+ return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]);
+}
+
+static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate)
+{
+ if (cur_rate <= req_rate)
+ return 0;
+
+ /*
+ * Inter-packet delay (IPD) to get from rate X down to a rate
+ * no more than Y is (X - 1) / Y.
+ */
+ switch ((cur_rate - 1) / req_rate) {
+ case 0: return MTHCA_RATE_MEMFREE_FULL;
+ case 1: return MTHCA_RATE_MEMFREE_HALF;
+ case 2: /* fall through */
+ case 3: return MTHCA_RATE_MEMFREE_QUARTER;
+ default: return MTHCA_RATE_MEMFREE_EIGHTH;
+ }
+}
+
+static u8 ib_rate_to_tavor(u8 static_rate)
+{
+ switch (static_rate) {
+ case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X;
+ case IB_RATE_5_GBPS: return MTHCA_RATE_TAVOR_1X_DDR;
+ case IB_RATE_10_GBPS: return MTHCA_RATE_TAVOR_4X;
+ default: return MTHCA_RATE_TAVOR_FULL;
+ }
+}
+
+u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port)
+{
+ u8 rate;
+
+ if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1])
+ return 0;
+
+ if (mthca_is_memfree(dev))
+ rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate),
+ dev->rate[port - 1]);
+ else
+ rate = ib_rate_to_tavor(static_rate);
+
+ if (!(dev->limits.stat_rate_support & (1 << rate)))
+ rate = 1;
+
+ return rate;
+}
+
int mthca_create_ah(struct mthca_dev *dev,
struct mthca_pd *pd,
struct ib_ah_attr *ah_attr,
@@ -107,7 +205,7 @@ on_hca_fail:
av->g_slid = ah_attr->src_path_bits;
av->dlid = cpu_to_be16(ah_attr->dlid);
av->msg_sr = (3 << 4) | /* 2K message */
- ah_attr->static_rate;
+ mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num);
av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
if (ah_attr->ah_flags & IB_AH_GRH) {
av->g_slid |= 0x80;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 343eca507870..1985b5dfa481 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -965,6 +965,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
u32 *outbox;
u8 field;
u16 size;
+ u16 stat_rate;
int err;
#define QUERY_DEV_LIM_OUT_SIZE 0x100
@@ -995,6 +996,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
#define QUERY_DEV_LIM_MTU_WIDTH_OFFSET 0x36
#define QUERY_DEV_LIM_VL_PORT_OFFSET 0x37
#define QUERY_DEV_LIM_MAX_GID_OFFSET 0x3b
+#define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_LIM_MAX_PKEY_OFFSET 0x3f
#define QUERY_DEV_LIM_FLAGS_OFFSET 0x44
#define QUERY_DEV_LIM_RSVD_UAR_OFFSET 0x48
@@ -1086,6 +1088,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
dev_lim->num_ports = field & 0xf;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET);
dev_lim->max_gids = 1 << (field & 0xf);
+ MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET);
+ dev_lim->stat_rate_support = stat_rate;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET);
dev_lim->max_pkeys = 1 << (field & 0xf);
MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index e4ec35c40dd3..2f976f2051d6 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -146,6 +146,7 @@ struct mthca_dev_lim {
int max_vl;
int num_ports;
int max_gids;
+ u16 stat_rate_support;
int max_pkeys;
u32 flags;
int reserved_uars;
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index ad52edbefe98..4c1dcb4c1822 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -151,6 +151,7 @@ struct mthca_limits {
int reserved_qps;
int num_srqs;
int max_srq_wqes;
+ int max_srq_sge;
int reserved_srqs;
int num_eecs;
int reserved_eecs;
@@ -172,6 +173,7 @@ struct mthca_limits {
int reserved_pds;
u32 page_size_cap;
u32 flags;
+ u16 stat_rate_support;
u8 port_width_cap;
};
@@ -353,10 +355,24 @@ struct mthca_dev {
struct ib_mad_agent *send_agent[MTHCA_MAX_PORTS][2];
struct ib_ah *sm_ah[MTHCA_MAX_PORTS];
spinlock_t sm_lock;
+ u8 rate[MTHCA_MAX_PORTS];
};
-#define mthca_dbg(mdev, format, arg...) \
- dev_dbg(&mdev->pdev->dev, format, ## arg)
+#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
+extern int mthca_debug_level;
+
+#define mthca_dbg(mdev, format, arg...) \
+ do { \
+ if (mthca_debug_level) \
+ dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \
+ } while (0)
+
+#else /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
+#define mthca_dbg(mdev, format, arg...) do { (void) mdev; } while (0)
+
+#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
#define mthca_err(mdev, format, arg...) \
dev_err(&mdev->pdev->dev, format, ## arg)
#define mthca_info(mdev, format, arg...) \
@@ -492,6 +508,7 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
enum ib_srq_attr_mask attr_mask);
int mthca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+int mthca_max_srq_sge(struct mthca_dev *dev);
void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
enum ib_event_type event_type);
void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
@@ -542,6 +559,8 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
struct ib_ud_header *header);
int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr);
int mthca_ah_grh_present(struct mthca_ah *ah);
+u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port);
+enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port);
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index dfb482eac9a2..4730863ece9a 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -49,6 +49,30 @@ enum {
MTHCA_VENDOR_CLASS2 = 0xa
};
+static int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
+{
+ struct ib_port_attr *tprops = NULL;
+ int ret;
+
+ tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
+ if (!tprops)
+ return -ENOMEM;
+
+ ret = ib_query_port(&dev->ib_dev, port_num, tprops);
+ if (ret) {
+ printk(KERN_WARNING "ib_query_port failed (%d) for %s port %d\n",
+ ret, dev->ib_dev.name, port_num);
+ goto out;
+ }
+
+ dev->rate[port_num - 1] = tprops->active_speed *
+ ib_width_enum_to_int(tprops->active_width);
+
+out:
+ kfree(tprops);
+ return ret;
+}
+
static void update_sm_ah(struct mthca_dev *dev,
u8 port_num, u16 lid, u8 sl)
{
@@ -90,6 +114,7 @@ static void smp_snoop(struct ib_device *ibdev,
mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&
mad->mad_hdr.method == IB_MGMT_METHOD_SET) {
if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) {
+ mthca_update_rate(to_mdev(ibdev), port_num);
update_sm_ah(to_mdev(ibdev), port_num,
be16_to_cpup((__be16 *) (mad->data + 58)),
(*(u8 *) (mad->data + 76)) & 0xf);
@@ -246,6 +271,7 @@ int mthca_create_agents(struct mthca_dev *dev)
{
struct ib_mad_agent *agent;
int p, q;
+ int ret;
spin_lock_init(&dev->sm_lock);
@@ -255,11 +281,23 @@ int mthca_create_agents(struct mthca_dev *dev)
q ? IB_QPT_GSI : IB_QPT_SMI,
NULL, 0, send_handler,
NULL, NULL);
- if (IS_ERR(agent))
+ if (IS_ERR(agent)) {
+ ret = PTR_ERR(agent);
goto err;
+ }
dev->send_agent[p][q] = agent;
}
+
+ for (p = 1; p <= dev->limits.num_ports; ++p) {
+ ret = mthca_update_rate(dev, p);
+ if (ret) {
+ mthca_err(dev, "Failed to obtain port %d rate."
+ " aborting.\n", p);
+ goto err;
+ }
+ }
+
return 0;
err:
@@ -268,7 +306,7 @@ err:
if (dev->send_agent[p][q])
ib_unregister_mad_agent(dev->send_agent[p][q]);
- return PTR_ERR(agent);
+ return ret;
}
void __devexit mthca_free_agents(struct mthca_dev *dev)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 266f347c6707..9b9ff7bff357 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -52,6 +52,14 @@ MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRV_VERSION);
+#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
+
+int mthca_debug_level = 0;
+module_param_named(debug_level, mthca_debug_level, int, 0644);
+MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+
+#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
#ifdef CONFIG_PCI_MSI
static int msi_x = 0;
@@ -69,6 +77,10 @@ MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero");
#endif /* CONFIG_PCI_MSI */
+static int tune_pci = 0;
+module_param(tune_pci, int, 0444);
+MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");
+
static const char mthca_version[] __devinitdata =
DRV_NAME ": Mellanox InfiniBand HCA driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -90,6 +102,9 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev)
int cap;
u16 val;
+ if (!tune_pci)
+ return 0;
+
/* First try to max out Read Byte Count */
cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
if (cap) {
@@ -176,6 +191,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.reserved_srqs = dev_lim->reserved_srqs;
mdev->limits.reserved_eecs = dev_lim->reserved_eecs;
mdev->limits.max_desc_sz = dev_lim->max_desc_sz;
+ mdev->limits.max_srq_sge = mthca_max_srq_sge(mdev);
/*
* Subtract 1 from the limit because we need to allocate a
* spare CQE so the HCA HW can tell the difference between an
@@ -191,6 +207,18 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.port_width_cap = dev_lim->max_port_width;
mdev->limits.page_size_cap = ~(u32) (dev_lim->min_page_sz - 1);
mdev->limits.flags = dev_lim->flags;
+ /*
+ * For old FW that doesn't return static rate support, use a
+ * value of 0x3 (only static rate values of 0 or 1 are handled),
+ * except on Sinai, where even old FW can handle static rate
+ * values of 2 and 3.
+ */
+ if (dev_lim->stat_rate_support)
+ mdev->limits.stat_rate_support = dev_lim->stat_rate_support;
+ else if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
+ mdev->limits.stat_rate_support = 0xf;
+ else
+ mdev->limits.stat_rate_support = 0x3;
/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
May be doable since hardware supports it for SRQ.
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 2c250bc11c33..565a24b1756f 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -106,7 +106,7 @@ static int mthca_query_device(struct ib_device *ibdev,
props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
props->max_srq = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
props->max_srq_wr = mdev->limits.max_srq_wqes;
- props->max_srq_sge = mdev->limits.max_sg;
+ props->max_srq_sge = mdev->limits.max_srq_sge;
props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay;
props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ?
IB_ATOMIC_HCA : IB_ATOMIC_NONE;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 2e7f52136965..6676a786d690 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -257,6 +257,8 @@ struct mthca_qp {
atomic_t refcount;
u32 qpn;
int is_direct;
+ u8 port; /* for SQP and memfree use only */
+ u8 alt_port; /* for memfree use only */
u8 transport;
u8 state;
u8 atomic_rd_en;
@@ -278,7 +280,6 @@ struct mthca_qp {
struct mthca_sqp {
struct mthca_qp qp;
- int port;
int pkey_index;
u32 qkey;
u32 send_psn;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 057c8e6af87b..f37b0e367323 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -248,6 +248,9 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
return;
}
+ if (event_type == IB_EVENT_PATH_MIG)
+ qp->port = qp->alt_port;
+
event.device = &dev->ib_dev;
event.event = event_type;
event.element.qp = &qp->ibqp;
@@ -392,10 +395,16 @@ static void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr,
{
memset(ib_ah_attr, 0, sizeof *path);
ib_ah_attr->port_num = (be32_to_cpu(path->port_pkey) >> 24) & 0x3;
+
+ if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->limits.num_ports)
+ return;
+
ib_ah_attr->dlid = be16_to_cpu(path->rlid);
ib_ah_attr->sl = be32_to_cpu(path->sl_tclass_flowlabel) >> 28;
ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f;
- ib_ah_attr->static_rate = path->static_rate & 0x7;
+ ib_ah_attr->static_rate = mthca_rate_to_ib(dev,
+ path->static_rate & 0x7,
+ ib_ah_attr->port_num);
ib_ah_attr->ah_flags = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
if (ib_ah_attr->ah_flags) {
ib_ah_attr->grh.sgid_index = path->mgid_index & (dev->limits.gid_table_len - 1);
@@ -455,8 +464,10 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
qp_attr->cap.max_recv_sge = qp->rq.max_gs;
qp_attr->cap.max_inline_data = qp->max_inline_data;
- to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
- to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
+ if (qp->transport == RC || qp->transport == UC) {
+ to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
+ to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
+ }
qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f;
qp_attr->alt_pkey_index = be32_to_cpu(context->alt_path.port_pkey) & 0x7f;
@@ -484,11 +495,11 @@ out:
}
static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
- struct mthca_qp_path *path)
+ struct mthca_qp_path *path, u8 port)
{
path->g_mylmc = ah->src_path_bits & 0x7f;
path->rlid = cpu_to_be16(ah->dlid);
- path->static_rate = !!ah->static_rate;
+ path->static_rate = mthca_get_rate(dev, ah->static_rate, port);
if (ah->ah_flags & IB_AH_GRH) {
if (ah->grh.sgid_index >= dev->limits.gid_table_len) {
@@ -634,7 +645,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (qp->transport == MLX)
qp_context->pri_path.port_pkey |=
- cpu_to_be32(to_msqp(qp)->port << 24);
+ cpu_to_be32(qp->port << 24);
else {
if (attr_mask & IB_QP_PORT) {
qp_context->pri_path.port_pkey |=
@@ -657,7 +668,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_AV) {
- if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path))
+ if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
+ attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
return -EINVAL;
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
@@ -681,7 +693,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
- if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path))
+ if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
+ attr->alt_ah_attr.port_num))
return -EINVAL;
qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
@@ -791,6 +804,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp->atomic_rd_en = attr->qp_access_flags;
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
qp->resp_depth = attr->max_dest_rd_atomic;
+ if (attr_mask & IB_QP_PORT)
+ qp->port = attr->port_num;
+ if (attr_mask & IB_QP_ALT_PATH)
+ qp->alt_port = attr->alt_port_num;
if (is_sqp(dev, qp))
store_attrs(to_msqp(qp), attr, attr_mask);
@@ -802,13 +819,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (is_qp0(dev, qp)) {
if (cur_state != IB_QPS_RTR &&
new_state == IB_QPS_RTR)
- init_port(dev, to_msqp(qp)->port);
+ init_port(dev, qp->port);
if (cur_state != IB_QPS_RESET &&
cur_state != IB_QPS_ERR &&
(new_state == IB_QPS_RESET ||
new_state == IB_QPS_ERR))
- mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
+ mthca_CLOSE_IB(dev, qp->port, &status);
}
/*
@@ -1212,6 +1229,9 @@ int mthca_alloc_qp(struct mthca_dev *dev,
if (qp->qpn == -1)
return -ENOMEM;
+ /* initialize port to zero for error-catching. */
+ qp->port = 0;
+
err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
send_policy, qp);
if (err) {
@@ -1261,7 +1281,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
if (err)
goto err_out;
- sqp->port = port;
+ sqp->qp.port = port;
sqp->qp.qpn = mqpn;
sqp->qp.transport = MLX;
@@ -1404,10 +1424,10 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
if (!sqp->qp.ibqp.qp_num)
- ib_get_cached_pkey(&dev->ib_dev, sqp->port,
+ ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
sqp->pkey_index, &pkey);
else
- ib_get_cached_pkey(&dev->ib_dev, sqp->port,
+ ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
wr->wr.ud.pkey_index, &pkey);
sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 2dd3aea05341..adcaf85355ae 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -192,7 +192,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
/* Sanity check SRQ size before proceeding */
if (attr->max_wr > dev->limits.max_srq_wqes ||
- attr->max_sge > dev->limits.max_sg)
+ attr->max_sge > dev->limits.max_srq_sge)
return -EINVAL;
srq->max = attr->max_wr;
@@ -660,6 +660,31 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
return err;
}
+int mthca_max_srq_sge(struct mthca_dev *dev)
+{
+ if (mthca_is_memfree(dev))
+ return dev->limits.max_sg;
+
+ /*
+ * SRQ allocations are based on powers of 2 for Tavor,
+ * (although they only need to be multiples of 16 bytes).
+ *
+ * Therefore, we need to base the max number of sg entries on
+ * the largest power of 2 descriptor size that is <= to the
+ * actual max WQE descriptor size, rather than return the
+ * max_sg value given by the firmware (which is based on WQE
+ * sizes as multiples of 16, not powers of 2).
+ *
+ * If SRQ implementation is changed for Tavor to be based on
+ * multiples of 16, the calculation below can be deleted and
+ * the FW max_sg value returned.
+ */
+ return min_t(int, dev->limits.max_sg,
+ ((1 << (fls(dev->limits.max_desc_sz) - 1)) -
+ sizeof (struct mthca_next_seg)) /
+ sizeof (struct mthca_data_seg));
+}
+
int __devinit mthca_init_srq_table(struct mthca_dev *dev)
{
int err;
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 8d2e04cac68e..13d6d01c72c0 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -10,8 +10,9 @@ config INFINIBAND_IPOIB
group: <http://www.ietf.org/html.charters/ipoib-charter.html>.
config INFINIBAND_IPOIB_DEBUG
- bool "IP-over-InfiniBand debugging"
+ bool "IP-over-InfiniBand debugging" if EMBEDDED
depends on INFINIBAND_IPOIB
+ default y
---help---
This option causes debugging code to be compiled into the
IPoIB driver. The output can be turned on via the
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index b640107fb732..12a1e0572ef2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -65,6 +65,8 @@ enum {
IPOIB_RX_RING_SIZE = 128,
IPOIB_TX_RING_SIZE = 64,
+ IPOIB_MAX_QUEUE_SIZE = 8192,
+ IPOIB_MIN_QUEUE_SIZE = 2,
IPOIB_NUM_WC = 4,
@@ -230,6 +232,9 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh)
INFINIBAND_ALEN, sizeof(void *));
}
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
+void ipoib_neigh_free(struct ipoib_neigh *neigh);
+
extern struct workqueue_struct *ipoib_workqueue;
/* functions */
@@ -329,6 +334,8 @@ static inline void ipoib_unregister_debugfs(void) { }
#define ipoib_warn(priv, format, arg...) \
ipoib_printk(KERN_WARNING, priv, format , ## arg)
+extern int ipoib_sendq_size;
+extern int ipoib_recvq_size;
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
extern int ipoib_debug_level;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 685258e34034..5dde380e8dbe 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -213,7 +213,7 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
gid_buf, path.pathrec.dlid ? "yes" : "no");
if (path.pathrec.dlid) {
- rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25;
+ rate = ib_rate_to_mult(path.pathrec.rate) * 25;
seq_printf(file,
" DLID: 0x%04x\n"
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index ed65202878d8..a54da42849ae 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -161,7 +161,7 @@ static int ipoib_ib_post_receives(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int i;
- for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
+ for (i = 0; i < ipoib_recvq_size; ++i) {
if (ipoib_alloc_rx_skb(dev, i)) {
ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
return -ENOMEM;
@@ -187,7 +187,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
if (wr_id & IPOIB_OP_RECV) {
wr_id &= ~IPOIB_OP_RECV;
- if (wr_id < IPOIB_RX_RING_SIZE) {
+ if (wr_id < ipoib_recvq_size) {
struct sk_buff *skb = priv->rx_ring[wr_id].skb;
dma_addr_t addr = priv->rx_ring[wr_id].mapping;
@@ -252,9 +252,9 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
struct ipoib_tx_buf *tx_req;
unsigned long flags;
- if (wr_id >= IPOIB_TX_RING_SIZE) {
+ if (wr_id >= ipoib_sendq_size) {
ipoib_warn(priv, "completion event with wrid %d (> %d)\n",
- wr_id, IPOIB_TX_RING_SIZE);
+ wr_id, ipoib_sendq_size);
return;
}
@@ -275,7 +275,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
spin_lock_irqsave(&priv->tx_lock, flags);
++priv->tx_tail;
if (netif_queue_stopped(dev) &&
- priv->tx_head - priv->tx_tail <= IPOIB_TX_RING_SIZE / 2)
+ priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
netif_wake_queue(dev);
spin_unlock_irqrestore(&priv->tx_lock, flags);
@@ -344,13 +344,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
* means we have to make sure everything is properly recorded and
* our state is consistent before we call post_send().
*/
- tx_req = &priv->tx_ring[priv->tx_head & (IPOIB_TX_RING_SIZE - 1)];
+ tx_req = &priv->tx_ring[priv->tx_head & (ipoib_sendq_size - 1)];
tx_req->skb = skb;
addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,
DMA_TO_DEVICE);
pci_unmap_addr_set(tx_req, mapping, addr);
- if (unlikely(post_send(priv, priv->tx_head & (IPOIB_TX_RING_SIZE - 1),
+ if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
address->ah, qpn, addr, skb->len))) {
ipoib_warn(priv, "post_send failed\n");
++priv->stats.tx_errors;
@@ -363,7 +363,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
address->last_send = priv->tx_head;
++priv->tx_head;
- if (priv->tx_head - priv->tx_tail == IPOIB_TX_RING_SIZE) {
+ if (priv->tx_head - priv->tx_tail == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
netif_stop_queue(dev);
}
@@ -488,7 +488,7 @@ static int recvs_pending(struct net_device *dev)
int pending = 0;
int i;
- for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
+ for (i = 0; i < ipoib_recvq_size; ++i)
if (priv->rx_ring[i].skb)
++pending;
@@ -527,7 +527,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
*/
while ((int) priv->tx_tail - (int) priv->tx_head < 0) {
tx_req = &priv->tx_ring[priv->tx_tail &
- (IPOIB_TX_RING_SIZE - 1)];
+ (ipoib_sendq_size - 1)];
dma_unmap_single(priv->ca->dma_device,
pci_unmap_addr(tx_req, mapping),
tx_req->skb->len,
@@ -536,7 +536,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
++priv->tx_tail;
}
- for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
+ for (i = 0; i < ipoib_recvq_size; ++i)
if (priv->rx_ring[i].skb) {
dma_unmap_single(priv->ca->dma_device,
pci_unmap_addr(&priv->rx_ring[i],
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 9b0bd7c746ca..cb078a7d0bf5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -41,6 +41,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/kernel.h>
#include <linux/if_arp.h> /* For ARPHRD_xxx */
@@ -53,6 +54,14 @@ MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
MODULE_LICENSE("Dual BSD/GPL");
+int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE;
+int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE;
+
+module_param_named(send_queue_size, ipoib_sendq_size, int, 0444);
+MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue");
+module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444);
+MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue");
+
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
int ipoib_debug_level;
@@ -252,8 +261,8 @@ static void path_free(struct net_device *dev, struct ipoib_path *path)
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
- *to_ipoib_neigh(neigh->neighbour) = NULL;
- kfree(neigh);
+
+ ipoib_neigh_free(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -327,9 +336,8 @@ void ipoib_flush_paths(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path, *tp;
LIST_HEAD(remove_list);
- unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irq(&priv->lock);
list_splice(&priv->path_list, &remove_list);
INIT_LIST_HEAD(&priv->path_list);
@@ -337,14 +345,15 @@ void ipoib_flush_paths(struct net_device *dev)
list_for_each_entry(path, &remove_list, list)
rb_erase(&path->rb_node, &priv->path_tree);
- spin_unlock_irqrestore(&priv->lock, flags);
-
list_for_each_entry_safe(path, tp, &remove_list, list) {
if (path->query)
ib_sa_cancel_query(path->query_id, path->query);
+ spin_unlock_irq(&priv->lock);
wait_for_completion(&path->done);
path_free(dev, path);
+ spin_lock_irq(&priv->lock);
}
+ spin_unlock_irq(&priv->lock);
}
static void path_rec_completion(int status,
@@ -373,16 +382,9 @@ static void path_rec_completion(int status,
struct ib_ah_attr av = {
.dlid = be16_to_cpu(pathrec->dlid),
.sl = pathrec->sl,
- .port_num = priv->port
+ .port_num = priv->port,
+ .static_rate = pathrec->rate
};
- int path_rate = ib_sa_rate_enum_to_int(pathrec->rate);
-
- if (path_rate > 0 && priv->local_rate > path_rate)
- av.static_rate = (priv->local_rate - 1) / path_rate;
-
- ipoib_dbg(priv, "static_rate %d for local port %dX, path %dX\n",
- av.static_rate, priv->local_rate,
- ib_sa_rate_enum_to_int(pathrec->rate));
ah = ipoib_create_ah(dev, priv->pd, &av);
}
@@ -481,7 +483,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_path *path;
struct ipoib_neigh *neigh;
- neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+ neigh = ipoib_neigh_alloc(skb->dst->neighbour);
if (!neigh) {
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -489,8 +491,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
}
skb_queue_head_init(&neigh->queue);
- neigh->neighbour = skb->dst->neighbour;
- *to_ipoib_neigh(skb->dst->neighbour) = neigh;
/*
* We can only be called from ipoib_start_xmit, so we're
@@ -503,7 +503,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
path = path_rec_create(dev,
(union ib_gid *) (skb->dst->neighbour->ha + 4));
if (!path)
- goto err;
+ goto err_path;
__path_add(dev, path);
}
@@ -521,17 +521,17 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
__skb_queue_tail(&neigh->queue, skb);
if (!path->query && path_rec_start(dev, path))
- goto err;
+ goto err_list;
}
spin_unlock(&priv->lock);
return;
-err:
- *to_ipoib_neigh(skb->dst->neighbour) = NULL;
+err_list:
list_del(&neigh->list);
- kfree(neigh);
+err_path:
+ ipoib_neigh_free(neigh);
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -763,8 +763,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
if (neigh->ah)
ah = neigh->ah;
list_del(&neigh->list);
- *to_ipoib_neigh(n) = NULL;
- kfree(neigh);
+ ipoib_neigh_free(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -773,6 +772,26 @@ static void ipoib_neigh_destructor(struct neighbour *n)
ipoib_put_ah(ah);
}
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
+{
+ struct ipoib_neigh *neigh;
+
+ neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+ if (!neigh)
+ return NULL;
+
+ neigh->neighbour = neighbour;
+ *to_ipoib_neigh(neighbour) = neigh;
+
+ return neigh;
+}
+
+void ipoib_neigh_free(struct ipoib_neigh *neigh)
+{
+ *to_ipoib_neigh(neigh->neighbour) = NULL;
+ kfree(neigh);
+}
+
static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
{
parms->neigh_destructor = ipoib_neigh_destructor;
@@ -785,20 +804,19 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
struct ipoib_dev_priv *priv = netdev_priv(dev);
/* Allocate RX/TX "rings" to hold queued skbs */
-
- priv->rx_ring = kzalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
+ priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
GFP_KERNEL);
if (!priv->rx_ring) {
printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
- ca->name, IPOIB_RX_RING_SIZE);
+ ca->name, ipoib_recvq_size);
goto out;
}
- priv->tx_ring = kzalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
+ priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring,
GFP_KERNEL);
if (!priv->tx_ring) {
printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
- ca->name, IPOIB_TX_RING_SIZE);
+ ca->name, ipoib_sendq_size);
goto out_rx_ring_cleanup;
}
@@ -866,7 +884,7 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
dev->addr_len = INFINIBAND_ALEN;
dev->type = ARPHRD_INFINIBAND;
- dev->tx_queue_len = IPOIB_TX_RING_SIZE * 2;
+ dev->tx_queue_len = ipoib_sendq_size * 2;
dev->features = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX;
/* MTU will be reset when mcast join happens */
@@ -1118,6 +1136,14 @@ static int __init ipoib_init_module(void)
{
int ret;
+ ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size);
+ ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE);
+ ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE);
+
+ ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
+ ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
+ ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
+
ret = ipoib_register_debugfs();
if (ret)
return ret;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 93c462eaf4fd..1dae4b238252 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -114,8 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
- *to_ipoib_neigh(neigh->neighbour) = NULL;
- kfree(neigh);
+ ipoib_neigh_free(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -251,6 +250,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
.port_num = priv->port,
.sl = mcast->mcmember.sl,
.ah_flags = IB_AH_GRH,
+ .static_rate = mcast->mcmember.rate,
.grh = {
.flow_label = be32_to_cpu(mcast->mcmember.flow_label),
.hop_limit = mcast->mcmember.hop_limit,
@@ -258,17 +258,8 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
.traffic_class = mcast->mcmember.traffic_class
}
};
- int path_rate = ib_sa_rate_enum_to_int(mcast->mcmember.rate);
-
av.grh.dgid = mcast->mcmember.mgid;
- if (path_rate > 0 && priv->local_rate > path_rate)
- av.static_rate = (priv->local_rate - 1) / path_rate;
-
- ipoib_dbg_mcast(priv, "static_rate %d for local port %dX, mcmember %dX\n",
- av.static_rate, priv->local_rate,
- ib_sa_rate_enum_to_int(mcast->mcmember.rate));
-
ah = ipoib_create_ah(dev, priv->pd, &av);
if (!ah) {
ipoib_warn(priv, "ib_address_create failed\n");
@@ -618,6 +609,22 @@ int ipoib_mcast_start_thread(struct net_device *dev)
return 0;
}
+static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
+ struct ipoib_mcast *mcast)
+{
+ spin_lock_irq(&priv->lock);
+ if (mcast && mcast->query) {
+ ib_sa_cancel_query(mcast->query_id, mcast->query);
+ mcast->query = NULL;
+ spin_unlock_irq(&priv->lock);
+ ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
+ IPOIB_GID_ARG(mcast->mcmember.mgid));
+ wait_for_completion(&mcast->done);
+ }
+ else
+ spin_unlock_irq(&priv->lock);
+}
+
int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -637,28 +644,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
if (flush)
flush_workqueue(ipoib_workqueue);
- spin_lock_irq(&priv->lock);
- if (priv->broadcast && priv->broadcast->query) {
- ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
- priv->broadcast->query = NULL;
- spin_unlock_irq(&priv->lock);
- ipoib_dbg_mcast(priv, "waiting for bcast\n");
- wait_for_completion(&priv->broadcast->done);
- } else
- spin_unlock_irq(&priv->lock);
+ wait_for_mcast_join(priv, priv->broadcast);
- list_for_each_entry(mcast, &priv->multicast_list, list) {
- spin_lock_irq(&priv->lock);
- if (mcast->query) {
- ib_sa_cancel_query(mcast->query_id, mcast->query);
- mcast->query = NULL;
- spin_unlock_irq(&priv->lock);
- ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
- wait_for_completion(&mcast->done);
- } else
- spin_unlock_irq(&priv->lock);
- }
+ list_for_each_entry(mcast, &priv->multicast_list, list)
+ wait_for_mcast_join(priv, mcast);
return 0;
}
@@ -772,13 +761,11 @@ out:
if (skb->dst &&
skb->dst->neighbour &&
!*to_ipoib_neigh(skb->dst->neighbour)) {
- struct ipoib_neigh *neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+ struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour);
if (neigh) {
kref_get(&mcast->ah->ref);
neigh->ah = mcast->ah;
- neigh->neighbour = skb->dst->neighbour;
- *to_ipoib_neigh(skb->dst->neighbour) = neigh;
list_add_tail(&neigh->list, &mcast->neigh_list);
}
}
@@ -913,6 +900,7 @@ void ipoib_mcast_restart_task(void *dev_ptr)
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+ wait_for_mcast_join(priv, mcast);
ipoib_mcast_leave(mcast->dev, mcast);
ipoib_mcast_free(mcast);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 5f0388027b25..1d49d1643c59 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -159,8 +159,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_init_attr init_attr = {
.cap = {
- .max_send_wr = IPOIB_TX_RING_SIZE,
- .max_recv_wr = IPOIB_RX_RING_SIZE,
+ .max_send_wr = ipoib_sendq_size,
+ .max_recv_wr = ipoib_recvq_size,
.max_send_sge = 1,
.max_recv_sge = 1
},
@@ -175,7 +175,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
}
priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev,
- IPOIB_TX_RING_SIZE + IPOIB_RX_RING_SIZE + 1);
+ ipoib_sendq_size + ipoib_recvq_size + 1);
if (IS_ERR(priv->cq)) {
printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
goto out_free_pd;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index fd8a95a9c5d3..5bb55742ada6 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -617,6 +617,14 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
scmnd->sc_data_direction);
}
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req,
+ int index)
+{
+ list_del(&req->list);
+ req->next = target->req_head;
+ target->req_head = index;
+}
+
static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
{
struct srp_request *req;
@@ -664,9 +672,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
scmnd->host_scribble = (void *) -1L;
scmnd->scsi_done(scmnd);
- list_del(&req->list);
- req->next = target->req_head;
- target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT;
+ srp_remove_req(target, req, rsp->tag & ~SRP_TAG_TSK_MGMT);
} else
req->cmd_done = 1;
}
@@ -1188,12 +1194,10 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
spin_lock_irq(target->scsi_host->host_lock);
if (req->cmd_done) {
- list_del(&req->list);
- req->next = target->req_head;
- target->req_head = req_index;
-
+ srp_remove_req(target, req, req_index);
scmnd->scsi_done(scmnd);
} else if (!req->tsk_status) {
+ srp_remove_req(target, req, req_index);
scmnd->result = DID_ABORT << 16;
ret = SUCCESS;
}
@@ -1434,6 +1438,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
p = match_strdup(args);
if (strlen(p) != 32) {
printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
+ kfree(p);
goto out;
}
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 1dca3cf42a54..2e4abdc26367 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -350,11 +350,11 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
return 0;
bail2:
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
bail1:
input_free_device(kbd->dev);
bail0:
kfree(kbd);
- serio_set_drvdata(serio, NULL);
return -EIO;
}
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
index 53c4fb62ed85..5b203fe21dcd 100644
--- a/drivers/isdn/gigaset/Kconfig
+++ b/drivers/isdn/gigaset/Kconfig
@@ -3,8 +3,8 @@ menu "Siemens Gigaset"
config ISDN_DRV_GIGASET
tristate "Siemens Gigaset support (isdn)"
- depends on ISDN_I4L && m
-# depends on ISDN_I4L && MODULES
+ depends on ISDN_I4L
+ select CRC_CCITT
help
Say m here if you have a Gigaset or Sinus isdn device.
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 171f8b703d61..ce3cd77094b3 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
* Hansjoerg Lipp <hjlipp@web.de>,
- * Stefan Eilers <Eilers.Stefan@epost.de>.
+ * Stefan Eilers.
*
* =====================================================================
* This program is free software; you can redistribute it and/or
@@ -11,10 +11,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -45,7 +41,7 @@ static inline int muststuff(unsigned char c)
* number of processed bytes
*/
static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
unsigned cbytes = cs->cbytes;
@@ -55,10 +51,11 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
for (;;) {
cs->respdata[cbytes] = c;
if (c == 10 || c == 13) {
- dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
- __func__, cbytes);
+ gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ __func__, cbytes);
cs->cbytes = cbytes;
- gigaset_handle_modem_response(cs); /* can change cs->dle */
+ gigaset_handle_modem_response(cs); /* can change
+ cs->dle */
cbytes = 0;
if (cs->dle &&
@@ -71,7 +68,7 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
if (cbytes < MAX_RESP_SIZE - 1)
cbytes++;
else
- warn("response too large");
+ dev_warn(cs->dev, "response too large\n");
}
if (!numbytes)
@@ -96,11 +93,12 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
* number of processed bytes
*/
static inline int lock_loop(unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
- gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0);
+ gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
+ numbytes, src);
gigaset_if_receive(cs, src, numbytes);
return numbytes;
@@ -115,24 +113,18 @@ static inline int lock_loop(unsigned char *src, int numbytes,
* numbytes (all bytes processed) on error --FIXME
*/
static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = inbuf->bcs;
- int inputstate;
- __u16 fcs;
- struct sk_buff *skb;
+ int inputstate = bcs->inputstate;
+ __u16 fcs = bcs->fcs;
+ struct sk_buff *skb = bcs->skb;
unsigned char error;
struct sk_buff *compskb;
int startbytes = numbytes;
int l;
- IFNULLRETVAL(bcs, numbytes);
- inputstate = bcs->inputstate;
- fcs = bcs->fcs;
- skb = bcs->skb;
- IFNULLRETVAL(skb, numbytes);
-
if (unlikely(inputstate & INS_byte_stuff)) {
inputstate &= ~INS_byte_stuff;
goto byte_stuff;
@@ -156,39 +148,37 @@ byte_stuff:
c ^= PPP_TRANS;
#ifdef CONFIG_GIGASET_DEBUG
if (unlikely(!muststuff(c)))
- dbg(DEBUG_HDLC,
- "byte stuffed: 0x%02x", c);
+ gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
#endif
} else if (unlikely(c == PPP_FLAG)) {
if (unlikely(inputstate & INS_skip_frame)) {
if (!(inputstate & INS_have_data)) { /* 7E 7E */
- //dbg(DEBUG_HDLC, "(7e)7e------------------------");
#ifdef CONFIG_GIGASET_DEBUG
++bcs->emptycount;
#endif
} else
- dbg(DEBUG_HDLC,
+ gig_dbg(DEBUG_HDLC,
"7e----------------------------");
/* end of frame */
error = 1;
gigaset_rcv_error(NULL, cs, bcs);
} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
- //dbg(DEBUG_HDLC, "(7e)7e------------------------");
#ifdef CONFIG_GIGASET_DEBUG
++bcs->emptycount;
#endif
break;
} else {
- dbg(DEBUG_HDLC,
- "7e----------------------------");
+ gig_dbg(DEBUG_HDLC,
+ "7e----------------------------");
/* end of frame */
error = 0;
if (unlikely(fcs != PPP_GOODFCS)) {
- err("Packet checksum at %lu failed, "
- "packet is corrupted (%u bytes)!",
+ dev_err(cs->dev,
+ "Packet checksum at %lu failed, "
+ "packet is corrupted (%u bytes)!\n",
bcs->rcvbytes, skb->len);
compskb = NULL;
gigaset_rcv_error(compskb, cs, bcs);
@@ -202,9 +192,11 @@ byte_stuff:
skb = NULL;
inputstate |= INS_skip_frame;
if (l == 1) {
- err("invalid packet size (1)!");
+ dev_err(cs->dev,
+ "invalid packet size (1)!\n");
error = 1;
- gigaset_rcv_error(NULL, cs, bcs);
+ gigaset_rcv_error(NULL,
+ cs, bcs);
}
}
if (likely(!(error ||
@@ -227,7 +219,8 @@ byte_stuff:
} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
skb_reserve(skb, HW_HDR_LEN);
} else {
- warn("could not allocate new skb");
+ dev_warn(cs->dev,
+ "could not allocate new skb\n");
inputstate |= INS_skip_frame;
}
@@ -235,7 +228,7 @@ byte_stuff:
#ifdef CONFIG_GIGASET_DEBUG
} else if (unlikely(muststuff(c))) {
/* Should not happen. Possible after ZDLE=1<CR><LF>. */
- dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
+ gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
#endif
}
@@ -243,8 +236,8 @@ byte_stuff:
#ifdef CONFIG_GIGASET_DEBUG
if (unlikely(!(inputstate & INS_have_data))) {
- dbg(DEBUG_HDLC,
- "7e (%d x) ================", bcs->emptycount);
+ gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
+ bcs->emptycount);
bcs->emptycount = 0;
}
#endif
@@ -253,14 +246,13 @@ byte_stuff:
if (likely(!(inputstate & INS_skip_frame))) {
if (unlikely(skb->len == SBUFSIZE)) {
- warn("received packet too long");
+ dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
skb = NULL;
inputstate |= INS_skip_frame;
break;
}
- *gigaset_skb_put_quick(skb, 1) = c;
- /* *__skb_put (skb, 1) = c; */
+ *__skb_put(skb, 1) = c;
fcs = crc_ccitt_byte(fcs, c);
}
@@ -289,19 +281,14 @@ byte_stuff:
* numbytes (all bytes processed) on error --FIXME
*/
static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = inbuf->bcs;
- int inputstate;
- struct sk_buff *skb;
+ int inputstate = bcs->inputstate;
+ struct sk_buff *skb = bcs->skb;
int startbytes = numbytes;
- IFNULLRETVAL(bcs, numbytes);
- inputstate = bcs->inputstate;
- skb = bcs->skb;
- IFNULLRETVAL(skb, numbytes);
-
for (;;) {
/* add character */
inputstate |= INS_have_data;
@@ -309,13 +296,13 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
if (likely(!(inputstate & INS_skip_frame))) {
if (unlikely(skb->len == SBUFSIZE)) {
//FIXME just pass skb up and allocate a new one
- warn("received packet too long");
+ dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
skb = NULL;
inputstate |= INS_skip_frame;
break;
}
- *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c];
+ *__skb_put(skb, 1) = gigaset_invtab[c];
}
if (unlikely(!numbytes))
@@ -343,7 +330,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
!= NULL)) {
skb_reserve(skb, HW_HDR_LEN);
} else {
- warn("could not allocate new skb");
+ dev_warn(cs->dev, "could not allocate new skb\n");
inputstate |= INS_skip_frame;
}
}
@@ -364,13 +351,13 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
head = atomic_read(&inbuf->head);
tail = atomic_read(&inbuf->tail);
- dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
if (head != tail) {
cs = inbuf->cs;
src = inbuf->data + head;
numbytes = (head > tail ? RBUFSIZE : tail) - head;
- dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+ gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
while (numbytes) {
if (atomic_read(&cs->mstate) == MS_LOCKED) {
@@ -392,8 +379,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
if (!(inbuf->inputstate & INS_DLE_char)) {
- /* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]? */
- /* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */
+ /* FIXME use function pointers? */
if (inbuf->inputstate & INS_command)
procbytes = cmd_loop(c, src, numbytes, inbuf);
else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
@@ -403,13 +389,14 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
src += procbytes;
numbytes -= procbytes;
- } else { /* DLE-char */
+ } else { /* DLE char */
inbuf->inputstate &= ~INS_DLE_char;
switch (c) {
case 'X': /*begin of command*/
#ifdef CONFIG_GIGASET_DEBUG
if (inbuf->inputstate & INS_command)
- err("received <DLE> 'X' in command mode");
+ dev_err(cs->dev,
+ "received <DLE> 'X' in command mode\n");
#endif
inbuf->inputstate |=
INS_command | INS_DLE_command;
@@ -417,7 +404,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
case '.': /*end of command*/
#ifdef CONFIG_GIGASET_DEBUG
if (!(inbuf->inputstate & INS_command))
- err("received <DLE> '.' in hdlc mode");
+ dev_err(cs->dev,
+ "received <DLE> '.' in hdlc mode\n");
#endif
inbuf->inputstate &= cs->dle ?
~(INS_DLE_command|INS_command)
@@ -425,7 +413,9 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
break;
//case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
default:
- err("received 0x10 0x%02x!", (int) c);
+ dev_err(cs->dev,
+ "received 0x10 0x%02x!\n",
+ (int) c);
/* FIXME: reset driver?? */
}
}
@@ -444,7 +434,7 @@ nextbyte:
}
}
- dbg(DEBUG_INTR, "setting head to %u", head);
+ gig_dbg(DEBUG_INTR, "setting head to %u", head);
atomic_set(&inbuf->head, head);
}
}
@@ -479,14 +469,13 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
stuf_cnt++;
fcs = crc_ccitt_byte(fcs, *cp++);
}
- fcs ^= 0xffff; /* complement */
+ fcs ^= 0xffff; /* complement */
/* size of new buffer: original size + number of stuffing bytes
* + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
*/
hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
if (!hdlc_skb) {
- err("unable to allocate memory for HDLC encoding!");
dev_kfree_skb(skb);
return NULL;
}
@@ -508,7 +497,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
}
/* Finally add FCS (byte stuffed) and flag sequence */
- c = (fcs & 0x00ff); /* least significant byte first */
+ c = (fcs & 0x00ff); /* least significant byte first */
if (muststuff(c)) {
*(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
c ^= PPP_TRANS;
@@ -546,7 +535,6 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
/* worst case: every byte must be stuffed */
iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
if (!iraw_skb) {
- err("unable to allocate memory for HDLC encoding!");
dev_kfree_skb(skb);
return NULL;
}
@@ -577,21 +565,23 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
*/
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
- unsigned len;
-
- IFNULLRETVAL(bcs, -EFAULT);
- IFNULLRETVAL(skb, -EFAULT);
- len = skb->len;
+ unsigned len = skb->len;
+ unsigned long flags;
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
else
skb = iraw_encode(skb, HW_HDR_LEN, 0);
- if (!skb)
+ if (!skb) {
+ err("unable to allocate memory for encoding!\n");
return -ENOMEM;
+ }
skb_queue_tail(&bcs->squeue, skb);
- tasklet_schedule(&bcs->cs->write_tasklet);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (bcs->cs->connected)
+ tasklet_schedule(&bcs->cs->write_tasklet);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return len; /* ok so far */
}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 31f0f07832bc..eb41aba3ddef 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -3,9 +3,7 @@
*
* Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>,
- * Stefan Eilers <Eilers.Stefan@epost.de>.
- *
- * Based on usb-gigaset.c.
+ * Stefan Eilers.
*
* =====================================================================
* This program is free software; you can redistribute it and/or
@@ -13,10 +11,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -30,7 +24,7 @@
#include <linux/moduleparam.h>
/* Version Information */
-#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
#define DRIVER_DESC "USB Driver for Gigaset 307x"
@@ -50,19 +44,20 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
#define GIGASET_DEVFSNAME "gig/bas/"
#define GIGASET_DEVNAME "ttyGB"
-#define IF_WRITEBUF 256 //FIXME
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
/* Values for the Gigaset 307x */
#define USB_GIGA_VENDOR_ID 0x0681
-#define USB_GIGA_PRODUCT_ID 0x0001
-#define USB_4175_PRODUCT_ID 0x0002
+#define USB_3070_PRODUCT_ID 0x0001
+#define USB_3075_PRODUCT_ID 0x0002
#define USB_SX303_PRODUCT_ID 0x0021
#define USB_SX353_PRODUCT_ID 0x0022
/* table of devices that work with this driver */
static struct usb_device_id gigaset_table [] = {
- { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) },
- { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) },
{ } /* Terminating entry */
@@ -70,9 +65,6 @@ static struct usb_device_id gigaset_table [] = {
MODULE_DEVICE_TABLE(usb, gigaset_table);
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE 200
-
/*======================= local function prototypes =============================*/
/* This function is called if a new device is connected to the USB port. It
@@ -84,29 +76,33 @@ static int gigaset_probe(struct usb_interface *interface,
/* Function will be called if the device is unplugged */
static void gigaset_disconnect(struct usb_interface *interface);
+static void read_ctrl_callback(struct urb *, struct pt_regs *);
+static void stopurbs(struct bas_bc_state *);
+static int atwrite_submit(struct cardstate *, unsigned char *, int);
+static int start_cbsend(struct cardstate *);
/*==============================================================================*/
struct bas_cardstate {
- struct usb_device *udev; /* USB device pointer */
- struct usb_interface *interface; /* interface for this device */
+ struct usb_device *udev; /* USB device pointer */
+ struct usb_interface *interface; /* interface for this device */
unsigned char minor; /* starting minor number */
- struct urb *urb_ctrl; /* control pipe default URB */
+ struct urb *urb_ctrl; /* control pipe default URB */
struct usb_ctrlrequest dr_ctrl;
struct timer_list timer_ctrl; /* control request timeout */
struct timer_list timer_atrdy; /* AT command ready timeout */
- struct urb *urb_cmd_out; /* for sending AT commands */
+ struct urb *urb_cmd_out; /* for sending AT commands */
struct usb_ctrlrequest dr_cmd_out;
int retry_cmd_out;
- struct urb *urb_cmd_in; /* for receiving AT replies */
+ struct urb *urb_cmd_in; /* for receiving AT replies */
struct usb_ctrlrequest dr_cmd_in;
struct timer_list timer_cmd_in; /* receive request timeout */
- unsigned char *rcvbuf; /* AT reply receive buffer */
+ unsigned char *rcvbuf; /* AT reply receive buffer */
- struct urb *urb_int_in; /* URB for interrupt pipe */
+ struct urb *urb_int_in; /* URB for interrupt pipe */
unsigned char int_in_buf[3];
spinlock_t lock; /* locks all following */
@@ -118,12 +114,14 @@ struct bas_cardstate {
};
/* status of direct USB connection to 307x base (bits in basstate) */
-#define BS_ATOPEN 0x001
-#define BS_B1OPEN 0x002
-#define BS_B2OPEN 0x004
-#define BS_ATREADY 0x008
-#define BS_INIT 0x010
-#define BS_ATTIMER 0x020
+#define BS_ATOPEN 0x001 /* AT channel open */
+#define BS_B1OPEN 0x002 /* B channel 1 open */
+#define BS_B2OPEN 0x004 /* B channel 2 open */
+#define BS_ATREADY 0x008 /* base ready for AT command */
+#define BS_INIT 0x010 /* base has signalled INIT_OK */
+#define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */
+#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */
+#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */
static struct gigaset_driver *driver = NULL;
@@ -137,6 +135,47 @@ static struct usb_driver gigaset_usb_driver = {
.id_table = gigaset_table,
};
+/* get message text for usb_submit_urb return code
+ */
+static char *get_usb_rcmsg(int rc)
+{
+ static char unkmsg[28];
+
+ switch (rc) {
+ case 0:
+ return "success";
+ case -ENOMEM:
+ return "out of memory";
+ case -ENODEV:
+ return "device not present";
+ case -ENOENT:
+ return "endpoint not present";
+ case -ENXIO:
+ return "URB type not supported";
+ case -EINVAL:
+ return "invalid argument";
+ case -EAGAIN:
+ return "start frame too early or too much scheduled";
+ case -EFBIG:
+ return "too many isochronous frames requested";
+ case -EPIPE:
+ return "endpoint stalled";
+ case -EMSGSIZE:
+ return "invalid packet size";
+ case -ENOSPC:
+ return "would overcommit USB bandwidth";
+ case -ESHUTDOWN:
+ return "device shut down";
+ case -EPERM:
+ return "reject flag set";
+ case -EHOSTUNREACH:
+ return "device suspended";
+ default:
+ snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc);
+ return unkmsg;
+ }
+}
+
/* get message text for USB status code
*/
static char *get_usb_statmsg(int status)
@@ -147,43 +186,37 @@ static char *get_usb_statmsg(int status)
case 0:
return "success";
case -ENOENT:
- return "canceled";
- case -ECONNRESET:
- return "canceled (async)";
+ return "unlinked (sync)";
case -EINPROGRESS:
return "pending";
case -EPROTO:
- return "bit stuffing or unknown USB error";
+ return "bit stuffing error, timeout, or unknown USB error";
case -EILSEQ:
- return "Illegal byte sequence (CRC mismatch)";
- case -EPIPE:
- return "babble detect or endpoint stalled";
- case -ENOSR:
- return "buffer error";
+ return "CRC mismatch, timeout, or unknown USB error";
case -ETIMEDOUT:
return "timed out";
- case -ENODEV:
- return "device not present";
+ case -EPIPE:
+ return "endpoint stalled";
+ case -ECOMM:
+ return "IN buffer overrun";
+ case -ENOSR:
+ return "OUT buffer underrun";
+ case -EOVERFLOW:
+ return "too much data";
case -EREMOTEIO:
return "short packet detected";
+ case -ENODEV:
+ return "device removed";
case -EXDEV:
return "partial isochronous transfer";
case -EINVAL:
return "invalid argument";
- case -ENXIO:
- return "URB already queued";
- case -EAGAIN:
- return "isochronous start frame too early or too much scheduled";
- case -EFBIG:
- return "too many isochronous frames requested";
- case -EMSGSIZE:
- return "endpoint message size zero";
+ case -ECONNRESET:
+ return "unlinked (async)";
case -ESHUTDOWN:
- return "endpoint shutdown";
- case -EBUSY:
- return "another request pending";
+ return "device shut down";
default:
- snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status);
+ snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status);
return unkmsg;
}
}
@@ -208,53 +241,54 @@ static inline char *usb_pipetype_str(int pipe)
* write content of URB to syslog for debugging
*/
static inline void dump_urb(enum debuglevel level, const char *tag,
- struct urb *urb)
+ struct urb *urb)
{
#ifdef CONFIG_GIGASET_DEBUG
int i;
- IFNULLRET(tag);
- dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
+ gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
if (urb) {
- dbg(level,
- " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
- "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
- (unsigned long) urb->dev,
- usb_pipetype_str(urb->pipe),
- usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out",
- urb->status, (unsigned long) urb->hcpriv,
- urb->transfer_flags);
- dbg(level,
- " transfer_buffer=0x%08lx[%d], actual_length=%d, "
- "bandwidth=%d, setup_packet=0x%08lx,",
- (unsigned long) urb->transfer_buffer,
- urb->transfer_buffer_length, urb->actual_length,
- urb->bandwidth, (unsigned long) urb->setup_packet);
- dbg(level,
- " start_frame=%d, number_of_packets=%d, interval=%d, "
- "error_count=%d,",
- urb->start_frame, urb->number_of_packets, urb->interval,
- urb->error_count);
- dbg(level,
- " context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={",
- (unsigned long) urb->context,
- (unsigned long) urb->complete);
+ gig_dbg(level,
+ " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
+ "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
+ (unsigned long) urb->dev,
+ usb_pipetype_str(urb->pipe),
+ usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->status, (unsigned long) urb->hcpriv,
+ urb->transfer_flags);
+ gig_dbg(level,
+ " transfer_buffer=0x%08lx[%d], actual_length=%d, "
+ "bandwidth=%d, setup_packet=0x%08lx,",
+ (unsigned long) urb->transfer_buffer,
+ urb->transfer_buffer_length, urb->actual_length,
+ urb->bandwidth, (unsigned long) urb->setup_packet);
+ gig_dbg(level,
+ " start_frame=%d, number_of_packets=%d, interval=%d, "
+ "error_count=%d,",
+ urb->start_frame, urb->number_of_packets, urb->interval,
+ urb->error_count);
+ gig_dbg(level,
+ " context=0x%08lx, complete=0x%08lx, "
+ "iso_frame_desc[]={",
+ (unsigned long) urb->context,
+ (unsigned long) urb->complete);
for (i = 0; i < urb->number_of_packets; i++) {
- struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i];
- dbg(level,
- " {offset=%u, length=%u, actual_length=%u, "
- "status=%u}",
- pifd->offset, pifd->length, pifd->actual_length,
- pifd->status);
+ struct usb_iso_packet_descriptor *pifd
+ = &urb->iso_frame_desc[i];
+ gig_dbg(level,
+ " {offset=%u, length=%u, actual_length=%u, "
+ "status=%u}",
+ pifd->offset, pifd->length, pifd->actual_length,
+ pifd->status);
}
}
- dbg(level, "}}");
+ gig_dbg(level, "}}");
#endif
}
/* read/set modem control bits etc. (m10x only) */
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
- unsigned new_state)
+ unsigned new_state)
{
return -EINVAL;
}
@@ -280,43 +314,39 @@ static inline void error_hangup(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
- dbg(DEBUG_ANY,
- "%s: scheduling HUP for channel %d", __func__, bcs->channel);
+ gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d",
+ __func__, bcs->channel);
- if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
- //FIXME what should we do?
- return;
- }
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL))
+ dev_err(cs->dev, "event queue full\n");
gigaset_schedule_event(cs);
}
/* error_reset
* reset Gigaset device because of an unrecoverable error
- * This function may be called from any context and takes care of scheduling
- * the necessary actions for execution outside of interrupt context.
+ * This function may be called from any context, and should take care of
+ * scheduling the necessary actions for execution outside of interrupt context.
+ * Right now, it just generates a kernel message calling for help.
* argument:
* controller state structure
*/
static inline void error_reset(struct cardstate *cs)
{
//FIXME try to recover without bothering the user
- err("unrecoverable error - please disconnect the Gigaset base to reset");
+ dev_err(cs->dev,
+ "unrecoverable error - please disconnect Gigaset base to reset\n");
}
/* check_pending
* check for completion of pending control request
* parameter:
- * urb USB request block of completed request
- * urb->context = hardware specific controller state structure
+ * ucs hardware specific controller state structure
*/
static void check_pending(struct bas_cardstate *ucs)
{
unsigned long flags;
- IFNULLRET(ucs);
- IFNULLRET(cardstate);
-
spin_lock_irqsave(&ucs->lock, flags);
switch (ucs->pending) {
case 0:
@@ -336,8 +366,6 @@ static void check_pending(struct bas_cardstate *ucs)
case HD_CLOSE_ATCHANNEL:
if (!(atomic_read(&ucs->basstate) & BS_ATOPEN))
ucs->pending = 0;
- //wake_up_interruptible(cs->initwait);
- //FIXME need own wait queue?
break;
case HD_CLOSE_B1CHANNEL:
if (!(atomic_read(&ucs->basstate) & BS_B1OPEN))
@@ -354,7 +382,9 @@ static void check_pending(struct bas_cardstate *ucs)
* are handled separately and should never end up here
*/
default:
- warn("unknown pending request 0x%02x cleared", ucs->pending);
+ dev_warn(&ucs->interface->dev,
+ "unknown pending request 0x%02x cleared\n",
+ ucs->pending);
ucs->pending = 0;
}
@@ -372,58 +402,53 @@ static void check_pending(struct bas_cardstate *ucs)
static void cmd_in_timeout(unsigned long data)
{
struct cardstate *cs = (struct cardstate *) data;
- struct bas_cardstate *ucs;
- unsigned long flags;
-
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
+ struct bas_cardstate *ucs = cs->hw.bas;
- spin_lock_irqsave(&cs->lock, flags);
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_USBREQ, "%s: disconnected", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
- return;
- }
if (!ucs->rcvbuf_size) {
- dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
+ gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
return;
}
- spin_unlock_irqrestore(&cs->lock, flags);
- err("timeout reading AT response");
+ dev_err(cs->dev, "timeout reading AT response\n");
error_reset(cs); //FIXME retry?
}
+/* set/clear bits in base connection state, return previous state
+ */
+inline static int update_basstate(struct bas_cardstate *ucs,
+ int set, int clear)
+{
+ unsigned long flags;
+ int state;
-static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs);
+ spin_lock_irqsave(&ucs->lock, flags);
+ state = atomic_read(&ucs->basstate);
+ atomic_set(&ucs->basstate, (state & ~clear) | set);
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ return state;
+}
/* atread_submit
- * submit an HD_READ_ATMESSAGE command URB
+ * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout
* parameters:
* cs controller state structure
* timeout timeout in 1/10 sec., 0: none
* return value:
* 0 on success
- * -EINVAL if a NULL pointer is encountered somewhere
* -EBUSY if another request is pending
* any URB submission error code
*/
static int atread_submit(struct cardstate *cs, int timeout)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = cs->hw.bas;
int ret;
- IFNULLRETVAL(cs, -EINVAL);
- ucs = cs->hw.bas;
- IFNULLRETVAL(ucs, -EINVAL);
- IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL);
+ gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
+ ucs->rcvbuf_size);
- dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size);
-
- if (ucs->urb_cmd_in->status == -EINPROGRESS) {
- err("could not submit HD_READ_ATMESSAGE: URB busy");
+ if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) {
+ dev_err(cs->dev,
+ "could not submit HD_READ_ATMESSAGE: URB busy\n");
return -EBUSY;
}
@@ -433,19 +458,20 @@ static int atread_submit(struct cardstate *cs, int timeout)
ucs->dr_cmd_in.wIndex = 0;
ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size);
usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
- usb_rcvctrlpipe(ucs->udev, 0),
- (unsigned char*) & ucs->dr_cmd_in,
- ucs->rcvbuf, ucs->rcvbuf_size,
- read_ctrl_callback, cs->inbuf);
+ usb_rcvctrlpipe(ucs->udev, 0),
+ (unsigned char*) & ucs->dr_cmd_in,
+ ucs->rcvbuf, ucs->rcvbuf_size,
+ read_ctrl_callback, cs->inbuf);
if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
- err("could not submit HD_READ_ATMESSAGE: %s",
- get_usb_statmsg(ret));
+ update_basstate(ucs, 0, BS_ATRDPEND);
+ dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
+ get_usb_statmsg(ret));
return ret;
}
if (timeout > 0) {
- dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+ gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10;
ucs->timer_cmd_in.data = (unsigned long) cs;
ucs->timer_cmd_in.function = cmd_in_timeout;
@@ -454,26 +480,6 @@ static int atread_submit(struct cardstate *cs, int timeout)
return 0;
}
-static void stopurbs(struct bas_bc_state *);
-static int start_cbsend(struct cardstate *);
-
-/* set/clear bits in base connection state
- */
-inline static void update_basstate(struct bas_cardstate *ucs,
- int set, int clear)
-{
- unsigned long flags;
- int state;
-
- spin_lock_irqsave(&ucs->lock, flags);
- state = atomic_read(&ucs->basstate);
- state &= ~clear;
- state |= set;
- atomic_set(&ucs->basstate, state);
- spin_unlock_irqrestore(&ucs->lock, flags);
-}
-
-
/* read_int_callback
* USB completion handler for interrupt pipe input
* called by the USB subsystem in interrupt context
@@ -483,48 +489,49 @@ inline static void update_basstate(struct bas_cardstate *ucs,
*/
static void read_int_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs;
- struct bas_cardstate *ucs;
+ struct cardstate *cs = urb->context;
+ struct bas_cardstate *ucs = cs->hw.bas;
struct bc_state *bcs;
unsigned long flags;
- int status;
+ int rc;
unsigned l;
int channel;
- IFNULLRET(urb);
- cs = (struct cardstate *) urb->context;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
-
- if (unlikely(!atomic_read(&cs->connected))) {
- warn("%s: disconnected", __func__);
- return;
- }
-
switch (urb->status) {
case 0: /* success */
break;
- case -ENOENT: /* canceled */
- case -ECONNRESET: /* canceled (async) */
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
/* ignore silently */
- dbg(DEBUG_USBREQ,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
+ return;
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
+ //FIXME use this as disconnect indicator?
+ gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
return;
default: /* severe trouble */
- warn("interrupt read: %s", get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "interrupt read: %s\n",
+ get_usb_statmsg(urb->status));
//FIXME corrective action? resubmission always ok?
goto resubmit;
}
+ /* drop incomplete packets even if the missing bytes wouldn't matter */
+ if (unlikely(urb->actual_length < 3)) {
+ dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n",
+ urb->actual_length);
+ goto resubmit;
+ }
+
l = (unsigned) ucs->int_in_buf[1] +
(((unsigned) ucs->int_in_buf[2]) << 8);
- dbg(DEBUG_USBREQ,
- "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length,
- (int)ucs->int_in_buf[0], l,
- (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
+ gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])",
+ urb->actual_length, (int)ucs->int_in_buf[0], l,
+ (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
channel = 0;
@@ -570,62 +577,68 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs)
case HD_B1_FLOW_CONTROL:
bcs = cs->bcs + channel;
atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES,
- &bcs->hw.bas->corrbytes);
- dbg(DEBUG_ISO,
- "Flow control (channel %d, sub %d): 0x%02x => %d",
- channel, bcs->hw.bas->numsub, l,
- atomic_read(&bcs->hw.bas->corrbytes));
+ &bcs->hw.bas->corrbytes);
+ gig_dbg(DEBUG_ISO,
+ "Flow control (channel %d, sub %d): 0x%02x => %d",
+ channel, bcs->hw.bas->numsub, l,
+ atomic_read(&bcs->hw.bas->corrbytes));
break;
case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */
if (!l) {
- warn("HD_RECEIVEATDATA_ACK with length 0 ignored");
+ dev_warn(cs->dev,
+ "HD_RECEIVEATDATA_ACK with length 0 ignored\n");
break;
}
spin_lock_irqsave(&cs->lock, flags);
if (ucs->rcvbuf_size) {
- spin_unlock_irqrestore(&cs->lock, flags);
- err("receive AT data overrun, %d bytes lost", l);
- error_reset(cs); //FIXME reschedule
- break;
+ /* throw away previous buffer - we have no queue */
+ dev_err(cs->dev,
+ "receive AT data overrun, %d bytes lost\n",
+ ucs->rcvbuf_size);
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf_size = 0;
}
if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) {
spin_unlock_irqrestore(&cs->lock, flags);
- err("%s: out of memory, %d bytes lost", __func__, l);
- error_reset(cs); //FIXME reschedule
+ dev_err(cs->dev, "out of memory receiving AT data\n");
+ error_reset(cs);
break;
}
ucs->rcvbuf_size = l;
ucs->retry_cmd_in = 0;
- if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) {
+ if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) {
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- error_reset(cs); //FIXME reschedule
+ if (rc != -ENODEV)
+ //FIXME corrective action?
+ error_reset(cs);
}
spin_unlock_irqrestore(&cs->lock, flags);
break;
case HD_RESET_INTERRUPT_PIPE_ACK:
- dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+ gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
break;
case HD_SUSPEND_END:
- dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
+ gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
break;
default:
- warn("unknown Gigaset signal 0x%02x (%u) ignored",
- (int) ucs->int_in_buf[0], l);
+ dev_warn(cs->dev,
+ "unknown Gigaset signal 0x%02x (%u) ignored\n",
+ (int) ucs->int_in_buf[0], l);
}
check_pending(ucs);
resubmit:
- status = usb_submit_urb(urb, SLAB_ATOMIC);
- if (unlikely(status)) {
- err("could not resubmit interrupt URB: %s",
- get_usb_statmsg(status));
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc != 0 && rc != -ENODEV)) {
+ dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
+ get_usb_rcmsg(rc));
error_reset(cs);
}
}
@@ -639,31 +652,17 @@ resubmit:
*/
static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs;
- struct bas_cardstate *ucs;
- unsigned numbytes;
- unsigned long flags;
- struct inbuf_t *inbuf;
+ struct inbuf_t *inbuf = urb->context;
+ struct cardstate *cs = inbuf->cs;
+ struct bas_cardstate *ucs = cs->hw.bas;
int have_data = 0;
+ unsigned numbytes;
+ int rc;
- IFNULLRET(urb);
- inbuf = (struct inbuf_t *) urb->context;
- IFNULLRET(inbuf);
- cs = inbuf->cs;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
-
- spin_lock_irqsave(&cs->lock, flags);
- if (!atomic_read(&cs->connected)) {
- warn("%s: disconnected", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
- return;
- }
+ update_basstate(ucs, 0, BS_ATRDPEND);
if (!ucs->rcvbuf_size) {
- warn("%s: no receive in progress", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
+ dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
return;
}
@@ -673,12 +672,14 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
case 0: /* normal completion */
numbytes = urb->actual_length;
if (unlikely(numbytes == 0)) {
- warn("control read: empty block received");
+ dev_warn(cs->dev,
+ "control read: empty block received\n");
goto retry;
}
if (unlikely(numbytes != ucs->rcvbuf_size)) {
- warn("control read: received %d chars, expected %d",
- numbytes, ucs->rcvbuf_size);
+ dev_warn(cs->dev,
+ "control read: received %d chars, expected %d\n",
+ numbytes, ucs->rcvbuf_size);
if (numbytes > ucs->rcvbuf_size)
numbytes = ucs->rcvbuf_size;
}
@@ -694,27 +695,32 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
}
break;
- case -ENOENT: /* canceled */
- case -ECONNRESET: /* canceled (async) */
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
/* no action necessary */
- dbg(DEBUG_USBREQ,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
break;
default: /* severe trouble */
- warn("control read: %s", get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "control read: %s\n",
+ get_usb_statmsg(urb->status));
retry:
if (ucs->retry_cmd_in++ < BAS_RETRY) {
- notice("control read: retry %d", ucs->retry_cmd_in);
- if (atread_submit(cs, BAS_TIMEOUT) >= 0) {
- /* resubmitted - bypass regular exit block */
- spin_unlock_irqrestore(&cs->lock, flags);
+ dev_notice(cs->dev, "control read: retry %d\n",
+ ucs->retry_cmd_in);
+ rc = atread_submit(cs, BAS_TIMEOUT);
+ if (rc >= 0 || rc == -ENODEV)
+ /* resubmitted or disconnected */
+ /* - bypass regular exit block */
return;
- }
} else {
- err("control read: giving up after %d tries",
- ucs->retry_cmd_in);
+ dev_err(cs->dev,
+ "control read: giving up after %d tries\n",
+ ucs->retry_cmd_in);
}
error_reset(cs);
}
@@ -722,9 +728,8 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- spin_unlock_irqrestore(&cs->lock, flags);
if (have_data) {
- dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
gigaset_schedule_event(cs);
}
}
@@ -743,21 +748,19 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
unsigned long flags;
int i, rc;
- IFNULLRET(urb);
- IFNULLRET(urb->context);
- IFNULLRET(cardstate);
-
/* status codes not worth bothering the tasklet with */
- if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
- urb->status == -EINPROGRESS)) {
- dbg(DEBUG_ISO,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ if (unlikely(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS ||
+ urb->status == -ENODEV ||
+ urb->status == -ESHUTDOWN)) {
+ gig_dbg(DEBUG_ISO, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
}
- bcs = (struct bc_state *) urb->context;
+ bcs = urb->context;
ubc = bcs->hw.bas;
- IFNULLRET(ubc);
spin_lock_irqsave(&ubc->isoinlock, flags);
if (likely(ubc->isoindone == NULL)) {
@@ -770,21 +773,24 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
for (i = 0; i < BAS_NUMFRAMES; i++) {
ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
if (unlikely(urb->iso_frame_desc[i].status != 0 &&
- urb->iso_frame_desc[i].status != -EINPROGRESS)) {
+ urb->iso_frame_desc[i].status !=
+ -EINPROGRESS))
ubc->loststatus = urb->iso_frame_desc[i].status;
- }
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
}
if (likely(atomic_read(&ubc->running))) {
- urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ /* urb->dev is clobbered by USB subsystem */
+ urb->dev = bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->number_of_packets = BAS_NUMFRAMES;
- dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__);
+ gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
+ __func__);
rc = usb_submit_urb(urb, SLAB_ATOMIC);
- if (unlikely(rc != 0)) {
- err("could not resubmit isochronous read URB: %s",
- get_usb_statmsg(rc));
+ if (unlikely(rc != 0 && rc != -ENODEV)) {
+ dev_err(bcs->cs->dev,
+ "could not resubmit isochronous read "
+ "URB: %s\n", get_usb_rcmsg(rc));
dump_urb(DEBUG_ISO, "isoc read", urb);
error_hangup(bcs);
}
@@ -806,23 +812,20 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
struct bas_bc_state *ubc;
unsigned long flags;
- IFNULLRET(urb);
- IFNULLRET(urb->context);
- IFNULLRET(cardstate);
-
/* status codes not worth bothering the tasklet with */
- if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
- urb->status == -EINPROGRESS)) {
- dbg(DEBUG_ISO,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ if (unlikely(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS ||
+ urb->status == -ENODEV ||
+ urb->status == -ESHUTDOWN)) {
+ gig_dbg(DEBUG_ISO, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
}
/* pass URB context to tasklet */
- ucx = (struct isow_urbctx_t *) urb->context;
- IFNULLRET(ucx->bcs);
+ ucx = urb->context;
ubc = ucx->bcs->hw.bas;
- IFNULLRET(ubc);
spin_lock_irqsave(&ubc->isooutlock, flags);
ubc->isooutovfl = ubc->isooutdone;
@@ -841,15 +844,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
*/
static int starturbs(struct bc_state *bcs)
{
+ struct bas_bc_state *ubc = bcs->hw.bas;
struct urb *urb;
- struct bas_bc_state *ubc;
int j, k;
int rc;
- IFNULLRETVAL(bcs, -EFAULT);
- ubc = bcs->hw.bas;
- IFNULLRETVAL(ubc, -EFAULT);
-
/* initialize L2 reception */
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
bcs->inputstate |= INS_flag_hunt;
@@ -859,7 +858,6 @@ static int starturbs(struct bc_state *bcs)
for (k = 0; k < BAS_INURBS; k++) {
urb = ubc->isoinurbs[k];
if (!urb) {
- err("isoinurbs[%d]==NULL", k);
rc = -EFAULT;
goto error;
}
@@ -881,11 +879,8 @@ static int starturbs(struct bc_state *bcs)
}
dump_urb(DEBUG_ISO, "Initial isoc read", urb);
- if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
- err("could not submit isochronous read URB %d: %s",
- k, get_usb_statmsg(rc));
+ if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0)
goto error;
- }
}
/* initialize L2 transmission */
@@ -895,7 +890,6 @@ static int starturbs(struct bc_state *bcs)
for (k = 0; k < BAS_OUTURBS; ++k) {
urb = ubc->isoouturbs[k].urb;
if (!urb) {
- err("isoouturbs[%d].urb==NULL", k);
rc = -EFAULT;
goto error;
}
@@ -921,11 +915,8 @@ static int starturbs(struct bc_state *bcs)
for (k = 0; k < 2; ++k) {
dump_urb(DEBUG_ISO, "Initial isoc write", urb);
rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC);
- if (rc != 0) {
- err("could not submit isochronous write URB %d: %s",
- k, get_usb_statmsg(rc));
+ if (rc != 0)
goto error;
- }
}
dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
ubc->isooutfree = &ubc->isoouturbs[2];
@@ -946,20 +937,20 @@ static void stopurbs(struct bas_bc_state *ubc)
{
int k, rc;
- IFNULLRET(ubc);
-
atomic_set(&ubc->running, 0);
for (k = 0; k < BAS_INURBS; ++k) {
rc = usb_unlink_urb(ubc->isoinurbs[k]);
- dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d",
- __func__, k, rc);
+ gig_dbg(DEBUG_ISO,
+ "%s: isoc input URB %d unlinked, result = %s",
+ __func__, k, get_usb_rcmsg(rc));
}
for (k = 0; k < BAS_OUTURBS; ++k) {
rc = usb_unlink_urb(ubc->isoouturbs[k].urb);
- dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d",
- __func__, k, rc);
+ gig_dbg(DEBUG_ISO,
+ "%s: isoc output URB %d unlinked, result = %s",
+ __func__, k, get_usb_rcmsg(rc));
}
}
@@ -969,7 +960,7 @@ static void stopurbs(struct bas_bc_state *ubc)
/* submit_iso_write_urb
* fill and submit the next isochronous write URB
* parameters:
- * bcs B channel state structure
+ * ucx context structure containing URB
* return value:
* number of frames submitted in URB
* 0 if URB not submitted because no data available (isooutbuf busy)
@@ -977,19 +968,13 @@ static void stopurbs(struct bas_bc_state *ubc)
*/
static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
{
- struct urb *urb;
- struct bas_bc_state *ubc;
+ struct urb *urb = ucx->urb;
+ struct bas_bc_state *ubc = ucx->bcs->hw.bas;
struct usb_iso_packet_descriptor *ifd;
int corrbytes, nframe, rc;
- IFNULLRETVAL(ucx, -EFAULT);
- urb = ucx->urb;
- IFNULLRETVAL(urb, -EFAULT);
- IFNULLRETVAL(ucx->bcs, -EFAULT);
- ubc = ucx->bcs->hw.bas;
- IFNULLRETVAL(ubc, -EFAULT);
-
- urb->dev = ucx->bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ /* urb->dev is clobbered by USB subsystem */
+ urb->dev = ucx->bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = ubc->isooutbuf->data;
urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data);
@@ -1000,7 +985,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
/* compute frame length according to flow control */
ifd->length = BAS_NORMFRAME;
if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) {
- dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes);
+ gig_dbg(DEBUG_ISO, "%s: corrbytes=%d",
+ __func__, corrbytes);
if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME)
corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME;
else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME)
@@ -1008,18 +994,21 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
ifd->length += corrbytes;
atomic_add(-corrbytes, &ubc->corrbytes);
}
- //dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length);
/* retrieve block of data to send */
- ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+ ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf,
+ ifd->length);
if (ifd->offset < 0) {
if (ifd->offset == -EBUSY) {
- dbg(DEBUG_ISO, "%s: buffer busy at frame %d",
- __func__, nframe);
- /* tasklet will be restarted from gigaset_send_skb() */
+ gig_dbg(DEBUG_ISO,
+ "%s: buffer busy at frame %d",
+ __func__, nframe);
+ /* tasklet will be restarted from
+ gigaset_send_skb() */
} else {
- err("%s: buffer error %d at frame %d",
- __func__, ifd->offset, nframe);
+ dev_err(ucx->bcs->cs->dev,
+ "%s: buffer error %d at frame %d\n",
+ __func__, ifd->offset, nframe);
return ifd->offset;
}
break;
@@ -1028,15 +1017,22 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
ifd->status = 0;
ifd->actual_length = 0;
}
- if ((urb->number_of_packets = nframe) > 0) {
- if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
- err("could not submit isochronous write URB: %s",
- get_usb_statmsg(rc));
- dump_urb(DEBUG_ISO, "isoc write", urb);
- return rc;
- }
- ++ubc->numsub;
+ if (unlikely(nframe == 0))
+ return 0; /* no data to send */
+ urb->number_of_packets = nframe;
+
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc)) {
+ if (rc == -ENODEV)
+ /* device removed - give up silently */
+ gig_dbg(DEBUG_ISO, "%s: disconnected", __func__);
+ else
+ dev_err(ucx->bcs->cs->dev,
+ "could not submit isochronous write URB: %s\n",
+ get_usb_rcmsg(rc));
+ return rc;
}
+ ++ubc->numsub;
return nframe;
}
@@ -1048,9 +1044,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
*/
static void write_iso_tasklet(unsigned long data)
{
- struct bc_state *bcs;
- struct bas_bc_state *ubc;
- struct cardstate *cs;
+ struct bc_state *bcs = (struct bc_state *) data;
+ struct bas_bc_state *ubc = bcs->hw.bas;
+ struct cardstate *cs = bcs->cs;
struct isow_urbctx_t *done, *next, *ovfl;
struct urb *urb;
struct usb_iso_packet_descriptor *ifd;
@@ -1059,23 +1055,12 @@ static void write_iso_tasklet(unsigned long data)
int i;
struct sk_buff *skb;
int len;
-
- bcs = (struct bc_state *) data;
- IFNULLRET(bcs);
- ubc = bcs->hw.bas;
- IFNULLRET(ubc);
- cs = bcs->cs;
- IFNULLRET(cs);
+ int rc;
/* loop while completed URBs arrive in time */
for (;;) {
- if (unlikely(!atomic_read(&cs->connected))) {
- warn("%s: disconnected", __func__);
- return;
- }
-
if (unlikely(!(atomic_read(&ubc->running)))) {
- dbg(DEBUG_ISO, "%s: not running", __func__);
+ gig_dbg(DEBUG_ISO, "%s: not running", __func__);
return;
}
@@ -1087,7 +1072,7 @@ static void write_iso_tasklet(unsigned long data)
ubc->isooutovfl = NULL;
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (ovfl) {
- err("isochronous write buffer underrun - buy a faster machine :-)");
+ dev_err(cs->dev, "isochronous write buffer underrun\n");
error_hangup(bcs);
break;
}
@@ -1100,7 +1085,8 @@ static void write_iso_tasklet(unsigned long data)
ubc->isooutfree = NULL;
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (next) {
- if (submit_iso_write_urb(next) <= 0) {
+ rc = submit_iso_write_urb(next);
+ if (unlikely(rc <= 0 && rc != -ENODEV)) {
/* could not submit URB, put it back */
spin_lock_irqsave(&ubc->isooutlock, flags);
if (ubc->isooutfree == NULL) {
@@ -1110,7 +1096,8 @@ static void write_iso_tasklet(unsigned long data)
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (next) {
/* couldn't put it back */
- err("losing isochronous write URB");
+ dev_err(cs->dev,
+ "losing isochronous write URB\n");
error_hangup(bcs);
}
}
@@ -1119,26 +1106,30 @@ static void write_iso_tasklet(unsigned long data)
/* process completed URB */
urb = done->urb;
switch (urb->status) {
+ case -EXDEV: /* partial completion */
+ gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+ __func__);
+ /* fall through - what's the difference anyway? */
case 0: /* normal completion */
- break;
- case -EXDEV: /* inspect individual frames */
- /* assumptions (for lack of documentation):
- * - actual_length bytes of the frame in error are successfully sent
+ /* inspect individual frames
+ * assumptions (for lack of documentation):
+ * - actual_length bytes of first frame in error are
+ * successfully sent
* - all following frames are not sent at all
*/
- dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
- offset = done->limit; /* just in case */
+ offset = done->limit; /* default (no error) */
for (i = 0; i < BAS_NUMFRAMES; i++) {
ifd = &urb->iso_frame_desc[i];
if (ifd->status ||
ifd->actual_length != ifd->length) {
- warn("isochronous write: frame %d: %s, "
- "only %d of %d bytes sent",
+ dev_warn(cs->dev,
+ "isochronous write: frame %d: %s, "
+ "only %d of %d bytes sent\n",
i, get_usb_statmsg(ifd->status),
ifd->actual_length, ifd->length);
offset = (ifd->offset +
- ifd->actual_length)
- % BAS_OUTBUFSIZE;
+ ifd->actual_length)
+ % BAS_OUTBUFSIZE;
break;
}
}
@@ -1148,25 +1139,26 @@ static void write_iso_tasklet(unsigned long data)
ifd = &urb->iso_frame_desc[i];
if (ifd->status != -EINPROGRESS
|| ifd->actual_length != 0) {
- warn("isochronous write: frame %d: %s, "
- "%d of %d bytes sent",
+ dev_warn(cs->dev,
+ "isochronous write: frame %d: %s, "
+ "%d of %d bytes sent\n",
i, get_usb_statmsg(ifd->status),
ifd->actual_length, ifd->length);
offset = (ifd->offset +
- ifd->actual_length)
- % BAS_OUTBUFSIZE;
+ ifd->actual_length)
+ % BAS_OUTBUFSIZE;
break;
}
}
#endif
break;
- case -EPIPE: //FIXME is this the code for "underrun"?
- err("isochronous write stalled");
+ case -EPIPE: /* stall - probably underrun */
+ dev_err(cs->dev, "isochronous write stalled\n");
error_hangup(bcs);
break;
default: /* severe trouble */
- warn("isochronous write: %s",
- get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "isochronous write: %s\n",
+ get_usb_statmsg(urb->status));
}
/* mark the write buffer area covered by this URB as free */
@@ -1180,7 +1172,8 @@ static void write_iso_tasklet(unsigned long data)
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (next) {
/* only one URB still active - resubmit one */
- if (submit_iso_write_urb(next) <= 0) {
+ rc = submit_iso_write_urb(next);
+ if (unlikely(rc <= 0 && rc != -ENODEV)) {
/* couldn't submit */
error_hangup(bcs);
}
@@ -1194,8 +1187,8 @@ static void write_iso_tasklet(unsigned long data)
if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) {
/* insufficient buffer space, push back onto queue */
skb_queue_head(&bcs->squeue, skb);
- dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
- __func__, skb_queue_len(&bcs->squeue));
+ gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
+ __func__, skb_queue_len(&bcs->squeue));
break;
}
skb_pull(skb, len);
@@ -1215,28 +1208,16 @@ static void write_iso_tasklet(unsigned long data)
*/
static void read_iso_tasklet(unsigned long data)
{
- struct bc_state *bcs;
- struct bas_bc_state *ubc;
- struct cardstate *cs;
+ struct bc_state *bcs = (struct bc_state *) data;
+ struct bas_bc_state *ubc = bcs->hw.bas;
+ struct cardstate *cs = bcs->cs;
struct urb *urb;
char *rcvbuf;
unsigned long flags;
int totleft, numbytes, offset, frame, rc;
- bcs = (struct bc_state *) data;
- IFNULLRET(bcs);
- ubc = bcs->hw.bas;
- IFNULLRET(ubc);
- cs = bcs->cs;
- IFNULLRET(cs);
-
/* loop while more completed URBs arrive in the meantime */
for (;;) {
- if (!atomic_read(&cs->connected)) {
- warn("%s: disconnected", __func__);
- return;
- }
-
/* retrieve URB */
spin_lock_irqsave(&ubc->isoinlock, flags);
if (!(urb = ubc->isoindone)) {
@@ -1245,38 +1226,44 @@ static void read_iso_tasklet(unsigned long data)
}
ubc->isoindone = NULL;
if (unlikely(ubc->loststatus != -EINPROGRESS)) {
- warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost",
- get_usb_statmsg(ubc->loststatus), ubc->isoinlost);
+ dev_warn(cs->dev,
+ "isochronous read overrun, "
+ "dropped URB with status: %s, %d bytes lost\n",
+ get_usb_statmsg(ubc->loststatus),
+ ubc->isoinlost);
ubc->loststatus = -EINPROGRESS;
}
spin_unlock_irqrestore(&ubc->isoinlock, flags);
if (unlikely(!(atomic_read(&ubc->running)))) {
- dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s",
- __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_ISO,
+ "%s: channel not running, "
+ "dropped URB with status: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
}
switch (urb->status) {
case 0: /* normal completion */
break;
- case -EXDEV: /* inspect individual frames (we do that anyway) */
- dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
+ case -EXDEV: /* inspect individual frames
+ (we do that anyway) */
+ gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+ __func__);
break;
case -ENOENT:
case -ECONNRESET:
- dbg(DEBUG_ISO, "%s: URB canceled", __func__);
- continue; /* -> skip */
- case -EINPROGRESS: /* huh? */
- dbg(DEBUG_ISO, "%s: URB still pending", __func__);
+ case -EINPROGRESS:
+ gig_dbg(DEBUG_ISO, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
continue; /* -> skip */
case -EPIPE:
- err("isochronous read stalled");
+ dev_err(cs->dev, "isochronous read stalled\n");
error_hangup(bcs);
continue; /* -> skip */
default: /* severe trouble */
- warn("isochronous read: %s",
- get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "isochronous read: %s\n",
+ get_usb_statmsg(urb->status));
goto error;
}
@@ -1284,33 +1271,44 @@ static void read_iso_tasklet(unsigned long data)
totleft = urb->actual_length;
for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
if (unlikely(urb->iso_frame_desc[frame].status)) {
- warn("isochronous read: frame %d: %s",
- frame, get_usb_statmsg(urb->iso_frame_desc[frame].status));
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: %s\n",
+ frame,
+ get_usb_statmsg(
+ urb->iso_frame_desc[frame].status));
break;
}
numbytes = urb->iso_frame_desc[frame].actual_length;
if (unlikely(numbytes > BAS_MAXFRAME)) {
- warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME",
- frame, numbytes);
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: "
+ "numbytes (%d) > BAS_MAXFRAME\n",
+ frame, numbytes);
break;
}
if (unlikely(numbytes > totleft)) {
- warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)",
- frame, numbytes, totleft);
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: "
+ "numbytes (%d) > totleft (%d)\n",
+ frame, numbytes, totleft);
break;
}
offset = urb->iso_frame_desc[frame].offset;
if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
- warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE",
- frame, offset, numbytes);
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: "
+ "offset (%d) + numbytes (%d) "
+ "> BAS_INBUFSIZE\n",
+ frame, offset, numbytes);
break;
}
gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
totleft -= numbytes;
}
if (unlikely(totleft > 0))
- warn("isochronous read: %d data bytes missing",
- totleft);
+ dev_warn(cs->dev,
+ "isochronous read: %d data bytes missing\n",
+ totleft);
error:
/* URB processed, resubmit */
@@ -1318,12 +1316,15 @@ static void read_iso_tasklet(unsigned long data)
urb->iso_frame_desc[frame].status = 0;
urb->iso_frame_desc[frame].actual_length = 0;
}
- urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ /* urb->dev is clobbered by USB subsystem */
+ urb->dev = bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->number_of_packets = BAS_NUMFRAMES;
- if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
- err("could not resubmit isochronous read URB: %s",
- get_usb_statmsg(rc));
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc != 0 && rc != -ENODEV)) {
+ dev_err(cs->dev,
+ "could not resubmit isochronous read URB: %s\n",
+ get_usb_rcmsg(rc));
dump_urb(DEBUG_ISO, "resubmit iso read", urb);
error_hangup(bcs);
}
@@ -1341,15 +1342,10 @@ static void read_iso_tasklet(unsigned long data)
static void req_timeout(unsigned long data)
{
struct bc_state *bcs = (struct bc_state *) data;
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = bcs->cs->hw.bas;
int pending;
unsigned long flags;
- IFNULLRET(bcs);
- IFNULLRET(bcs->cs);
- ucs = bcs->cs->hw.bas;
- IFNULLRET(ucs);
-
check_pending(ucs);
spin_lock_irqsave(&ucs->lock, flags);
@@ -1359,33 +1355,34 @@ static void req_timeout(unsigned long data)
switch (pending) {
case 0: /* no pending request */
- dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
+ gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
break;
case HD_OPEN_ATCHANNEL:
- err("timeout opening AT channel");
+ dev_err(bcs->cs->dev, "timeout opening AT channel\n");
error_reset(bcs->cs);
break;
case HD_OPEN_B2CHANNEL:
case HD_OPEN_B1CHANNEL:
- err("timeout opening channel %d", bcs->channel + 1);
+ dev_err(bcs->cs->dev, "timeout opening channel %d\n",
+ bcs->channel + 1);
error_hangup(bcs);
break;
case HD_CLOSE_ATCHANNEL:
- err("timeout closing AT channel");
- //wake_up_interruptible(cs->initwait);
- //FIXME need own wait queue?
+ dev_err(bcs->cs->dev, "timeout closing AT channel\n");
break;
case HD_CLOSE_B2CHANNEL:
case HD_CLOSE_B1CHANNEL:
- err("timeout closing channel %d", bcs->channel + 1);
+ dev_err(bcs->cs->dev, "timeout closing channel %d\n",
+ bcs->channel + 1);
break;
default:
- warn("request 0x%02x timed out, clearing", pending);
+ dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
+ pending);
}
}
@@ -1398,18 +1395,14 @@ static void req_timeout(unsigned long data)
*/
static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = urb->context;
unsigned long flags;
- IFNULLRET(urb);
- IFNULLRET(urb->context);
- IFNULLRET(cardstate);
-
- ucs = (struct bas_cardstate *) urb->context;
spin_lock_irqsave(&ucs->lock, flags);
if (urb->status && ucs->pending) {
- err("control request 0x%02x failed: %s",
- ucs->pending, get_usb_statmsg(urb->status));
+ dev_err(&ucs->interface->dev,
+ "control request 0x%02x failed: %s\n",
+ ucs->pending, get_usb_statmsg(urb->status));
del_timer(&ucs->timer_ctrl);
ucs->pending = 0;
}
@@ -1432,34 +1425,24 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
* timeout timeout in seconds (0: no timeout)
* return value:
* 0 on success
- * -EINVAL if a NULL pointer is encountered somewhere
* -EBUSY if another request is pending
* any URB submission error code
*/
static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = bcs->cs->hw.bas;
int ret;
unsigned long flags;
- IFNULLRETVAL(bcs, -EINVAL);
- IFNULLRETVAL(bcs->cs, -EINVAL);
- ucs = bcs->cs->hw.bas;
- IFNULLRETVAL(ucs, -EINVAL);
- IFNULLRETVAL(ucs->urb_ctrl, -EINVAL);
-
- dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
+ gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
spin_lock_irqsave(&ucs->lock, flags);
if (ucs->pending) {
spin_unlock_irqrestore(&ucs->lock, flags);
- err("submission of request 0x%02x failed: request 0x%02x still pending",
- req, ucs->pending);
- return -EBUSY;
- }
- if (ucs->urb_ctrl->status == -EINPROGRESS) {
- spin_unlock_irqrestore(&ucs->lock, flags);
- err("could not submit request 0x%02x: URB busy", req);
+ dev_err(bcs->cs->dev,
+ "submission of request 0x%02x failed: "
+ "request 0x%02x still pending\n",
+ req, ucs->pending);
return -EBUSY;
}
@@ -1469,19 +1452,19 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
ucs->dr_ctrl.wIndex = 0;
ucs->dr_ctrl.wLength = 0;
usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
- usb_sndctrlpipe(ucs->udev, 0),
- (unsigned char*) &ucs->dr_ctrl, NULL, 0,
- write_ctrl_callback, ucs);
+ usb_sndctrlpipe(ucs->udev, 0),
+ (unsigned char*) &ucs->dr_ctrl, NULL, 0,
+ write_ctrl_callback, ucs);
if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) {
- err("could not submit request 0x%02x: %s",
- req, get_usb_statmsg(ret));
+ dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n",
+ req, get_usb_statmsg(ret));
spin_unlock_irqrestore(&ucs->lock, flags);
return ret;
}
ucs->pending = req;
if (timeout > 0) {
- dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+ gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10;
ucs->timer_ctrl.data = (unsigned long) bcs;
ucs->timer_ctrl.function = req_timeout;
@@ -1503,23 +1486,36 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
static int gigaset_init_bchannel(struct bc_state *bcs)
{
int req, ret;
+ unsigned long flags;
- IFNULLRETVAL(bcs, -EINVAL);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (unlikely(!bcs->cs->connected)) {
+ gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return -ENODEV;
+ }
if ((ret = starturbs(bcs)) < 0) {
- err("could not start isochronous I/O for channel %d",
- bcs->channel + 1);
- error_hangup(bcs);
+ dev_err(bcs->cs->dev,
+ "could not start isochronous I/O for channel B%d: %s\n",
+ bcs->channel + 1,
+ ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
+ if (ret != -ENODEV)
+ error_hangup(bcs);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
- err("could not open channel %d: %s",
- bcs->channel + 1, get_usb_statmsg(ret));
+ dev_err(bcs->cs->dev, "could not open channel B%d\n",
+ bcs->channel + 1);
stopurbs(bcs->hw.bas);
- error_hangup(bcs);
+ if (ret != -ENODEV)
+ error_hangup(bcs);
}
+
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
@@ -1536,20 +1532,30 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
static int gigaset_close_bchannel(struct bc_state *bcs)
{
int req, ret;
+ unsigned long flags;
- IFNULLRETVAL(bcs, -EINVAL);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (unlikely(!bcs->cs->connected)) {
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ return -ENODEV;
+ }
if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
(bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
/* channel not running: just signal common.c */
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
gigaset_bchannel_down(bcs);
return 0;
}
+ /* channel running: tell device to close it */
req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
- err("could not submit HD_CLOSE_BxCHANNEL request: %s",
- get_usb_statmsg(ret));
+ dev_err(bcs->cs->dev, "closing channel B%d failed\n",
+ bcs->channel + 1);
+
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
@@ -1564,17 +1570,13 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
*/
static void complete_cb(struct cardstate *cs)
{
- struct cmdbuf_t *cb;
-
- IFNULLRET(cs);
- cb = cs->cmdbuf;
- IFNULLRET(cb);
+ struct cmdbuf_t *cb = cs->cmdbuf;
/* unqueue completed buffer */
cs->cmdbytes -= cs->curlen;
- dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD,
- "write_command: sent %u bytes, %u left",
- cs->curlen, cs->cmdbytes);
+ gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD,
+ "write_command: sent %u bytes, %u left",
+ cs->curlen, cs->cmdbytes);
if ((cs->cmdbuf = cb->next) != NULL) {
cs->cmdbuf->prev = NULL;
cs->curlen = cs->cmdbuf->len;
@@ -1589,8 +1591,6 @@ static void complete_cb(struct cardstate *cs)
kfree(cb);
}
-static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
-
/* write_command_callback
* USB completion handler for AT command transmission
* called by the USB subsystem in interrupt context
@@ -1600,40 +1600,43 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
*/
static void write_command_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs;
+ struct cardstate *cs = urb->context;
+ struct bas_cardstate *ucs = cs->hw.bas;
unsigned long flags;
- struct bas_cardstate *ucs;
- IFNULLRET(urb);
- cs = (struct cardstate *) urb->context;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
+ update_basstate(ucs, 0, BS_ATWRPEND);
/* check status */
switch (urb->status) {
case 0: /* normal completion */
break;
- case -ENOENT: /* canceled */
- case -ECONNRESET: /* canceled (async) */
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
/* ignore silently */
- dbg(DEBUG_USBREQ,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
default: /* any failure */
if (++ucs->retry_cmd_out > BAS_RETRY) {
- warn("command write: %s, giving up after %d retries",
- get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+ dev_warn(cs->dev,
+ "command write: %s, "
+ "giving up after %d retries\n",
+ get_usb_statmsg(urb->status),
+ ucs->retry_cmd_out);
break;
}
if (cs->cmdbuf == NULL) {
- warn("command write: %s, cannot retry - cmdbuf gone",
- get_usb_statmsg(urb->status));
+ dev_warn(cs->dev,
+ "command write: %s, "
+ "cannot retry - cmdbuf gone\n",
+ get_usb_statmsg(urb->status));
break;
}
- notice("command write: %s, retry %d",
- get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+ dev_notice(cs->dev, "command write: %s, retry %d\n",
+ get_usb_statmsg(urb->status), ucs->retry_cmd_out);
if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0)
/* resubmitted - bypass regular exit block */
return;
@@ -1655,13 +1658,9 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs)
static void atrdy_timeout(unsigned long data)
{
struct cardstate *cs = (struct cardstate *) data;
- struct bas_cardstate *ucs;
-
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
+ struct bas_cardstate *ucs = cs->hw.bas;
- warn("timeout waiting for HD_READY_SEND_ATDATA");
+ dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n");
/* fake the missing signal - what else can I do? */
update_basstate(ucs, BS_ATREADY, BS_ATTIMER);
@@ -1676,24 +1675,19 @@ static void atrdy_timeout(unsigned long data)
* len length of command to send
* return value:
* 0 on success
- * -EFAULT if a NULL pointer is encountered somewhere
* -EBUSY if another request is pending
* any URB submission error code
*/
static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
{
- struct bas_cardstate *ucs;
- int ret;
-
- IFNULLRETVAL(cs, -EFAULT);
- ucs = cs->hw.bas;
- IFNULLRETVAL(ucs, -EFAULT);
- IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT);
+ struct bas_cardstate *ucs = cs->hw.bas;
+ int rc;
- dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
+ gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
- if (ucs->urb_cmd_out->status == -EINPROGRESS) {
- err("could not submit HD_WRITE_ATMESSAGE: URB busy");
+ if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) {
+ dev_err(cs->dev,
+ "could not submit HD_WRITE_ATMESSAGE: URB busy\n");
return -EBUSY;
}
@@ -1706,25 +1700,22 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
usb_sndctrlpipe(ucs->udev, 0),
(unsigned char*) &ucs->dr_cmd_out, buf, len,
write_command_callback, cs);
-
- if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) {
- err("could not submit HD_WRITE_ATMESSAGE: %s",
- get_usb_statmsg(ret));
- return ret;
+ rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC);
+ if (unlikely(rc)) {
+ update_basstate(ucs, 0, BS_ATWRPEND);
+ dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n",
+ get_usb_rcmsg(rc));
+ return rc;
}
- /* submitted successfully */
- update_basstate(ucs, 0, BS_ATREADY);
-
- /* start timeout if necessary */
- if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) {
- dbg(DEBUG_OUTPUT,
- "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT);
+ /* submitted successfully, start timeout if necessary */
+ if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) {
+ gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs",
+ ATRDY_TIMEOUT);
ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
ucs->timer_atrdy.data = (unsigned long) cs;
ucs->timer_atrdy.function = atrdy_timeout;
add_timer(&ucs->timer_atrdy);
- update_basstate(ucs, BS_ATTIMER, 0);
}
return 0;
}
@@ -1740,21 +1731,16 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
static int start_cbsend(struct cardstate *cs)
{
struct cmdbuf_t *cb;
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = cs->hw.bas;
unsigned long flags;
int rc;
int retval = 0;
- IFNULLRETVAL(cs, -EFAULT);
- ucs = cs->hw.bas;
- IFNULLRETVAL(ucs, -EFAULT);
-
/* check if AT channel is open */
if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
- dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open");
+ gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
if (rc < 0) {
- err("could not open AT channel");
/* flush command queue */
spin_lock_irqsave(&cs->cmdlock, flags);
while (cs->cmdbuf != NULL)
@@ -1792,27 +1778,23 @@ static int start_cbsend(struct cardstate *cs)
* cs controller state structure
* buf command string to send
* len number of bytes to send (max. IF_WRITEBUF)
- * wake_tasklet tasklet to run when transmission is completed (NULL if none)
+ * wake_tasklet tasklet to run when transmission is completed
+ * (NULL if none)
* return value:
* number of bytes queued on success
* error code < 0 on error
*/
static int gigaset_write_cmd(struct cardstate *cs,
- const unsigned char *buf, int len,
- struct tasklet_struct *wake_tasklet)
+ const unsigned char *buf, int len,
+ struct tasklet_struct *wake_tasklet)
{
struct cmdbuf_t *cb;
unsigned long flags;
int status;
gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
- DEBUG_TRANSCMD : DEBUG_LOCKCMD,
- "CMD Transmit", len, buf, 0);
-
- if (!atomic_read(&cs->connected)) {
- err("%s: not connected", __func__);
- return -ENODEV;
- }
+ DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+ "CMD Transmit", len, buf);
if (len <= 0)
return 0; /* nothing to do */
@@ -1820,7 +1802,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
if (len > IF_WRITEBUF)
len = IF_WRITEBUF;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
- err("%s: out of memory", __func__);
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
return -ENOMEM;
}
@@ -1842,14 +1824,21 @@ static int gigaset_write_cmd(struct cardstate *cs,
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (unlikely(!cs->connected)) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ return -ENODEV;
+ }
status = start_cbsend(cs);
-
+ spin_unlock_irqrestore(&cs->lock, flags);
return status < 0 ? status : len;
}
/* gigaset_write_room
* tty_driver.write_room interface routine
- * return number of characters the driver will accept to be written via gigaset_write_cmd
+ * return number of characters the driver will accept to be written via
+ * gigaset_write_cmd
* parameter:
* controller state structure
* return value:
@@ -1904,12 +1893,32 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
*/
static int gigaset_freebcshw(struct bc_state *bcs)
{
- if (!bcs->hw.bas)
+ struct bas_bc_state *ubc = bcs->hw.bas;
+ int i;
+
+ if (!ubc)
return 0;
- if (bcs->hw.bas->isooutbuf)
- kfree(bcs->hw.bas->isooutbuf);
- kfree(bcs->hw.bas);
+ /* kill URBs and tasklets before freeing - better safe than sorry */
+ atomic_set(&ubc->running, 0);
+ for (i = 0; i < BAS_OUTURBS; ++i)
+ if (ubc->isoouturbs[i].urb) {
+ gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d",
+ __func__, i);
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ }
+ for (i = 0; i < BAS_INURBS; ++i)
+ if (ubc->isoinurbs[i]) {
+ gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d",
+ __func__, i);
+ usb_kill_urb(ubc->isoinurbs[i]);
+ usb_free_urb(ubc->isoinurbs[i]);
+ }
+ tasklet_kill(&ubc->sent_tasklet);
+ tasklet_kill(&ubc->rcvd_tasklet);
+ kfree(ubc->isooutbuf);
+ kfree(ubc);
bcs->hw.bas = NULL;
return 1;
}
@@ -1947,7 +1956,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
return 0;
}
tasklet_init(&ubc->sent_tasklet,
- &write_iso_tasklet, (unsigned long) bcs);
+ &write_iso_tasklet, (unsigned long) bcs);
spin_lock_init(&ubc->isoinlock);
for (i = 0; i < BAS_INURBS; ++i)
@@ -1968,7 +1977,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
ubc->shared0s = 0;
ubc->stolen0s = 0;
tasklet_init(&ubc->rcvd_tasklet,
- &read_iso_tasklet, (unsigned long) bcs);
+ &read_iso_tasklet, (unsigned long) bcs);
return 1;
}
@@ -1986,13 +1995,9 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
static void gigaset_freecshw(struct cardstate *cs)
{
- struct bas_cardstate *ucs = cs->hw.bas;
-
- del_timer(&ucs->timer_ctrl);
- del_timer(&ucs->timer_atrdy);
- del_timer(&ucs->timer_cmd_in);
-
+ /* timers, URBs and rcvbuf are disposed of in disconnect */
kfree(cs->hw.bas);
+ cs->hw.bas = NULL;
}
static int gigaset_initcshw(struct cardstate *cs)
@@ -2027,57 +2032,56 @@ static int gigaset_initcshw(struct cardstate *cs)
*/
static void freeurbs(struct cardstate *cs)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = cs->hw.bas;
struct bas_bc_state *ubc;
int i, j;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
-
for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
- IFNULLCONT(ubc);
for (i = 0; i < BAS_OUTURBS; ++i)
if (ubc->isoouturbs[i].urb) {
usb_kill_urb(ubc->isoouturbs[i].urb);
- dbg(DEBUG_INIT,
- "%s: isoc output URB %d/%d unlinked",
- __func__, j, i);
+ gig_dbg(DEBUG_INIT,
+ "%s: isoc output URB %d/%d unlinked",
+ __func__, j, i);
usb_free_urb(ubc->isoouturbs[i].urb);
ubc->isoouturbs[i].urb = NULL;
}
for (i = 0; i < BAS_INURBS; ++i)
if (ubc->isoinurbs[i]) {
usb_kill_urb(ubc->isoinurbs[i]);
- dbg(DEBUG_INIT,
- "%s: isoc input URB %d/%d unlinked",
- __func__, j, i);
+ gig_dbg(DEBUG_INIT,
+ "%s: isoc input URB %d/%d unlinked",
+ __func__, j, i);
usb_free_urb(ubc->isoinurbs[i]);
ubc->isoinurbs[i] = NULL;
}
}
if (ucs->urb_int_in) {
usb_kill_urb(ucs->urb_int_in);
- dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_int_in);
ucs->urb_int_in = NULL;
}
if (ucs->urb_cmd_out) {
usb_kill_urb(ucs->urb_cmd_out);
- dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: command output URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_cmd_out);
ucs->urb_cmd_out = NULL;
}
if (ucs->urb_cmd_in) {
usb_kill_urb(ucs->urb_cmd_in);
- dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: command input URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_cmd_in);
ucs->urb_cmd_in = NULL;
}
if (ucs->urb_ctrl) {
usb_kill_urb(ucs->urb_ctrl);
- dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: control output URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_ctrl);
ucs->urb_ctrl = NULL;
}
@@ -2097,35 +2101,24 @@ static int gigaset_probe(struct usb_interface *interface,
struct bas_bc_state *ubc;
struct usb_endpoint_descriptor *endpoint;
int i, j;
- int ret;
-
- IFNULLRETVAL(udev, -ENODEV);
-
- dbg(DEBUG_ANY,
- "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
- __func__, le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ int rc;
- /* See if the device offered us matches what we can accept */
- if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) ||
- (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID &&
- le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID &&
- le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID &&
- le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) {
- dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__);
- return -ENODEV;
- }
+ gig_dbg(DEBUG_ANY,
+ "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
/* set required alternate setting */
hostif = interface->cur_altsetting;
if (hostif->desc.bAlternateSetting != 3) {
- dbg(DEBUG_ANY,
- "%s: wrong alternate setting %d - trying to switch",
- __func__, hostif->desc.bAlternateSetting);
+ gig_dbg(DEBUG_ANY,
+ "%s: wrong alternate setting %d - trying to switch",
+ __func__, hostif->desc.bAlternateSetting);
if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) {
- warn("usb_set_interface failed, device %d interface %d altsetting %d",
- udev->devnum, hostif->desc.bInterfaceNumber,
- hostif->desc.bAlternateSetting);
+ dev_warn(&udev->dev, "usb_set_interface failed, "
+ "device %d interface %d altsetting %d\n",
+ udev->devnum, hostif->desc.bInterfaceNumber,
+ hostif->desc.bAlternateSetting);
return -ENODEV;
}
hostif = interface->cur_altsetting;
@@ -2134,68 +2127,50 @@ static int gigaset_probe(struct usb_interface *interface,
/* Reject application specific interfaces
*/
if (hostif->desc.bInterfaceClass != 255) {
- warn("%s: bInterfaceClass == %d",
- __func__, hostif->desc.bInterfaceClass);
+ dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n",
+ __func__, hostif->desc.bInterfaceClass);
return -ENODEV;
}
- info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)",
- __func__, le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ dev_info(&udev->dev,
+ "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
cs = gigaset_getunassignedcs(driver);
if (!cs) {
- err("%s: no free cardstate", __func__);
+ dev_err(&udev->dev, "no free cardstate\n");
return -ENODEV;
}
ucs = cs->hw.bas;
+
+ /* save off device structure ptrs for later use */
+ usb_get_dev(udev);
ucs->udev = udev;
ucs->interface = interface;
+ cs->dev = &interface->dev;
/* allocate URBs:
* - one for the interrupt pipe
* - three for the different uses of the default control pipe
* - three for each isochronous pipe
*/
- ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_int_in) {
- err("No free urbs available");
- goto error;
- }
- ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_cmd_in) {
- err("No free urbs available");
- goto error;
- }
- ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_cmd_out) {
- err("No free urbs available");
- goto error;
- }
- ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_ctrl) {
- err("No free urbs available");
- goto error;
- }
+ if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+ !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+ !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) ||
+ !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL)))
+ goto allocerr;
for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
- for (i = 0; i < BAS_OUTURBS; ++i) {
- ubc->isoouturbs[i].urb =
- usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
- if (!ubc->isoouturbs[i].urb) {
- err("No free urbs available");
- goto error;
- }
- }
- for (i = 0; i < BAS_INURBS; ++i) {
- ubc->isoinurbs[i] =
- usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
- if (!ubc->isoinurbs[i]) {
- err("No free urbs available");
- goto error;
- }
- }
+ for (i = 0; i < BAS_OUTURBS; ++i)
+ if (!(ubc->isoouturbs[i].urb =
+ usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+ goto allocerr;
+ for (i = 0; i < BAS_INURBS; ++i)
+ if (!(ubc->isoinurbs[i] =
+ usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+ goto allocerr;
}
ucs->rcvbuf = NULL;
@@ -2204,35 +2179,37 @@ static int gigaset_probe(struct usb_interface *interface,
/* Fill the interrupt urb and send it to the core */
endpoint = &hostif->endpoint[0].desc;
usb_fill_int_urb(ucs->urb_int_in, udev,
- usb_rcvintpipe(udev,
- (endpoint->bEndpointAddress) & 0x0f),
- ucs->int_in_buf, 3, read_int_callback, cs,
- endpoint->bInterval);
- ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL);
- if (ret) {
- err("could not submit interrupt URB: %s", get_usb_statmsg(ret));
+ usb_rcvintpipe(udev,
+ (endpoint->bEndpointAddress) & 0x0f),
+ ucs->int_in_buf, 3, read_int_callback, cs,
+ endpoint->bInterval);
+ if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) {
+ dev_err(cs->dev, "could not submit interrupt URB: %s\n",
+ get_usb_rcmsg(rc));
goto error;
}
/* tell the device that the driver is ready */
- if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
+ if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
goto error;
/* tell common part that the device is ready */
if (startmode == SM_LOCKED)
atomic_set(&cs->mstate, MS_LOCKED);
- if (!gigaset_start(cs))
- goto error;
/* save address of controller structure */
usb_set_intfdata(interface, cs);
- /* set up device sysfs */
- gigaset_init_dev_sysfs(interface);
+ if (!gigaset_start(cs))
+ goto error;
+
return 0;
+allocerr:
+ dev_err(cs->dev, "could not allocate URBs\n");
error:
freeurbs(cs);
+ usb_set_intfdata(interface, NULL);
gigaset_unassign(cs);
return -ENODEV;
}
@@ -2244,24 +2221,38 @@ static void gigaset_disconnect(struct usb_interface *interface)
{
struct cardstate *cs;
struct bas_cardstate *ucs;
-
- /* clear device sysfs */
- gigaset_free_dev_sysfs(interface);
+ int j;
cs = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
- IFNULLRET(cs);
ucs = cs->hw.bas;
- IFNULLRET(ucs);
- info("disconnecting GigaSet base");
+ dev_info(cs->dev, "disconnecting Gigaset base\n");
+
+ /* mark base as not ready, all channels disconnected */
+ atomic_set(&ucs->basstate, 0);
+
+ /* tell LL all channels are down */
+ //FIXME shouldn't gigaset_stop() do this?
+ for (j = 0; j < 2; ++j)
+ gigaset_bchannel_down(cs->bcs + j);
+
+ /* stop driver (common part) */
gigaset_stop(cs);
+
+ /* stop timers and URBs, free ressources */
+ del_timer_sync(&ucs->timer_ctrl);
+ del_timer_sync(&ucs->timer_atrdy);
+ del_timer_sync(&ucs->timer_cmd_in);
freeurbs(cs);
+ usb_set_intfdata(interface, NULL);
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- atomic_set(&ucs->basstate, 0);
+ usb_put_dev(ucs->udev);
+ ucs->interface = NULL;
+ ucs->udev = NULL;
+ cs->dev = NULL;
gigaset_unassign(cs);
}
@@ -2293,13 +2284,14 @@ static int __init bas_gigaset_init(void)
/* allocate memory for our driver state and intialize it */
if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
- GIGASET_MODULENAME, GIGASET_DEVNAME,
- GIGASET_DEVFSNAME, &gigops,
- THIS_MODULE)) == NULL)
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ GIGASET_DEVFSNAME, &gigops,
+ THIS_MODULE)) == NULL)
goto error;
/* allocate memory for our device state and intialize it */
- cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, GIGASET_MODULENAME);
+ cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode,
+ GIGASET_MODULENAME);
if (!cardstate)
goto error;
@@ -2328,22 +2320,35 @@ error: if (cardstate)
*/
static void __exit bas_gigaset_exit(void)
{
+ struct bas_cardstate *ucs = cardstate->hw.bas;
+
gigaset_blockdriver(driver); /* => probe will fail
- * => no gigaset_start any more
- */
+ * => no gigaset_start any more
+ */
gigaset_shutdown(cardstate);
/* from now on, no isdn callback should be possible */
- if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) {
- dbg(DEBUG_ANY, "closing AT channel");
- if (req_submit(cardstate->bcs,
- HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) {
- /* successfully submitted - wait for completion */
- //wait_event_interruptible(cs->initwait, !cs->hw.bas->pending);
- //FIXME need own wait queue? wakeup?
- }
+ /* close all still open channels */
+ if (atomic_read(&ucs->basstate) & BS_B1OPEN) {
+ gig_dbg(DEBUG_INIT, "closing B1 channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
+ }
+ if (atomic_read(&ucs->basstate) & BS_B2OPEN) {
+ gig_dbg(DEBUG_INIT, "closing B2 channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
+ }
+ if (atomic_read(&ucs->basstate) & BS_ATOPEN) {
+ gig_dbg(DEBUG_INIT, "closing AT channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
}
+ atomic_set(&ucs->basstate, 0);
/* deregister this driver with the USB subsystem */
usb_deregister(&gigaset_usb_driver);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 64371995c1a9..e55767b2ccd3 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -1,7 +1,7 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
* Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>.
*
@@ -11,10 +11,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -23,7 +19,7 @@
#include <linux/moduleparam.h>
/* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
#define DRIVER_DESC "Driver for Gigaset 307x"
/* Module parameters */
@@ -32,21 +28,10 @@ EXPORT_SYMBOL_GPL(gigaset_debuglevel);
module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "debug level");
-/*======================================================================
- Prototypes of internal functions
- */
-
-//static void gigaset_process_response(int resp_code, int parameter,
-// struct at_state_t *at_state,
-// unsigned char ** pstring);
-static struct cardstate *alloc_cs(struct gigaset_driver *drv);
-static void free_cs(struct cardstate *cs);
-static void make_valid(struct cardstate *cs, unsigned mask);
-static void make_invalid(struct cardstate *cs, unsigned mask);
-
-#define VALID_MINOR 0x01
-#define VALID_ID 0x02
-#define ASSIGNED 0x04
+/* driver state flags */
+#define VALID_MINOR 0x01
+#define VALID_ID 0x02
+#define ASSIGNED 0x04
/* bitwise byte inversion table */
__u8 gigaset_invtab[256] = {
@@ -86,42 +71,40 @@ __u8 gigaset_invtab[256] = {
EXPORT_SYMBOL_GPL(gigaset_invtab);
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
- size_t len, const unsigned char *buf, int from_user)
+ size_t len, const unsigned char *buf)
{
unsigned char outbuf[80];
- unsigned char inbuf[80 - 1];
- size_t numin;
- const unsigned char *in;
+ unsigned char c;
size_t space = sizeof outbuf - 1;
unsigned char *out = outbuf;
+ size_t numin = len;
- if (!from_user) {
- in = buf;
- numin = len;
- } else {
- numin = len < sizeof inbuf ? len : sizeof inbuf;
- in = inbuf;
- if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) {
- strncpy(inbuf, "<FAULT>", sizeof inbuf);
- numin = sizeof "<FAULT>" - 1;
+ while (numin--) {
+ c = *buf++;
+ if (c == '~' || c == '^' || c == '\\') {
+ if (!space--)
+ break;
+ *out++ = '\\';
}
- }
-
- for (; numin && space; --numin, ++in) {
- --space;
- if (*in >= 32)
- *out++ = *in;
- else {
+ if (c & 0x80) {
+ if (!space--)
+ break;
+ *out++ = '~';
+ c ^= 0x80;
+ }
+ if (c < 0x20 || c == 0x7f) {
+ if (!space--)
+ break;
*out++ = '^';
- if (space) {
- *out++ = '@' + *in;
- --space;
- }
+ c ^= 0x40;
}
+ if (!space--)
+ break;
+ *out++ = c;
}
*out = 0;
- dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
+ gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
}
EXPORT_SYMBOL_GPL(gigaset_dbg_buffer);
@@ -146,11 +129,6 @@ int gigaset_enterconfigmode(struct cardstate *cs)
{
int i, r;
- if (!atomic_read(&cs->connected)) {
- err("not connected!");
- return -1;
- }
-
cs->control_state = TIOCM_RTS; //FIXME
r = setflags(cs, TIOCM_DTR, 200);
@@ -174,7 +152,7 @@ int gigaset_enterconfigmode(struct cardstate *cs)
return 0;
error:
- err("error %d on setuartbits!\n", -r);
+ dev_err(cs->dev, "error %d on setuartbits\n", -r);
cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value?
cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);
@@ -187,13 +165,13 @@ static int test_timeout(struct at_state_t *at_state)
return 0;
if (--at_state->timer_expires) {
- dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
- at_state, at_state->timer_expires);
+ gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
+ at_state, at_state->timer_expires);
return 0;
}
if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
- atomic_read(&at_state->timer_index), NULL)) {
+ at_state->timer_index, NULL)) {
//FIXME what should we do?
}
@@ -221,10 +199,10 @@ static void timer_tick(unsigned long data)
if (test_timeout(at_state))
timeout = 1;
- if (atomic_read(&cs->running)) {
- mod_timer(&cs->timer, jiffies + GIG_TICK);
+ if (cs->running) {
+ mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK));
if (timeout) {
- dbg(DEBUG_CMD, "scheduling timeout");
+ gig_dbg(DEBUG_CMD, "scheduling timeout");
tasklet_schedule(&cs->event_tasklet);
}
}
@@ -238,13 +216,14 @@ int gigaset_get_channel(struct bc_state *bcs)
spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->use_count) {
- dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "could not allocate channel %d",
+ bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
return 0;
}
++bcs->use_count;
bcs->busy = 1;
- dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
return 1;
}
@@ -255,13 +234,13 @@ void gigaset_free_channel(struct bc_state *bcs)
spin_lock_irqsave(&bcs->cs->lock, flags);
if (!bcs->busy) {
- dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
return;
}
--bcs->use_count;
bcs->busy = 0;
- dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
}
@@ -274,14 +253,14 @@ int gigaset_get_channels(struct cardstate *cs)
for (i = 0; i < cs->channels; ++i)
if (cs->bcs[i].use_count) {
spin_unlock_irqrestore(&cs->lock, flags);
- dbg(DEBUG_ANY, "could not allocated all channels");
+ gig_dbg(DEBUG_ANY, "could not allocate all channels");
return 0;
}
for (i = 0; i < cs->channels; ++i)
++cs->bcs[i].use_count;
spin_unlock_irqrestore(&cs->lock, flags);
- dbg(DEBUG_ANY, "allocated all channels");
+ gig_dbg(DEBUG_ANY, "allocated all channels");
return 1;
}
@@ -291,7 +270,7 @@ void gigaset_free_channels(struct cardstate *cs)
unsigned long flags;
int i;
- dbg(DEBUG_ANY, "unblocking all channels");
+ gig_dbg(DEBUG_ANY, "unblocking all channels");
spin_lock_irqsave(&cs->lock, flags);
for (i = 0; i < cs->channels; ++i)
--cs->bcs[i].use_count;
@@ -303,7 +282,7 @@ void gigaset_block_channels(struct cardstate *cs)
unsigned long flags;
int i;
- dbg(DEBUG_ANY, "blocking all channels");
+ gig_dbg(DEBUG_ANY, "blocking all channels");
spin_lock_irqsave(&cs->lock, flags);
for (i = 0; i < cs->channels; ++i)
++cs->bcs[i].use_count;
@@ -314,25 +293,27 @@ static void clear_events(struct cardstate *cs)
{
struct event_t *ev;
unsigned head, tail;
+ unsigned long flags;
- /* no locking needed (no reader/writer allowed) */
+ spin_lock_irqsave(&cs->ev_lock, flags);
- head = atomic_read(&cs->ev_head);
- tail = atomic_read(&cs->ev_tail);
+ head = cs->ev_head;
+ tail = cs->ev_tail;
while (tail != head) {
ev = cs->events + head;
kfree(ev->ptr);
-
head = (head + 1) % MAX_EVENTS;
}
- atomic_set(&cs->ev_head, tail);
+ cs->ev_head = tail;
+
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
}
struct event_t *gigaset_add_event(struct cardstate *cs,
- struct at_state_t *at_state, int type,
- void *ptr, int parameter, void *arg)
+ struct at_state_t *at_state, int type,
+ void *ptr, int parameter, void *arg)
{
unsigned long flags;
unsigned next, tail;
@@ -340,9 +321,9 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
spin_lock_irqsave(&cs->ev_lock, flags);
- tail = atomic_read(&cs->ev_tail);
+ tail = cs->ev_tail;
next = (tail + 1) % MAX_EVENTS;
- if (unlikely(next == atomic_read(&cs->ev_head)))
+ if (unlikely(next == cs->ev_head))
err("event queue full");
else {
event = cs->events + tail;
@@ -352,7 +333,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
event->ptr = ptr;
event->arg = arg;
event->parameter = parameter;
- atomic_set(&cs->ev_tail, next);
+ cs->ev_tail = next;
}
spin_unlock_irqrestore(&cs->ev_lock, flags);
@@ -391,14 +372,14 @@ static void gigaset_freebcs(struct bc_state *bcs)
{
int i;
- dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
+ gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
if (!bcs->cs->ops->freebcshw(bcs)) {
- dbg(DEBUG_INIT, "failed");
+ gig_dbg(DEBUG_INIT, "failed");
}
- dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
+ gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
- dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
+ gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
if (bcs->skb)
dev_kfree_skb(bcs->skb);
@@ -408,6 +389,52 @@ static void gigaset_freebcs(struct bc_state *bcs)
}
}
+static struct cardstate *alloc_cs(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+ unsigned i;
+ static struct cardstate *ret = NULL;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ for (i = 0; i < drv->minors; ++i) {
+ if (!(drv->flags[i] & VALID_MINOR)) {
+ drv->flags[i] = VALID_MINOR;
+ ret = drv->cs + i;
+ }
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&drv->lock, flags);
+ return ret;
+}
+
+static void free_cs(struct cardstate *cs)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] = 0;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_valid(struct cardstate *cs, unsigned mask)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] |= mask;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_invalid(struct cardstate *cs, unsigned mask)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] &= ~mask;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
void gigaset_freecs(struct cardstate *cs)
{
int i;
@@ -416,7 +443,7 @@ void gigaset_freecs(struct cardstate *cs)
if (!cs)
return;
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->bcs)
goto f_cs;
@@ -424,8 +451,9 @@ void gigaset_freecs(struct cardstate *cs)
goto f_bcs;
spin_lock_irqsave(&cs->lock, flags);
- atomic_set(&cs->running, 0);
- spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */
+ cs->running = 0;
+ spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
+ not rescheduled below */
tasklet_kill(&cs->event_tasklet);
del_timer_sync(&cs->timer);
@@ -434,7 +462,7 @@ void gigaset_freecs(struct cardstate *cs)
default:
gigaset_if_free(cs);
- dbg(DEBUG_INIT, "clearing hw");
+ gig_dbg(DEBUG_INIT, "clearing hw");
cs->ops->freecshw(cs);
//FIXME cmdbuf
@@ -443,36 +471,36 @@ void gigaset_freecs(struct cardstate *cs)
case 2: /* error in initcshw */
/* Deregister from LL */
make_invalid(cs, VALID_ID);
- dbg(DEBUG_INIT, "clearing iif");
+ gig_dbg(DEBUG_INIT, "clearing iif");
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
/* fall through */
case 1: /* error when regestering to LL */
- dbg(DEBUG_INIT, "clearing at_state");
+ gig_dbg(DEBUG_INIT, "clearing at_state");
clear_at_state(&cs->at_state);
dealloc_at_states(cs);
/* fall through */
case 0: /* error in one call to initbcs */
for (i = 0; i < cs->channels; ++i) {
- dbg(DEBUG_INIT, "clearing bcs[%d]", i);
+ gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
gigaset_freebcs(cs->bcs + i);
}
clear_events(cs);
- dbg(DEBUG_INIT, "freeing inbuf");
+ gig_dbg(DEBUG_INIT, "freeing inbuf");
kfree(cs->inbuf);
}
-f_bcs: dbg(DEBUG_INIT, "freeing bcs[]");
+f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]");
kfree(cs->bcs);
-f_cs: dbg(DEBUG_INIT, "freeing cs");
- up(&cs->sem);
+f_cs: gig_dbg(DEBUG_INIT, "freeing cs");
+ mutex_unlock(&cs->mutex);
free_cs(cs);
}
EXPORT_SYMBOL_GPL(gigaset_freecs);
void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
- struct cardstate *cs, int cid)
+ struct cardstate *cs, int cid)
{
int i;
@@ -482,8 +510,8 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
at_state->pending_commands = 0;
at_state->timer_expires = 0;
at_state->timer_active = 0;
- atomic_set(&at_state->timer_index, 0);
- atomic_set(&at_state->seq_index, 0);
+ at_state->timer_index = 0;
+ at_state->seq_index = 0;
at_state->ConState = 0;
for (i = 0; i < STR_NUM; ++i)
at_state->str_var[i] = NULL;
@@ -501,7 +529,7 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
- struct cardstate *cs, int inputstate)
+ struct cardstate *cs, int inputstate)
/* inbuf->read must be allocated before! */
{
atomic_set(&inbuf->head, 0);
@@ -512,9 +540,50 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
inbuf->inputstate = inputstate;
}
+/* append received bytes to inbuf */
+int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
+ unsigned numbytes)
+{
+ unsigned n, head, tail, bytesleft;
+
+ gig_dbg(DEBUG_INTR, "received %u bytes", numbytes);
+
+ if (!numbytes)
+ return 0;
+
+ bytesleft = numbytes;
+ tail = atomic_read(&inbuf->tail);
+ head = atomic_read(&inbuf->head);
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+
+ while (bytesleft) {
+ if (head > tail)
+ n = head - 1 - tail;
+ else if (head == 0)
+ n = (RBUFSIZE-1) - tail;
+ else
+ n = RBUFSIZE - tail;
+ if (!n) {
+ dev_err(inbuf->cs->dev,
+ "buffer overflow (%u bytes lost)", bytesleft);
+ break;
+ }
+ if (n > bytesleft)
+ n = bytesleft;
+ memcpy(inbuf->data + tail, src, n);
+ bytesleft -= n;
+ tail = (tail + n) % RBUFSIZE;
+ src += n;
+ }
+ gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
+ atomic_set(&inbuf->tail, tail);
+ return numbytes != bytesleft;
+}
+EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
+
/* Initialize the b-channel structure */
static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
- struct cardstate *cs, int channel)
+ struct cardstate *cs, int channel)
{
int i;
@@ -526,7 +595,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->trans_down = 0;
bcs->trans_up = 0;
- dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
+ gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
gigaset_at_init(&bcs->at_state, bcs, cs, -1);
bcs->rcvbytes = 0;
@@ -535,7 +604,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->emptycount = 0;
#endif
- dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
+ gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
bcs->fcs = PPP_INITFCS;
bcs->inputstate = 0;
if (cs->ignoreframes) {
@@ -544,7 +613,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else {
- warn("could not allocate skb");
+ dev_warn(cs->dev, "could not allocate skb\n");
bcs->inputstate |= INS_skip_frame;
}
@@ -559,14 +628,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
for (i = 0; i < AT_NUM; ++i)
bcs->commands[i] = NULL;
- dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
+ gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
if (cs->ops->initbcshw(bcs))
return bcs;
-//error:
- dbg(DEBUG_INIT, " failed");
+ gig_dbg(DEBUG_INIT, " failed");
- dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
+ gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
if (bcs->skb)
dev_kfree_skb(bcs->skb);
@@ -578,9 +646,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
* Calls hardware dependent gigaset_initcshw() function
* Calls B channel initialization function gigaset_initbcs() for each B channel
* parameters:
- * drv hardware driver the device belongs to
+ * drv hardware driver the device belongs to
* channels number of B channels supported by device
- * onechannel !=0: B channel data and AT commands share one communication channel
+ * onechannel !=0: B channel data and AT commands share one
+ * communication channel
* ==0: B channels have separate communication channels
* ignoreframes number of frames to ignore after setting up B channel
* cidmode !=0: start in CallID mode
@@ -593,17 +662,18 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
int cidmode, const char *modulename)
{
struct cardstate *cs = NULL;
+ unsigned long flags;
int i;
- dbg(DEBUG_INIT, "allocating cs");
+ gig_dbg(DEBUG_INIT, "allocating cs");
cs = alloc_cs(drv);
if (!cs)
goto error;
- dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
+ gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
if (!cs->bcs)
goto error;
- dbg(DEBUG_INIT, "allocating inbuf");
+ gig_dbg(DEBUG_INIT, "allocating inbuf");
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
if (!cs->inbuf)
goto error;
@@ -613,19 +683,23 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->onechannel = onechannel;
cs->ignoreframes = ignoreframes;
INIT_LIST_HEAD(&cs->temp_at_states);
- atomic_set(&cs->running, 0);
+ cs->running = 0;
init_timer(&cs->timer); /* clear next & prev */
spin_lock_init(&cs->ev_lock);
- atomic_set(&cs->ev_tail, 0);
- atomic_set(&cs->ev_head, 0);
- init_MUTEX_LOCKED(&cs->sem);
- tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs);
+ cs->ev_tail = 0;
+ cs->ev_head = 0;
+ mutex_init(&cs->mutex);
+ mutex_lock(&cs->mutex);
+
+ tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
+ (unsigned long) cs);
atomic_set(&cs->commands_pending, 0);
cs->cur_at_seq = 0;
cs->gotfwver = -1;
cs->open_count = 0;
+ cs->dev = NULL;
cs->tty = NULL;
- atomic_set(&cs->cidmode, cidmode != 0);
+ cs->cidmode = cidmode != 0;
//if(onechannel) { //FIXME
cs->tabnocid = gigaset_tab_nocid_m10x;
@@ -642,50 +716,43 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
atomic_set(&cs->mstate, MS_UNINITIALIZED);
for (i = 0; i < channels; ++i) {
- dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
+ gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
if (!gigaset_initbcs(cs->bcs + i, cs, i))
goto error;
}
++cs->cs_init;
- dbg(DEBUG_INIT, "setting up at_state");
+ gig_dbg(DEBUG_INIT, "setting up at_state");
spin_lock_init(&cs->lock);
gigaset_at_init(&cs->at_state, NULL, cs, 0);
cs->dle = 0;
cs->cbytes = 0;
- dbg(DEBUG_INIT, "setting up inbuf");
+ gig_dbg(DEBUG_INIT, "setting up inbuf");
if (onechannel) { //FIXME distinction necessary?
gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
} else
gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command);
- atomic_set(&cs->connected, 0);
+ cs->connected = 0;
+ cs->isdn_up = 0;
- dbg(DEBUG_INIT, "setting up cmdbuf");
+ gig_dbg(DEBUG_INIT, "setting up cmdbuf");
cs->cmdbuf = cs->lastcmdbuf = NULL;
spin_lock_init(&cs->cmdlock);
cs->curlen = 0;
cs->cmdbytes = 0;
- /*
- * Tell the ISDN4Linux subsystem (the LL) that
- * a driver for a USB-Device is available !
- * If this is done, "isdnctrl" is able to bind a device for this driver even
- * if no physical usb-device is currently connected.
- * But this device will just be accessable if a physical USB device is connected
- * (via "gigaset_probe") .
- */
- dbg(DEBUG_INIT, "setting up iif");
+ gig_dbg(DEBUG_INIT, "setting up iif");
if (!gigaset_register_to_LL(cs, modulename)) {
- err("register_isdn=>error");
+ err("register_isdn failed");
goto error;
}
make_valid(cs, VALID_ID);
++cs->cs_init;
- dbg(DEBUG_INIT, "setting up hw");
+ gig_dbg(DEBUG_INIT, "setting up hw");
if (!cs->ops->initcshw(cs))
goto error;
@@ -693,27 +760,28 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
gigaset_if_init(cs);
- atomic_set(&cs->running, 1);
- cs->timer.data = (unsigned long) cs;
- cs->timer.function = timer_tick;
- cs->timer.expires = jiffies + GIG_TICK;
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->running = 1;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
+ cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
/* FIXME: can jiffies increase too much until the timer is added?
* Same problem(?) with mod_timer() in timer_tick(). */
add_timer(&cs->timer);
- dbg(DEBUG_INIT, "cs initialized!");
- up(&cs->sem);
+ gig_dbg(DEBUG_INIT, "cs initialized");
+ mutex_unlock(&cs->mutex);
return cs;
error: if (cs)
- up(&cs->sem);
- dbg(DEBUG_INIT, "failed");
+ mutex_unlock(&cs->mutex);
+ gig_dbg(DEBUG_INIT, "failed");
gigaset_freecs(cs);
return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initcs);
-/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */
+/* ReInitialize the b-channel structure on hangup */
void gigaset_bcs_reinit(struct bc_state *bcs)
{
struct sk_buff *skb;
@@ -723,12 +791,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
while ((skb = skb_dequeue(&bcs->squeue)) != NULL)
dev_kfree_skb(skb);
- spin_lock_irqsave(&cs->lock, flags); //FIXME
+ spin_lock_irqsave(&cs->lock, flags);
clear_at_state(&bcs->at_state);
bcs->at_state.ConState = 0;
bcs->at_state.timer_active = 0;
bcs->at_state.timer_expires = 0;
- bcs->at_state.cid = -1; /* No CID defined */
+ bcs->at_state.cid = -1; /* No CID defined */
spin_unlock_irqrestore(&cs->lock, flags);
bcs->inputstate = 0;
@@ -803,11 +871,14 @@ static void cleanup_cs(struct cardstate *cs)
int gigaset_start(struct cardstate *cs)
{
- if (down_interruptible(&cs->sem))
+ unsigned long flags;
+
+ if (mutex_lock_interruptible(&cs->mutex))
return 0;
- //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor);
- atomic_set(&cs->connected, 1);
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->connected = 1;
+ spin_unlock_irqrestore(&cs->lock, flags);
if (atomic_read(&cs->mstate) != MS_LOCKED) {
cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
@@ -826,23 +897,26 @@ int gigaset_start(struct cardstate *cs)
goto error;
}
- dbg(DEBUG_CMD, "scheduling START");
+ gig_dbg(DEBUG_CMD, "scheduling START");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
- up(&cs->sem);
+ /* set up device sysfs */
+ gigaset_init_dev_sysfs(cs);
+
+ mutex_unlock(&cs->mutex);
return 1;
error:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return 0;
}
EXPORT_SYMBOL_GPL(gigaset_start);
void gigaset_shutdown(struct cardstate *cs)
{
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
cs->waiting = 1;
@@ -851,11 +925,11 @@ void gigaset_shutdown(struct cardstate *cs)
goto exit;
}
- dbg(DEBUG_CMD, "scheduling SHUTDOWN");
+ gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
gigaset_schedule_event(cs);
if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
- warn("aborted");
+ warn("%s: aborted", __func__);
//FIXME
}
@@ -872,15 +946,13 @@ void gigaset_shutdown(struct cardstate *cs)
cleanup_cs(cs);
exit:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
EXPORT_SYMBOL_GPL(gigaset_shutdown);
void gigaset_stop(struct cardstate *cs)
{
- down(&cs->sem);
-
- atomic_set(&cs->connected, 0);
+ mutex_lock(&cs->mutex);
cs->waiting = 1;
@@ -889,21 +961,21 @@ void gigaset_stop(struct cardstate *cs)
goto exit;
}
- dbg(DEBUG_CMD, "scheduling STOP");
+ gig_dbg(DEBUG_CMD, "scheduling STOP");
gigaset_schedule_event(cs);
if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
- warn("aborted");
+ warn("%s: aborted", __func__);
//FIXME
}
- /* Tell the LL that the device is not available .. */
- gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer?
+ /* clear device sysfs */
+ gigaset_free_dev_sysfs(cs);
cleanup_cs(cs);
exit:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
EXPORT_SYMBOL_GPL(gigaset_stop);
@@ -947,31 +1019,25 @@ void gigaset_debugdrivers(void)
spin_lock_irqsave(&driver_lock, flags);
list_for_each_entry(drv, &drivers, list) {
- dbg(DEBUG_DRIVER, "driver %p", drv);
+ gig_dbg(DEBUG_DRIVER, "driver %p", drv);
spin_lock(&drv->lock);
for (i = 0; i < drv->minors; ++i) {
- dbg(DEBUG_DRIVER, " index %u", i);
- dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]);
+ gig_dbg(DEBUG_DRIVER, " index %u", i);
+ gig_dbg(DEBUG_DRIVER, " flags 0x%02x",
+ drv->flags[i]);
cs = drv->cs + i;
- dbg(DEBUG_DRIVER, " cardstate %p", cs);
- dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index);
- dbg(DEBUG_DRIVER, " driver %p", cs->driver);
- dbg(DEBUG_DRIVER, " i4l id %d", cs->myid);
+ gig_dbg(DEBUG_DRIVER, " cardstate %p", cs);
+ gig_dbg(DEBUG_DRIVER, " minor_index %u",
+ cs->minor_index);
+ gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver);
+ gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid);
}
spin_unlock(&drv->lock);
}
spin_unlock_irqrestore(&driver_lock, flags);
}
-EXPORT_SYMBOL_GPL(gigaset_debugdrivers);
-
-struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
-{
- if (tty->index < 0 || tty->index >= tty->driver->num)
- return NULL;
- return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
-}
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
+static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
{
unsigned long flags;
static struct cardstate *ret = NULL;
@@ -994,6 +1060,13 @@ struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
return ret;
}
+struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
+{
+ if (tty->index < 0 || tty->index >= tty->driver->num)
+ return NULL;
+ return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
+}
+
void gigaset_freedriver(struct gigaset_driver *drv)
{
unsigned long flags;
@@ -1014,20 +1087,20 @@ EXPORT_SYMBOL_GPL(gigaset_freedriver);
/* gigaset_initdriver
* Allocate and initialize gigaset_driver structure. Initialize interface.
* parameters:
- * minor First minor number
- * minors Number of minors this driver can handle
- * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver)
- * devname Name of the device files (prefix without minor number)
- * devfsname Devfs name of the device files without %d
+ * minor First minor number
+ * minors Number of minors this driver can handle
+ * procname Name of the driver
+ * devname Name of the device files (prefix without minor number)
+ * devfsname Devfs name of the device files without %d
* return value:
- * Pointer to the gigaset_driver structure on success, NULL on failure.
+ * Pointer to the gigaset_driver structure on success, NULL on failure.
*/
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
- const char *procname,
- const char *devname,
- const char *devfsname,
- const struct gigaset_ops *ops,
- struct module *owner)
+ const char *procname,
+ const char *devname,
+ const char *devfsname,
+ const struct gigaset_ops *ops,
+ struct module *owner)
{
struct gigaset_driver *drv;
unsigned long flags;
@@ -1036,8 +1109,9 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv = kmalloc(sizeof *drv, GFP_KERNEL);
if (!drv)
return NULL;
+
if (!try_module_get(owner))
- return NULL;
+ goto out1;
drv->cs = NULL;
drv->have_tty = 0;
@@ -1051,10 +1125,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
if (!drv->cs)
- goto out1;
+ goto out2;
+
drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
if (!drv->flags)
- goto out2;
+ goto out3;
for (i = 0; i < minors; ++i) {
drv->flags[i] = 0;
@@ -1071,61 +1146,16 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
return drv;
-out2:
+out3:
kfree(drv->cs);
+out2:
+ module_put(owner);
out1:
kfree(drv);
- module_put(owner);
return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initdriver);
-static struct cardstate *alloc_cs(struct gigaset_driver *drv)
-{
- unsigned long flags;
- unsigned i;
- static struct cardstate *ret = NULL;
-
- spin_lock_irqsave(&drv->lock, flags);
- for (i = 0; i < drv->minors; ++i) {
- if (!(drv->flags[i] & VALID_MINOR)) {
- drv->flags[i] = VALID_MINOR;
- ret = drv->cs + i;
- }
- if (ret)
- break;
- }
- spin_unlock_irqrestore(&drv->lock, flags);
- return ret;
-}
-
-static void free_cs(struct cardstate *cs)
-{
- unsigned long flags;
- struct gigaset_driver *drv = cs->driver;
- spin_lock_irqsave(&drv->lock, flags);
- drv->flags[cs->minor_index] = 0;
- spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_valid(struct cardstate *cs, unsigned mask)
-{
- unsigned long flags;
- struct gigaset_driver *drv = cs->driver;
- spin_lock_irqsave(&drv->lock, flags);
- drv->flags[cs->minor_index] |= mask;
- spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_invalid(struct cardstate *cs, unsigned mask)
-{
- unsigned long flags;
- struct gigaset_driver *drv = cs->driver;
- spin_lock_irqsave(&drv->lock, flags);
- drv->flags[cs->minor_index] &= ~mask;
- spin_unlock_irqrestore(&drv->lock, flags);
-}
-
/* For drivers without fixed assignment device<->cardstate (usb) */
struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
{
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index fdcb80bb21c7..18e05c09b71c 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1,7 +1,7 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
* Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>.
*
@@ -11,82 +11,78 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
/* ========================================================== */
/* bit masks for pending commands */
-#define PC_INIT 0x004
-#define PC_DLE0 0x008
-#define PC_DLE1 0x010
-#define PC_CID 0x080
-#define PC_NOCID 0x100
-#define PC_HUP 0x002
-#define PC_DIAL 0x001
-#define PC_ACCEPT 0x040
-#define PC_SHUTDOWN 0x020
-#define PC_CIDMODE 0x200
-#define PC_UMMODE 0x400
+#define PC_DIAL 0x001
+#define PC_HUP 0x002
+#define PC_INIT 0x004
+#define PC_DLE0 0x008
+#define PC_DLE1 0x010
+#define PC_SHUTDOWN 0x020
+#define PC_ACCEPT 0x040
+#define PC_CID 0x080
+#define PC_NOCID 0x100
+#define PC_CIDMODE 0x200
+#define PC_UMMODE 0x400
/* types of modem responses */
-#define RT_NOTHING 0
-#define RT_ZSAU 1
-#define RT_RING 2
-#define RT_NUMBER 3
-#define RT_STRING 4
-#define RT_HEX 5
-#define RT_ZCAU 6
+#define RT_NOTHING 0
+#define RT_ZSAU 1
+#define RT_RING 2
+#define RT_NUMBER 3
+#define RT_STRING 4
+#define RT_HEX 5
+#define RT_ZCAU 6
/* Possible ASCII responses */
-#define RSP_OK 0
-//#define RSP_BUSY 1
-//#define RSP_CONNECT 2
-#define RSP_ZGCI 3
-#define RSP_RING 4
-#define RSP_ZAOC 5
-#define RSP_ZCSTR 6
-#define RSP_ZCFGT 7
-#define RSP_ZCFG 8
-#define RSP_ZCCR 9
-#define RSP_EMPTY 10
-#define RSP_ZLOG 11
-#define RSP_ZCAU 12
-#define RSP_ZMWI 13
-#define RSP_ZABINFO 14
-#define RSP_ZSMLSTCHG 15
-#define RSP_VAR 100
-#define RSP_ZSAU (RSP_VAR + VAR_ZSAU)
-#define RSP_ZDLE (RSP_VAR + VAR_ZDLE)
-#define RSP_ZVLS (RSP_VAR + VAR_ZVLS)
-#define RSP_ZCTP (RSP_VAR + VAR_ZCTP)
-#define RSP_STR (RSP_VAR + VAR_NUM)
-#define RSP_NMBR (RSP_STR + STR_NMBR)
-#define RSP_ZCPN (RSP_STR + STR_ZCPN)
-#define RSP_ZCON (RSP_STR + STR_ZCON)
-#define RSP_ZBC (RSP_STR + STR_ZBC)
-#define RSP_ZHLC (RSP_STR + STR_ZHLC)
-#define RSP_ERROR -1 /* ERROR */
-#define RSP_WRONG_CID -2 /* unknown cid in cmd */
-//#define RSP_EMPTY -3
-#define RSP_UNKNOWN -4 /* unknown response */
-#define RSP_FAIL -5 /* internal error */
-#define RSP_INVAL -6 /* invalid response */
-
-#define RSP_NONE -19
-#define RSP_STRING -20
-#define RSP_NULL -21
-//#define RSP_RETRYFAIL -22
-//#define RSP_RETRY -23
-//#define RSP_SKIP -24
-#define RSP_INIT -27
-#define RSP_ANY -26
-#define RSP_LAST -28
-#define RSP_NODEV -9
+#define RSP_OK 0
+//#define RSP_BUSY 1
+//#define RSP_CONNECT 2
+#define RSP_ZGCI 3
+#define RSP_RING 4
+#define RSP_ZAOC 5
+#define RSP_ZCSTR 6
+#define RSP_ZCFGT 7
+#define RSP_ZCFG 8
+#define RSP_ZCCR 9
+#define RSP_EMPTY 10
+#define RSP_ZLOG 11
+#define RSP_ZCAU 12
+#define RSP_ZMWI 13
+#define RSP_ZABINFO 14
+#define RSP_ZSMLSTCHG 15
+#define RSP_VAR 100
+#define RSP_ZSAU (RSP_VAR + VAR_ZSAU)
+#define RSP_ZDLE (RSP_VAR + VAR_ZDLE)
+#define RSP_ZVLS (RSP_VAR + VAR_ZVLS)
+#define RSP_ZCTP (RSP_VAR + VAR_ZCTP)
+#define RSP_STR (RSP_VAR + VAR_NUM)
+#define RSP_NMBR (RSP_STR + STR_NMBR)
+#define RSP_ZCPN (RSP_STR + STR_ZCPN)
+#define RSP_ZCON (RSP_STR + STR_ZCON)
+#define RSP_ZBC (RSP_STR + STR_ZBC)
+#define RSP_ZHLC (RSP_STR + STR_ZHLC)
+#define RSP_ERROR -1 /* ERROR */
+#define RSP_WRONG_CID -2 /* unknown cid in cmd */
+//#define RSP_EMPTY -3
+#define RSP_UNKNOWN -4 /* unknown response */
+#define RSP_FAIL -5 /* internal error */
+#define RSP_INVAL -6 /* invalid response */
+
+#define RSP_NONE -19
+#define RSP_STRING -20
+#define RSP_NULL -21
+//#define RSP_RETRYFAIL -22
+//#define RSP_RETRY -23
+//#define RSP_SKIP -24
+#define RSP_INIT -27
+#define RSP_ANY -26
+#define RSP_LAST -28
+#define RSP_NODEV -9
/* actions for process_response */
#define ACT_NOTHING 0
@@ -112,7 +108,7 @@
#define ACT_DISCONNECT 20
#define ACT_CONNECT 21
#define ACT_REMOTEREJECT 22
-#define ACT_CONNTIMEOUT 23
+#define ACT_CONNTIMEOUT 23
#define ACT_REMOTEHUP 24
#define ACT_ABORTHUP 25
#define ACT_ICALL 26
@@ -127,40 +123,40 @@
#define ACT_ERROR 35
#define ACT_ABORTCID 36
#define ACT_ZCAU 37
-#define ACT_NOTIFY_BC_DOWN 38
-#define ACT_NOTIFY_BC_UP 39
-#define ACT_DIAL 40
-#define ACT_ACCEPT 41
-#define ACT_PROTO_L2 42
-#define ACT_HUP 43
-#define ACT_IF_LOCK 44
-#define ACT_START 45
-#define ACT_STOP 46
-#define ACT_FAKEDLE0 47
-#define ACT_FAKEHUP 48
-#define ACT_FAKESDOWN 49
-#define ACT_SHUTDOWN 50
-#define ACT_PROC_CIDMODE 51
-#define ACT_UMODESET 52
-#define ACT_FAILUMODE 53
-#define ACT_CMODESET 54
-#define ACT_FAILCMODE 55
-#define ACT_IF_VER 56
+#define ACT_NOTIFY_BC_DOWN 38
+#define ACT_NOTIFY_BC_UP 39
+#define ACT_DIAL 40
+#define ACT_ACCEPT 41
+#define ACT_PROTO_L2 42
+#define ACT_HUP 43
+#define ACT_IF_LOCK 44
+#define ACT_START 45
+#define ACT_STOP 46
+#define ACT_FAKEDLE0 47
+#define ACT_FAKEHUP 48
+#define ACT_FAKESDOWN 49
+#define ACT_SHUTDOWN 50
+#define ACT_PROC_CIDMODE 51
+#define ACT_UMODESET 52
+#define ACT_FAILUMODE 53
+#define ACT_CMODESET 54
+#define ACT_FAILCMODE 55
+#define ACT_IF_VER 56
#define ACT_CMD 100
/* at command sequences */
-#define SEQ_NONE 0
-#define SEQ_INIT 100
-#define SEQ_DLE0 200
-#define SEQ_DLE1 250
-#define SEQ_CID 300
-#define SEQ_NOCID 350
-#define SEQ_HUP 400
-#define SEQ_DIAL 600
-#define SEQ_ACCEPT 720
-#define SEQ_SHUTDOWN 500
-#define SEQ_CIDMODE 10
-#define SEQ_UMMODE 11
+#define SEQ_NONE 0
+#define SEQ_INIT 100
+#define SEQ_DLE0 200
+#define SEQ_DLE1 250
+#define SEQ_CID 300
+#define SEQ_NOCID 350
+#define SEQ_HUP 400
+#define SEQ_DIAL 600
+#define SEQ_ACCEPT 720
+#define SEQ_SHUTDOWN 500
+#define SEQ_CIDMODE 10
+#define SEQ_UMMODE 11
// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring
@@ -175,7 +171,7 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */
// {ACT_TIMEOUT}},
{RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT,
- {ACT_TIMEOUT}}, /* wait until device is ready */
+ {ACT_TIMEOUT}}, /* wait until device is ready */
{EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */
{RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */
@@ -190,8 +186,8 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */
{RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}},
{EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0,
- ACT_HUPMODEM,
- ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
+ ACT_HUPMODEM,
+ ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
{EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"},
{RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */
@@ -377,6 +373,9 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */
{EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}},
+ /* B channel closed (general case) */
+ {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
+
/* misc. */
{EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME
@@ -393,7 +392,7 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */
#if 0
-static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen
+static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME
{
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
@@ -401,7 +400,7 @@ static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen ueberne
{RSP_LAST,0,0,0,0,0,0}
};
-static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen
+static struct reply_t tab_cid[] = /* no dle mode */ //FIXME
{
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
@@ -412,30 +411,30 @@ static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen ueberneh
static struct resp_type_t resp_type[]=
{
- /*{"", RSP_EMPTY, RT_NOTHING},*/
- {"OK", RSP_OK, RT_NOTHING},
- {"ERROR", RSP_ERROR, RT_NOTHING},
- {"ZSAU", RSP_ZSAU, RT_ZSAU},
- {"ZCAU", RSP_ZCAU, RT_ZCAU},
- {"RING", RSP_RING, RT_RING},
- {"ZGCI", RSP_ZGCI, RT_NUMBER},
- {"ZVLS", RSP_ZVLS, RT_NUMBER},
- {"ZCTP", RSP_ZCTP, RT_NUMBER},
- {"ZDLE", RSP_ZDLE, RT_NUMBER},
- {"ZCFGT", RSP_ZCFGT, RT_NUMBER},
- {"ZCCR", RSP_ZCCR, RT_NUMBER},
- {"ZMWI", RSP_ZMWI, RT_NUMBER},
- {"ZHLC", RSP_ZHLC, RT_STRING},
- {"ZBC", RSP_ZBC, RT_STRING},
- {"NMBR", RSP_NMBR, RT_STRING},
- {"ZCPN", RSP_ZCPN, RT_STRING},
- {"ZCON", RSP_ZCON, RT_STRING},
- {"ZAOC", RSP_ZAOC, RT_STRING},
- {"ZCSTR", RSP_ZCSTR, RT_STRING},
- {"ZCFG", RSP_ZCFG, RT_HEX},
- {"ZLOG", RSP_ZLOG, RT_NOTHING},
- {"ZABINFO", RSP_ZABINFO, RT_NOTHING},
- {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
+ /*{"", RSP_EMPTY, RT_NOTHING},*/
+ {"OK", RSP_OK, RT_NOTHING},
+ {"ERROR", RSP_ERROR, RT_NOTHING},
+ {"ZSAU", RSP_ZSAU, RT_ZSAU},
+ {"ZCAU", RSP_ZCAU, RT_ZCAU},
+ {"RING", RSP_RING, RT_RING},
+ {"ZGCI", RSP_ZGCI, RT_NUMBER},
+ {"ZVLS", RSP_ZVLS, RT_NUMBER},
+ {"ZCTP", RSP_ZCTP, RT_NUMBER},
+ {"ZDLE", RSP_ZDLE, RT_NUMBER},
+ {"ZCFGT", RSP_ZCFGT, RT_NUMBER},
+ {"ZCCR", RSP_ZCCR, RT_NUMBER},
+ {"ZMWI", RSP_ZMWI, RT_NUMBER},
+ {"ZHLC", RSP_ZHLC, RT_STRING},
+ {"ZBC", RSP_ZBC, RT_STRING},
+ {"NMBR", RSP_NMBR, RT_STRING},
+ {"ZCPN", RSP_ZCPN, RT_STRING},
+ {"ZCON", RSP_ZCON, RT_STRING},
+ {"ZAOC", RSP_ZAOC, RT_STRING},
+ {"ZCSTR", RSP_ZCSTR, RT_STRING},
+ {"ZCFG", RSP_ZCFG, RT_HEX},
+ {"ZLOG", RSP_ZLOG, RT_NOTHING},
+ {"ZABINFO", RSP_ZABINFO, RT_NOTHING},
+ {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
{NULL,0,0}
};
@@ -446,9 +445,7 @@ static int isdn_getnum(char *p)
{
int v = -1;
- IFNULLRETVAL(p, -1);
-
- dbg(DEBUG_TRANSCMD, "string: %s", p);
+ gig_dbg(DEBUG_TRANSCMD, "string: %s", p);
while (*p >= '0' && *p <= '9')
v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0');
@@ -465,9 +462,7 @@ static int isdn_gethex(char *p)
int v = 0;
int c;
- IFNULLRETVAL(p, -1);
-
- dbg(DEBUG_TRANSCMD, "string: %s", p);
+ gig_dbg(DEBUG_TRANSCMD, "string: %s", p);
if (!*p)
return -1;
@@ -490,14 +485,6 @@ static int isdn_gethex(char *p)
return v;
}
-static inline void new_index(atomic_t *index, int max)
-{
- if (atomic_read(index) == max) //FIXME race?
- atomic_set(index, 0);
- else
- atomic_inc(index);
-}
-
/* retrieve CID from parsed response
* returns 0 if no CID, -1 if invalid CID, or CID value 1..65535
*/
@@ -536,16 +523,14 @@ void gigaset_handle_modem_response(struct cardstate *cs)
int cid;
int rawstring;
- IFNULLRET(cs);
-
len = cs->cbytes;
if (!len) {
/* ignore additional LFs/CRs (M10x config mode or cx100) */
- dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
+ gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
return;
}
cs->respdata[len] = 0;
- dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
+ gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
argv[0] = cs->respdata;
params = 1;
if (cs->at_state.getstring) {
@@ -561,7 +546,8 @@ void gigaset_handle_modem_response(struct cardstate *cs)
case ',':
case '=':
if (params > MAX_REC_PARAMS) {
- warn("too many parameters in response");
+ dev_warn(cs->dev,
+ "too many parameters in response\n");
/* need last parameter (might be CID) */
params--;
}
@@ -572,33 +558,33 @@ void gigaset_handle_modem_response(struct cardstate *cs)
cid = params > 1 ? cid_of_response(argv[params-1]) : 0;
if (cid < 0) {
gigaset_add_event(cs, &cs->at_state, RSP_INVAL,
- NULL, 0, NULL);
+ NULL, 0, NULL);
return;
}
for (j = 1; j < params; ++j)
argv[j][-1] = 0;
- dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
+ gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
if (cid) {
--params;
- dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
+ gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
}
- dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
+ gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
for (j = 1; j < params; j++)
- dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
+ gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
}
spin_lock_irqsave(&cs->ev_lock, flags);
- head = atomic_read(&cs->ev_head);
- tail = atomic_read(&cs->ev_tail);
+ head = cs->ev_head;
+ tail = cs->ev_tail;
abort = 1;
curarg = 0;
while (curarg < params) {
next = (tail + 1) % MAX_EVENTS;
if (unlikely(next == head)) {
- err("event queue full");
+ dev_err(cs->dev, "event queue full\n");
break;
}
@@ -619,8 +605,9 @@ void gigaset_handle_modem_response(struct cardstate *cs)
if (!rt->response) {
event->type = RSP_UNKNOWN;
- warn("unknown modem response: %s",
- argv[curarg]);
+ dev_warn(cs->dev,
+ "unknown modem response: %s\n",
+ argv[curarg]);
break;
}
@@ -636,7 +623,8 @@ void gigaset_handle_modem_response(struct cardstate *cs)
break;
case RT_RING:
if (!cid) {
- err("received RING without CID!");
+ dev_err(cs->dev,
+ "received RING without CID!\n");
event->type = RSP_INVAL;
abort = 1;
} else {
@@ -664,27 +652,25 @@ void gigaset_handle_modem_response(struct cardstate *cs)
event->parameter = ZSAU_DISCONNECT_REQ;
else {
event->parameter = ZSAU_UNKNOWN;
- warn("%s: unknown parameter %s after ZSAU",
- __func__, argv[curarg]);
+ dev_warn(cs->dev,
+ "%s: unknown parameter %s after ZSAU\n",
+ __func__, argv[curarg]);
}
++curarg;
break;
case RT_STRING:
if (curarg < params) {
- len = strlen(argv[curarg]) + 1;
- event->ptr = kmalloc(len, GFP_ATOMIC);
- if (event->ptr)
- memcpy(event->ptr, argv[curarg], len);
- else
- err("no memory for string!");
+ event->ptr = kstrdup(argv[curarg], GFP_ATOMIC);
+ if (!event->ptr)
+ dev_err(cs->dev, "out of memory\n");
++curarg;
}
#ifdef CONFIG_GIGASET_DEBUG
if (!event->ptr)
- dbg(DEBUG_CMD, "string==NULL");
+ gig_dbg(DEBUG_CMD, "string==NULL");
else
- dbg(DEBUG_CMD,
- "string==%s", (char *) event->ptr);
+ gig_dbg(DEBUG_CMD, "string==%s",
+ (char *) event->ptr);
#endif
break;
case RT_ZCAU:
@@ -694,7 +680,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
j = isdn_gethex(argv[curarg + 1]);
if (i >= 0 && i < 256 && j >= 0 && j < 256)
event->parameter = (unsigned) i << 8
- | j;
+ | j;
curarg += 2;
} else
curarg = params - 1;
@@ -712,7 +698,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
} else
event->parameter = -1;
#ifdef CONFIG_GIGASET_DEBUG
- dbg(DEBUG_CMD, "parameter==%d", event->parameter);
+ gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter);
#endif
break;
}
@@ -724,12 +710,13 @@ void gigaset_handle_modem_response(struct cardstate *cs)
break;
}
- atomic_set(&cs->ev_tail, tail);
+ cs->ev_tail = tail;
spin_unlock_irqrestore(&cs->ev_lock, flags);
if (curarg != params)
- dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d",
- curarg, params);
+ gig_dbg(DEBUG_ANY,
+ "invalid number of processed parameters: %d/%d",
+ curarg, params);
}
EXPORT_SYMBOL_GPL(gigaset_handle_modem_response);
@@ -739,23 +726,19 @@ EXPORT_SYMBOL_GPL(gigaset_handle_modem_response);
static void disconnect(struct at_state_t **at_state_p)
{
unsigned long flags;
- struct bc_state *bcs;
- struct cardstate *cs;
-
- IFNULLRET(at_state_p);
- IFNULLRET(*at_state_p);
- bcs = (*at_state_p)->bcs;
- cs = (*at_state_p)->cs;
- IFNULLRET(cs);
+ struct bc_state *bcs = (*at_state_p)->bcs;
+ struct cardstate *cs = (*at_state_p)->cs;
- new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX);
+ spin_lock_irqsave(&cs->lock, flags);
+ ++(*at_state_p)->seq_index;
/* revert to selected idle mode */
- if (!atomic_read(&cs->cidmode)) {
+ if (!cs->cidmode) {
cs->at_state.pending_commands |= PC_UMMODE;
atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
}
+ spin_unlock_irqrestore(&cs->lock, flags);
if (bcs) {
/* B channel assigned: invoke hardware specific handler */
@@ -777,7 +760,7 @@ static void disconnect(struct at_state_t **at_state_p)
* The structure should be freed by calling disconnect() after use.
*/
static inline struct at_state_t *get_free_channel(struct cardstate *cs,
- int cid)
+ int cid)
/* cids: >0: siemens-cid
0: without cid
-1: no cid assigned yet
@@ -826,7 +809,7 @@ static void init_failed(struct cardstate *cs, int mode)
static void schedule_init(struct cardstate *cs, int state)
{
if (cs->at_state.pending_commands & PC_INIT) {
- dbg(DEBUG_CMD, "not scheduling PC_INIT again");
+ gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again");
return;
}
atomic_set(&cs->mstate, state);
@@ -834,52 +817,56 @@ static void schedule_init(struct cardstate *cs, int state)
gigaset_block_channels(cs);
cs->at_state.pending_commands |= PC_INIT;
atomic_set(&cs->commands_pending, 1);
- dbg(DEBUG_CMD, "Scheduling PC_INIT");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_INIT");
}
-/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */
+/* Add "AT" to a command, add the cid, dle encode it, send the result to the
+ hardware. */
static void send_command(struct cardstate *cs, const char *cmd, int cid,
- int dle, gfp_t kmallocflags)
+ int dle, gfp_t kmallocflags)
{
size_t cmdlen, buflen;
char *cmdpos, *cmdbuf, *cmdtail;
cmdlen = strlen(cmd);
buflen = 11 + cmdlen;
+ if (unlikely(buflen <= cmdlen)) {
+ dev_err(cs->dev, "integer overflow in buflen\n");
+ return;
+ }
- if (likely(buflen > cmdlen)) {
- cmdbuf = kmalloc(buflen, kmallocflags);
- if (likely(cmdbuf != NULL)) {
- cmdpos = cmdbuf + 9;
- cmdtail = cmdpos + cmdlen;
- memcpy(cmdpos, cmd, cmdlen);
-
- if (cid > 0 && cid <= 65535) {
- do {
- *--cmdpos = '0' + cid % 10;
- cid /= 10;
- ++cmdlen;
- } while (cid);
- }
+ cmdbuf = kmalloc(buflen, kmallocflags);
+ if (unlikely(!cmdbuf)) {
+ dev_err(cs->dev, "out of memory\n");
+ return;
+ }
- cmdlen += 2;
- *--cmdpos = 'T';
- *--cmdpos = 'A';
+ cmdpos = cmdbuf + 9;
+ cmdtail = cmdpos + cmdlen;
+ memcpy(cmdpos, cmd, cmdlen);
- if (dle) {
- cmdlen += 4;
- *--cmdpos = '(';
- *--cmdpos = 0x10;
- *cmdtail++ = 0x10;
- *cmdtail++ = ')';
- }
+ if (cid > 0 && cid <= 65535) {
+ do {
+ *--cmdpos = '0' + cid % 10;
+ cid /= 10;
+ ++cmdlen;
+ } while (cid);
+ }
- cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
- kfree(cmdbuf);
- } else
- err("no memory for command buffer");
- } else
- err("overflow in buflen");
+ cmdlen += 2;
+ *--cmdpos = 'T';
+ *--cmdpos = 'A';
+
+ if (dle) {
+ cmdlen += 4;
+ *--cmdpos = '(';
+ *--cmdpos = 0x10;
+ *cmdtail++ = 0x10;
+ *cmdtail++ = ')';
+ }
+
+ cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
+ kfree(cmdbuf);
}
static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
@@ -910,9 +897,6 @@ static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
static void bchannel_down(struct bc_state *bcs)
{
- IFNULLRET(bcs);
- IFNULLRET(bcs->cs);
-
if (bcs->chstate & CHS_B_UP) {
bcs->chstate &= ~CHS_B_UP;
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
@@ -930,16 +914,15 @@ static void bchannel_down(struct bc_state *bcs)
static void bchannel_up(struct bc_state *bcs)
{
- IFNULLRET(bcs);
-
if (!(bcs->chstate & CHS_D_UP)) {
- notice("%s: D channel not up", __func__);
+ dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__);
bcs->chstate |= CHS_D_UP;
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
}
if (bcs->chstate & CHS_B_UP) {
- notice("%s: B channel already up", __func__);
+ dev_notice(bcs->cs->dev, "%s: B channel already up\n",
+ __func__);
return;
}
@@ -947,17 +930,21 @@ static void bchannel_up(struct bc_state *bcs)
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
}
-static void start_dial(struct at_state_t *at_state, void *data, int seq_index)
+static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index)
{
struct bc_state *bcs = at_state->bcs;
struct cardstate *cs = at_state->cs;
int retval;
+ unsigned long flags;
bcs->chstate |= CHS_NOTIFY_LL;
- //atomic_set(&bcs->status, BCS_INIT);
- if (atomic_read(&at_state->seq_index) != seq_index)
+ spin_lock_irqsave(&cs->lock, flags);
+ if (at_state->seq_index != seq_index) {
+ spin_unlock_irqrestore(&cs->lock, flags);
goto error;
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
retval = gigaset_isdn_setup_dial(at_state, data);
if (retval != 0)
@@ -965,20 +952,14 @@ static void start_dial(struct at_state_t *at_state, void *data, int seq_index)
at_state->pending_commands |= PC_CID;
- dbg(DEBUG_CMD, "Scheduling PC_CID");
-//#ifdef GIG_MAYINITONDIAL
-// if (atomic_read(&cs->MState) == MS_UNKNOWN) {
-// cs->at_state.pending_commands |= PC_INIT;
-// dbg(DEBUG_CMD, "Scheduling PC_INIT");
-// }
-//#endif
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CID");
+ atomic_set(&cs->commands_pending, 1);
return;
error:
at_state->pending_commands |= PC_NOCID;
- dbg(DEBUG_CMD, "Scheduling PC_NOCID");
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
+ atomic_set(&cs->commands_pending, 1);
return;
}
@@ -991,13 +972,13 @@ static void start_accept(struct at_state_t *at_state)
if (retval == 0) {
at_state->pending_commands |= PC_ACCEPT;
- dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
+ atomic_set(&cs->commands_pending, 1);
} else {
//FIXME
at_state->pending_commands |= PC_HUP;
- dbg(DEBUG_CMD, "Scheduling PC_HUP");
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
+ atomic_set(&cs->commands_pending, 1);
}
}
@@ -1008,9 +989,10 @@ static void do_start(struct cardstate *cs)
if (atomic_read(&cs->mstate) != MS_LOCKED)
schedule_init(cs, MS_INIT);
+ cs->isdn_up = 1;
gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
- // FIXME: not in locked mode
- // FIXME 2: only after init sequence
+ // FIXME: not in locked mode
+ // FIXME 2: only after init sequence
cs->waiting = 0;
wake_up(&cs->waitqueue);
@@ -1023,6 +1005,12 @@ static void finish_shutdown(struct cardstate *cs)
atomic_set(&cs->mode, M_UNKNOWN);
}
+ /* Tell the LL that the device is not available .. */
+ if (cs->isdn_up) {
+ cs->isdn_up = 0;
+ gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
+ }
+
/* The rest is done by cleanup_cs () in user mode. */
cs->cmd_result = -ENODEV;
@@ -1037,15 +1025,20 @@ static void do_shutdown(struct cardstate *cs)
if (atomic_read(&cs->mstate) == MS_READY) {
atomic_set(&cs->mstate, MS_SHUTDOWN);
cs->at_state.pending_commands |= PC_SHUTDOWN;
- atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME
- //gigaset_schedule_event(cs); //FIXME
+ atomic_set(&cs->commands_pending, 1);
+ gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN");
} else
finish_shutdown(cs);
}
static void do_stop(struct cardstate *cs)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->connected = 0;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
do_shutdown(cs);
}
@@ -1069,9 +1062,11 @@ static int reinit_and_retry(struct cardstate *cs, int channel)
return 0;
if (channel < 0)
- warn("Could not enter cid mode. Reinit device and try again.");
+ dev_warn(cs->dev,
+ "Could not enter cid mode. Reinit device and try again.\n");
else {
- warn("Could not get a call id. Reinit device and try again.");
+ dev_warn(cs->dev,
+ "Could not get a call id. Reinit device and try again.\n");
cs->bcs[channel].at_state.pending_commands |= PC_CID;
}
schedule_init(cs, MS_INIT);
@@ -1079,7 +1074,7 @@ static int reinit_and_retry(struct cardstate *cs, int channel)
}
static int at_state_invalid(struct cardstate *cs,
- struct at_state_t *test_ptr)
+ struct at_state_t *test_ptr)
{
unsigned long flags;
unsigned channel;
@@ -1116,7 +1111,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs,
case ICALL_ACCEPT:
break;
default:
- err("internal error: disposition=%d", retval);
+ dev_err(cs->dev, "internal error: disposition=%d\n", retval);
/* --v-- fall through --v-- */
case ICALL_IGNORE:
case ICALL_REJECT:
@@ -1160,7 +1155,6 @@ static int do_lock(struct cardstate *cs)
mode = atomic_read(&cs->mode);
atomic_set(&cs->mstate, MS_LOCKED);
atomic_set(&cs->mode, M_UNKNOWN);
- //FIXME reset card state / at states / bcs states
return mode;
}
@@ -1173,8 +1167,7 @@ static int do_unlock(struct cardstate *cs)
atomic_set(&cs->mstate, MS_UNINITIALIZED);
atomic_set(&cs->mode, M_UNKNOWN);
gigaset_free_channels(cs);
- //FIXME reset card state / at states / bcs states
- if (atomic_read(&cs->connected))
+ if (cs->connected)
schedule_init(cs, MS_INIT);
return 0;
@@ -1203,21 +1196,23 @@ static void do_action(int action, struct cardstate *cs,
at_state->waiting = 1;
break;
case ACT_INIT:
- //FIXME setup everything
cs->at_state.pending_commands &= ~PC_INIT;
cs->cur_at_seq = SEQ_NONE;
atomic_set(&cs->mode, M_UNIMODEM);
- if (!atomic_read(&cs->cidmode)) {
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!cs->cidmode) {
+ spin_unlock_irqrestore(&cs->lock, flags);
gigaset_free_channels(cs);
atomic_set(&cs->mstate, MS_READY);
break;
}
+ spin_unlock_irqrestore(&cs->lock, flags);
cs->at_state.pending_commands |= PC_CIDMODE;
- atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ atomic_set(&cs->commands_pending, 1);
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
break;
case ACT_FAILINIT:
- warn("Could not initialize the device.");
+ dev_warn(cs->dev, "Could not initialize the device.\n");
cs->dle = 0;
init_failed(cs, M_UNKNOWN);
cs->cur_at_seq = SEQ_NONE;
@@ -1273,8 +1268,8 @@ static void do_action(int action, struct cardstate *cs,
/* get fresh AT state structure for new CID */
at_state2 = get_free_channel(cs, ev->parameter);
if (!at_state2) {
- warn("RING ignored: "
- "could not allocate channel structure");
+ dev_warn(cs->dev,
+ "RING ignored: could not allocate channel structure\n");
break;
}
@@ -1302,7 +1297,7 @@ static void do_action(int action, struct cardstate *cs,
at_state = *p_at_state;
break;
case ACT_FAILSDOWN:
- warn("Could not shut down the device.");
+ dev_warn(cs->dev, "Could not shut down the device.\n");
/* fall through */
case ACT_FAKESDOWN:
case ACT_SDOWN:
@@ -1355,7 +1350,7 @@ static void do_action(int action, struct cardstate *cs,
break;
case ACT_ABORTHUP:
cs->cur_at_seq = SEQ_NONE;
- warn("Could not hang up.");
+ dev_warn(cs->dev, "Could not hang up.\n");
at_state->cid = -1;
if (bcs && cs->onechannel)
at_state->pending_commands |= PC_DLE0;
@@ -1367,14 +1362,15 @@ static void do_action(int action, struct cardstate *cs,
break;
case ACT_FAILDLE0:
cs->cur_at_seq = SEQ_NONE;
- warn("Could not leave DLE mode.");
+ dev_warn(cs->dev, "Could not leave DLE mode.\n");
at_state2 = &cs->bcs[cs->curchannel].at_state;
disconnect(&at_state2);
schedule_init(cs, MS_RECOVER);
break;
case ACT_FAILDLE1:
cs->cur_at_seq = SEQ_NONE;
- warn("Could not enter DLE mode. Try to hang up.");
+ dev_warn(cs->dev,
+ "Could not enter DLE mode. Trying to hang up.\n");
channel = cs->curchannel;
cs->bcs[channel].at_state.pending_commands |= PC_HUP;
atomic_set(&cs->commands_pending, 1);
@@ -1395,7 +1391,8 @@ static void do_action(int action, struct cardstate *cs,
cs->cur_at_seq = SEQ_NONE;
channel = cs->curchannel;
if (!reinit_and_retry(cs, channel)) {
- warn("Could not get a call id. Dialing not possible");
+ dev_warn(cs->dev,
+ "Could not get a call ID. Cannot dial.\n");
at_state2 = &cs->bcs[channel].at_state;
disconnect(&at_state2);
}
@@ -1428,7 +1425,8 @@ static void do_action(int action, struct cardstate *cs,
at_state->pending_commands |= PC_HUP;
atomic_set(&cs->commands_pending, 1);
break;
- case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */
+ case ACT_GETSTRING: /* warning: RING, ZDLE, ...
+ are not handled properly anymore */
at_state->getstring = 1;
break;
case ACT_SETVER:
@@ -1469,16 +1467,16 @@ static void do_action(int action, struct cardstate *cs,
case ACT_GOTVER:
if (cs->gotfwver == 0) {
cs->gotfwver = 1;
- dbg(DEBUG_ANY,
- "firmware version %02d.%03d.%02d.%02d",
- cs->fwver[0], cs->fwver[1],
- cs->fwver[2], cs->fwver[3]);
+ gig_dbg(DEBUG_ANY,
+ "firmware version %02d.%03d.%02d.%02d",
+ cs->fwver[0], cs->fwver[1],
+ cs->fwver[2], cs->fwver[3]);
break;
}
/* fall through */
case ACT_FAILVER:
cs->gotfwver = -1;
- err("could not read firmware version.");
+ dev_err(cs->dev, "could not read firmware version.\n");
break;
#ifdef CONFIG_GIGASET_DEBUG
case ACT_ERROR:
@@ -1496,16 +1494,16 @@ static void do_action(int action, struct cardstate *cs,
break;
#endif
case ACT_DEBUG:
- dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
+ gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
__func__, ev->type, at_state->ConState);
break;
case ACT_WARN:
- warn("%s: resp_code %d in ConState %d!",
- __func__, ev->type, at_state->ConState);
+ dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n",
+ __func__, ev->type, at_state->ConState);
break;
case ACT_ZCAU:
- warn("cause code %04x in connection state %d.",
- ev->parameter, at_state->ConState);
+ dev_warn(cs->dev, "cause code %04x in connection state %d.\n",
+ ev->parameter, at_state->ConState);
break;
/* events from the LL */
@@ -1516,14 +1514,14 @@ static void do_action(int action, struct cardstate *cs,
start_accept(at_state);
break;
case ACT_PROTO_L2:
- dbg(DEBUG_CMD,
- "set protocol to %u", (unsigned) ev->parameter);
+ gig_dbg(DEBUG_CMD, "set protocol to %u",
+ (unsigned) ev->parameter);
at_state->bcs->proto2 = ev->parameter;
break;
case ACT_HUP:
at_state->pending_commands |= PC_HUP;
- atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_HUP");
+ atomic_set(&cs->commands_pending, 1);
+ gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
break;
/* hotplug events */
@@ -1555,17 +1553,19 @@ static void do_action(int action, struct cardstate *cs,
/* events from the proc file system */ // FIXME without ACT_xxxx?
case ACT_PROC_CIDMODE:
- if (ev->parameter != atomic_read(&cs->cidmode)) {
- atomic_set(&cs->cidmode, ev->parameter);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (ev->parameter != cs->cidmode) {
+ cs->cidmode = ev->parameter;
if (ev->parameter) {
cs->at_state.pending_commands |= PC_CIDMODE;
- dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
} else {
cs->at_state.pending_commands |= PC_UMMODE;
- dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
}
atomic_set(&cs->commands_pending, 1);
}
+ spin_unlock_irqrestore(&cs->lock, flags);
cs->waiting = 0;
wake_up(&cs->waitqueue);
break;
@@ -1590,7 +1590,7 @@ static void do_action(int action, struct cardstate *cs,
*p_resp_code = RSP_NULL;
}
} else
- err("%s: action==%d!", __func__, action);
+ dev_err(cs->dev, "%s: action==%d!\n", __func__, action);
}
}
@@ -1609,47 +1609,46 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
int curact;
unsigned long flags;
- IFNULLRET(cs);
- IFNULLRET(ev);
-
if (ev->cid >= 0) {
at_state = at_state_from_cid(cs, ev->cid);
if (!at_state) {
gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID,
- NULL, 0, NULL);
+ NULL, 0, NULL);
return;
}
} else {
at_state = ev->at_state;
if (at_state_invalid(cs, at_state)) {
- dbg(DEBUG_ANY,
- "event for invalid at_state %p", at_state);
+ gig_dbg(DEBUG_ANY, "event for invalid at_state %p",
+ at_state);
return;
}
}
- dbg(DEBUG_CMD,
- "connection state %d, event %d", at_state->ConState, ev->type);
+ gig_dbg(DEBUG_CMD, "connection state %d, event %d",
+ at_state->ConState, ev->type);
bcs = at_state->bcs;
sendcid = at_state->cid;
/* Setting the pointer to the dial array */
rep = at_state->replystruct;
- IFNULLRET(rep);
+ spin_lock_irqsave(&cs->lock, flags);
if (ev->type == EV_TIMEOUT) {
- if (ev->parameter != atomic_read(&at_state->timer_index)
+ if (ev->parameter != at_state->timer_index
|| !at_state->timer_active) {
ev->type = RSP_NONE; /* old timeout */
- dbg(DEBUG_ANY, "old timeout");
+ gig_dbg(DEBUG_ANY, "old timeout");
} else if (!at_state->waiting)
- dbg(DEBUG_ANY, "timeout occured");
+ gig_dbg(DEBUG_ANY, "timeout occurred");
else
- dbg(DEBUG_ANY, "stopped waiting");
+ gig_dbg(DEBUG_ANY, "stopped waiting");
}
+ spin_unlock_irqrestore(&cs->lock, flags);
- /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */
+ /* if the response belongs to a variable in at_state->int_var[VAR_XXXX]
+ or at_state->str_var[STR_XXXX], set it */
if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) {
index = ev->type - RSP_VAR;
at_state->int_var[index] = ev->parameter;
@@ -1657,20 +1656,22 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
index = ev->type - RSP_STR;
kfree(at_state->str_var[index]);
at_state->str_var[index] = ev->ptr;
- ev->ptr = NULL; /* prevent process_events() from deallocating ptr */
+ ev->ptr = NULL; /* prevent process_events() from
+ deallocating ptr */
}
if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING)
at_state->getstring = 0;
- /* Search row in dial array which matches modem response and current constate */
+ /* Search row in dial array which matches modem response and current
+ constate */
for (;; rep++) {
rcode = rep->resp_code;
- /* dbg (DEBUG_ANY, "rcode %d", rcode); */
if (rcode == RSP_LAST) {
/* found nothing...*/
- warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!",
- __func__, ev->type, at_state->ConState);
+ dev_warn(cs->dev, "%s: rcode=RSP_LAST: "
+ "resp_code %d in ConState %d!\n",
+ __func__, ev->type, at_state->ConState);
return;
}
if ((rcode == RSP_ANY || rcode == ev->type)
@@ -1706,14 +1707,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
} else {
/* Send command to modem if not NULL... */
if (p_command/*rep->command*/) {
- if (atomic_read(&cs->connected))
+ if (cs->connected)
send_command(cs, p_command,
- sendcid, cs->dle,
- GFP_ATOMIC);
+ sendcid, cs->dle,
+ GFP_ATOMIC);
else
gigaset_add_event(cs, at_state,
- RSP_NODEV,
- NULL, 0, NULL);
+ RSP_NODEV,
+ NULL, 0, NULL);
}
spin_lock_irqsave(&cs->lock, flags);
@@ -1723,8 +1724,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
} else if (rep->timeout > 0) { /* new timeout */
at_state->timer_expires = rep->timeout * 10;
at_state->timer_active = 1;
- new_index(&at_state->timer_index,
- MAX_TIMER_INDEX);
+ ++at_state->timer_index;
}
spin_unlock_irqrestore(&cs->lock, flags);
}
@@ -1744,17 +1744,16 @@ static void process_command_flags(struct cardstate *cs)
struct bc_state *bcs;
int i;
int sequence;
-
- IFNULLRET(cs);
+ unsigned long flags;
atomic_set(&cs->commands_pending, 0);
if (cs->cur_at_seq) {
- dbg(DEBUG_CMD, "not searching scheduled commands: busy");
+ gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy");
return;
}
- dbg(DEBUG_CMD, "searching scheduled commands");
+ gig_dbg(DEBUG_CMD, "searching scheduled commands");
sequence = SEQ_NONE;
@@ -1795,8 +1794,9 @@ static void process_command_flags(struct cardstate *cs)
}
/* only switch back to unimodem mode, if no commands are pending and no channels are up */
+ spin_lock_irqsave(&cs->lock, flags);
if (cs->at_state.pending_commands == PC_UMMODE
- && !atomic_read(&cs->cidmode)
+ && !cs->cidmode
&& list_empty(&cs->temp_at_states)
&& atomic_read(&cs->mode) == M_CID) {
sequence = SEQ_UMMODE;
@@ -1810,6 +1810,7 @@ static void process_command_flags(struct cardstate *cs)
}
}
}
+ spin_unlock_irqrestore(&cs->lock, flags);
cs->at_state.pending_commands &= ~PC_UMMODE;
if (sequence != SEQ_NONE) {
schedule_sequence(cs, at_state, sequence);
@@ -1865,11 +1866,7 @@ static void process_command_flags(struct cardstate *cs)
if (cs->at_state.pending_commands & PC_CIDMODE) {
cs->at_state.pending_commands &= ~PC_CIDMODE;
if (atomic_read(&cs->mode) == M_UNIMODEM) {
-#if 0
- cs->retry_count = 2;
-#else
cs->retry_count = 1;
-#endif
schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE);
return;
}
@@ -1897,7 +1894,7 @@ static void process_command_flags(struct cardstate *cs)
switch (atomic_read(&cs->mode)) {
case M_UNIMODEM:
cs->at_state.pending_commands |= PC_CIDMODE;
- dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
atomic_set(&cs->commands_pending, 1);
return;
#ifdef GIG_MAYINITONDIAL
@@ -1926,18 +1923,21 @@ static void process_events(struct cardstate *cs)
int i;
int check_flags = 0;
int was_busy;
+ unsigned long flags;
- /* no locking needed (only one reader) */
- head = atomic_read(&cs->ev_head);
+ spin_lock_irqsave(&cs->ev_lock, flags);
+ head = cs->ev_head;
for (i = 0; i < 2 * MAX_EVENTS; ++i) {
- tail = atomic_read(&cs->ev_tail);
+ tail = cs->ev_tail;
if (tail == head) {
if (!check_flags && !atomic_read(&cs->commands_pending))
break;
check_flags = 0;
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
process_command_flags(cs);
- tail = atomic_read(&cs->ev_tail);
+ spin_lock_irqsave(&cs->ev_lock, flags);
+ tail = cs->ev_tail;
if (tail == head) {
if (!atomic_read(&cs->commands_pending))
break;
@@ -1947,18 +1947,23 @@ static void process_events(struct cardstate *cs)
ev = cs->events + head;
was_busy = cs->cur_at_seq != SEQ_NONE;
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
process_event(cs, ev);
+ spin_lock_irqsave(&cs->ev_lock, flags);
kfree(ev->ptr);
ev->ptr = NULL;
if (was_busy && cs->cur_at_seq == SEQ_NONE)
check_flags = 1;
head = (head + 1) % MAX_EVENTS;
- atomic_set(&cs->ev_head, head);
+ cs->ev_head = head;
}
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
+
if (i == 2 * MAX_EVENTS) {
- err("infinite loop in process_events; aborting.");
+ dev_err(cs->dev,
+ "infinite loop in process_events; aborting.\n");
}
}
@@ -1970,12 +1975,9 @@ void gigaset_handle_event(unsigned long data)
{
struct cardstate *cs = (struct cardstate *) data;
- IFNULLRET(cs);
- IFNULLRET(cs->inbuf);
-
/* handle incoming data on control/common channel */
if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) {
- dbg(DEBUG_INTR, "processing new data");
+ gig_dbg(DEBUG_INTR, "processing new data");
cs->ops->handle_input(cs->inbuf);
}
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 729edcdb6dac..22b9693f7c0a 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -1,11 +1,16 @@
-/* Siemens Gigaset 307x driver
+/*
+ * Siemens Gigaset 307x driver
* Common header file for all connection variants
*
- * Written by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Written by Stefan Eilers
* and Hansjoerg Lipp <hjlipp@web.de>
*
- * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp 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.
+ * =====================================================================
*/
#ifndef GIGASET_H
@@ -15,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/types.h>
-#include <asm/atomic.h>
#include <linux/spinlock.h>
#include <linux/isdnif.h>
#include <linux/usb.h>
@@ -27,21 +31,22 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/list.h>
+#include <asm/atomic.h>
#define GIG_VERSION {0,5,0,0}
#define GIG_COMPAT {0,4,0,0}
-#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
-#define MAX_RESP_SIZE 512 /* Max. size of a response string */
-#define HW_HDR_LEN 2 /* Header size used to store ack info */
+#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
+#define MAX_RESP_SIZE 512 /* Max. size of a response string */
+#define HW_HDR_LEN 2 /* Header size used to store ack info */
-#define MAX_EVENTS 64 /* size of event queue */
+#define MAX_EVENTS 64 /* size of event queue */
#define RBUFSIZE 8192
-#define SBUFSIZE 4096 /* sk_buff payload size */
+#define SBUFSIZE 4096 /* sk_buff payload size */
-#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
-#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
+#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
+#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
/* compile time options */
#define GIG_MAJOR 0
@@ -50,10 +55,7 @@
#define GIG_RETRYCID
#define GIG_X75
-#define MAX_TIMER_INDEX 1000
-#define MAX_SEQ_INDEX 1000
-
-#define GIG_TICK (HZ / 10)
+#define GIG_TICK 100 /* in milliseconds */
/* timeout values (unit: 1 sec) */
#define INIT_TIMEOUT 1
@@ -67,74 +69,89 @@
#define MAXACT 3
-#define IFNULL(a) if (unlikely(!(a)))
-#define IFNULLRET(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; }
-#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); }
-#define IFNULLCONT(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; }
-#define IFNULLGOTO(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; }
-
extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */
-/* any combination of these can be given with the 'debug=' parameter to insmod, e.g.
- * 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and DEBUG_INTR. */
-enum debuglevel { /* up to 24 bits (atomic_t) */
+/* any combination of these can be given with the 'debug=' parameter to insmod,
+ * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and
+ * DEBUG_INTR.
+ */
+enum debuglevel {
DEBUG_REG = 0x0002, /* serial port I/O register operations */
DEBUG_OPEN = 0x0004, /* open/close serial port */
DEBUG_INTR = 0x0008, /* interrupt processing */
- DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on interrupt
- requests, not available as run-time option */
+ DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on
+ interrupt requests, not available as
+ run-time option */
DEBUG_CMD = 0x00020, /* sent/received LL commands */
DEBUG_STREAM = 0x00040, /* application data stream I/O events */
DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
DEBUG_LLDATA = 0x00100, /* sent/received LL data */
- DEBUG_INTR_0 = 0x00200, /* serial port output interrupt processing */
+ DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */
DEBUG_DRIVER = 0x00400, /* driver structure */
DEBUG_HDLC = 0x00800, /* M10x HDLC processing */
DEBUG_WRITE = 0x01000, /* M105 data write */
- DEBUG_TRANSCMD = 0x02000, /*AT-COMMANDS+RESPONSES*/
- DEBUG_MCMD = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/
- DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */
+ DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */
+ DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */
+ DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data
+ structures */
DEBUG_LOCK = 0x10000, /* semaphore operations */
DEBUG_OUTPUT = 0x20000, /* output to device */
- DEBUG_ISO = 0x40000, /* isochronous transfers */
+ DEBUG_ISO = 0x40000, /* isochronous transfers */
DEBUG_IF = 0x80000, /* character device operations */
- DEBUG_USBREQ = 0x100000, /* USB communication (except payload data) */
- DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when MS_LOCKED */
+ DEBUG_USBREQ = 0x100000, /* USB communication (except payload
+ data) */
+ DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when
+ MS_LOCKED */
- DEBUG_ANY = 0x3fffff, /* print message if any of the others is activated */
+ DEBUG_ANY = 0x3fffff, /* print message if any of the others is
+ activated */
};
-#ifdef CONFIG_GIGASET_DEBUG
-#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
-//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR)
-#else
-#define DEBUG_DEFAULT 0
+/* missing from linux/device.h ... */
+#ifndef dev_notice
+#define dev_notice(dev, format, arg...) \
+ dev_printk(KERN_NOTICE , dev , format , ## arg)
#endif
-/* redefine syslog macros to prepend module name instead of entire source path */
-/* The space before the comma in ", ##" is needed by gcc 2.95 */
+/* Kernel message macros for situations where dev_printk and friends cannot be
+ * used for lack of reliable access to a device structure.
+ * linux/usb.h already contains these but in an obsolete form which clutters
+ * the log needlessly, and according to the USB maintainer those should be
+ * removed rather than fixed anyway.
+ */
+#undef err
#undef info
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
-#undef notice
-#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
#undef warn
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+#undef notice
-#undef err
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
+#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
-#undef dbg
#ifdef CONFIG_GIGASET_DEBUG
-#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
- printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0)
+
+#define gig_dbg(level, format, arg...) \
+ do { \
+ if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
+ printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \
+ ## arg); \
+ } while (0)
+#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
+
#else
-#define dbg(level, format, arg...) do {} while (0)
+
+#define gig_dbg(level, format, arg...) do {} while (0)
+#define DEBUG_DEFAULT 0
+
#endif
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
- size_t len, const unsigned char *buf, int from_user);
+ size_t len, const unsigned char *buf);
/* connection state */
#define ZSAU_NONE 0
@@ -148,13 +165,14 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define ZSAU_UNKNOWN -1
/* USB control transfer requests */
-#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
-#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
/* int-in-events 3070 */
#define HD_B1_FLOW_CONTROL 0x80
#define HD_B2_FLOW_CONTROL 0x81
-#define HD_RECEIVEATDATA_ACK (0x35) // 3070 // att: HD_RECEIVE>>AT<<DATA_ACK
+#define HD_RECEIVEATDATA_ACK (0x35) // 3070
+ // att: HD_RECEIVE>>AT<<DATA_ACK
#define HD_READY_SEND_ATDATA (0x36) // 3070
#define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070
#define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070
@@ -181,17 +199,18 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define HD_CLOSE_ATCHANNEL (0x29) // 3070
/* USB frames for isochronous transfer */
-#define BAS_FRAMETIME 1 /* number of milliseconds between frames */
-#define BAS_NUMFRAMES 8 /* number of frames per URB */
-#define BAS_MAXFRAME 16 /* allocated bytes per frame */
-#define BAS_NORMFRAME 8 /* send size without flow control */
-#define BAS_HIGHFRAME 10 /* " " with positive flow control */
-#define BAS_LOWFRAME 5 /* " " with negative flow control */
-#define BAS_CORRFRAMES 4 /* flow control multiplicator */
-
-#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isochronous input buffer per URB */
-#define BAS_OUTBUFSIZE 4096 /* size of common isochronous output buffer */
-#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isochronous output buffer */
+#define BAS_FRAMETIME 1 /* number of milliseconds between frames */
+#define BAS_NUMFRAMES 8 /* number of frames per URB */
+#define BAS_MAXFRAME 16 /* allocated bytes per frame */
+#define BAS_NORMFRAME 8 /* send size without flow control */
+#define BAS_HIGHFRAME 10 /* " " with positive flow control */
+#define BAS_LOWFRAME 5 /* " " with negative flow control */
+#define BAS_CORRFRAMES 4 /* flow control multiplicator */
+
+#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES)
+ /* size of isoc in buf per URB */
+#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */
+#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */
#define BAS_INURBS 3
#define BAS_OUTURBS 3
@@ -207,40 +226,40 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define AT_NUM 7
/* variables in struct at_state_t */
-#define VAR_ZSAU 0
-#define VAR_ZDLE 1
-#define VAR_ZVLS 2
-#define VAR_ZCTP 3
-#define VAR_NUM 4
-
-#define STR_NMBR 0
-#define STR_ZCPN 1
-#define STR_ZCON 2
-#define STR_ZBC 3
-#define STR_ZHLC 4
-#define STR_NUM 5
-
-#define EV_TIMEOUT -105
-#define EV_IF_VER -106
-#define EV_PROC_CIDMODE -107
-#define EV_SHUTDOWN -108
-#define EV_START -110
-#define EV_STOP -111
-#define EV_IF_LOCK -112
-#define EV_PROTO_L2 -113
-#define EV_ACCEPT -114
-#define EV_DIAL -115
-#define EV_HUP -116
-#define EV_BC_OPEN -117
-#define EV_BC_CLOSED -118
+#define VAR_ZSAU 0
+#define VAR_ZDLE 1
+#define VAR_ZVLS 2
+#define VAR_ZCTP 3
+#define VAR_NUM 4
+
+#define STR_NMBR 0
+#define STR_ZCPN 1
+#define STR_ZCON 2
+#define STR_ZBC 3
+#define STR_ZHLC 4
+#define STR_NUM 5
+
+#define EV_TIMEOUT -105
+#define EV_IF_VER -106
+#define EV_PROC_CIDMODE -107
+#define EV_SHUTDOWN -108
+#define EV_START -110
+#define EV_STOP -111
+#define EV_IF_LOCK -112
+#define EV_PROTO_L2 -113
+#define EV_ACCEPT -114
+#define EV_DIAL -115
+#define EV_HUP -116
+#define EV_BC_OPEN -117
+#define EV_BC_CLOSED -118
/* input state */
-#define INS_command 0x0001
-#define INS_DLE_char 0x0002
-#define INS_byte_stuff 0x0004
-#define INS_have_data 0x0008
-#define INS_skip_frame 0x0010
-#define INS_DLE_command 0x0020
+#define INS_command 0x0001
+#define INS_DLE_char 0x0002
+#define INS_byte_stuff 0x0004
+#define INS_have_data 0x0008
+#define INS_skip_frame 0x0010
+#define INS_DLE_command 0x0020
#define INS_flag_hunt 0x0040
/* channel state */
@@ -248,27 +267,27 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define CHS_B_UP 0x02
#define CHS_NOTIFY_LL 0x04
-#define ICALL_REJECT 0
-#define ICALL_ACCEPT 1
-#define ICALL_IGNORE 2
+#define ICALL_REJECT 0
+#define ICALL_ACCEPT 1
+#define ICALL_IGNORE 2
/* device state */
-#define MS_UNINITIALIZED 0
-#define MS_INIT 1
-#define MS_LOCKED 2
-#define MS_SHUTDOWN 3
-#define MS_RECOVER 4
-#define MS_READY 5
+#define MS_UNINITIALIZED 0
+#define MS_INIT 1
+#define MS_LOCKED 2
+#define MS_SHUTDOWN 3
+#define MS_RECOVER 4
+#define MS_READY 5
/* mode */
-#define M_UNKNOWN 0
-#define M_CONFIG 1
-#define M_UNIMODEM 2
-#define M_CID 3
+#define M_UNKNOWN 0
+#define M_CONFIG 1
+#define M_UNIMODEM 2
+#define M_CID 3
/* start mode */
-#define SM_LOCKED 0
-#define SM_ISDN 1 /* default */
+#define SM_LOCKED 0
+#define SM_ISDN 1 /* default */
struct gigaset_ops;
struct gigaset_driver;
@@ -283,27 +302,26 @@ struct ser_bc_state;
struct bas_bc_state;
struct reply_t {
- int resp_code; /* RSP_XXXX */
- int min_ConState; /* <0 => ignore */
- int max_ConState; /* <0 => ignore */
- int parameter; /* e.g. ZSAU_XXXX <0: ignore*/
- int new_ConState; /* <0 => ignore */
- int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/
- int action[MAXACT]; /* ACT_XXXX */
- char *command; /* NULL==none */
+ int resp_code; /* RSP_XXXX */
+ int min_ConState; /* <0 => ignore */
+ int max_ConState; /* <0 => ignore */
+ int parameter; /* e.g. ZSAU_XXXX <0: ignore*/
+ int new_ConState; /* <0 => ignore */
+ int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/
+ int action[MAXACT]; /* ACT_XXXX */
+ char *command; /* NULL==none */
};
extern struct reply_t gigaset_tab_cid_m10x[];
extern struct reply_t gigaset_tab_nocid_m10x[];
struct inbuf_t {
- unsigned char *rcvbuf; /* usb-gigaset receive buffer */
+ unsigned char *rcvbuf; /* usb-gigaset receive buffer */
struct bc_state *bcs;
- struct cardstate *cs;
- int inputstate;
-
- atomic_t head, tail;
- unsigned char data[RBUFSIZE];
+ struct cardstate *cs;
+ int inputstate;
+ atomic_t head, tail;
+ unsigned char data[RBUFSIZE];
};
/* isochronous write buffer structure
@@ -319,16 +337,9 @@ struct inbuf_t {
* if writesem <= 0, data[write..read-1] is currently being written to
* - idle contains the byte value to repeat when the end of valid data is
* reached; if nextread==write (buffer contains no data to send), either the
- * BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD)
- * or those of the pad area (if write<BAS_OUTBUFPAD) are also filled with that
- * value
- * - optionally, the following statistics on the buffer's usage can be collected:
- * maxfill: maximum number of bytes occupied
- * idlefills: number of times a frame of idle bytes is prepared
- * emptygets: number of times the buffer was empty when a data frame was requested
- * backtoback: number of times two data packets were entered into the buffer
- * without intervening idle flags
- * nakedback: set if no idle flags have been inserted since the last data packet
+ * BAS_OUTBUFPAD bytes immediately before data[write] (if
+ * write>=BAS_OUTBUFPAD) or those of the pad area (if write<BAS_OUTBUFPAD)
+ * are also filled with that value
*/
struct isowbuf_t {
atomic_t read;
@@ -358,34 +369,28 @@ struct isow_urbctx_t {
* it is currently assigned a B channel
*/
struct at_state_t {
- struct list_head list;
- int waiting;
- int getstring;
- atomic_t timer_index;
+ struct list_head list;
+ int waiting;
+ int getstring;
+ unsigned timer_index;
unsigned long timer_expires;
int timer_active;
- unsigned int ConState; /* State of connection */
- struct reply_t *replystruct;
- int cid;
- int int_var[VAR_NUM]; /* see VAR_XXXX */
- char *str_var[STR_NUM]; /* see STR_XXXX */
- unsigned pending_commands; /* see PC_XXXX */
- atomic_t seq_index;
-
- struct cardstate *cs;
- struct bc_state *bcs;
+ unsigned int ConState; /* State of connection */
+ struct reply_t *replystruct;
+ int cid;
+ int int_var[VAR_NUM]; /* see VAR_XXXX */
+ char *str_var[STR_NUM]; /* see STR_XXXX */
+ unsigned pending_commands; /* see PC_XXXX */
+ unsigned seq_index;
+
+ struct cardstate *cs;
+ struct bc_state *bcs;
};
struct resp_type_t {
unsigned char *response;
- int resp_code; /* RSP_XXXX */
- int type; /* RT_XXXX */
-};
-
-struct prot_skb {
- atomic_t empty;
- struct semaphore *sem;
- struct sk_buff *skb;
+ int resp_code; /* RSP_XXXX */
+ int type; /* RT_XXXX */
};
struct event_t {
@@ -398,29 +403,29 @@ struct event_t {
/* This buffer holds all information about the used B-Channel */
struct bc_state {
- struct sk_buff *tx_skb; /* Current transfer buffer to modem */
- struct sk_buff_head squeue; /* B-Channel send Queue */
+ struct sk_buff *tx_skb; /* Current transfer buffer to modem */
+ struct sk_buff_head squeue; /* B-Channel send Queue */
/* Variables for debugging .. */
- int corrupted; /* Counter for corrupted packages */
- int trans_down; /* Counter of packages (downstream) */
- int trans_up; /* Counter of packages (upstream) */
+ int corrupted; /* Counter for corrupted packages */
+ int trans_down; /* Counter of packages (downstream) */
+ int trans_up; /* Counter of packages (upstream) */
struct at_state_t at_state;
unsigned long rcvbytes;
__u16 fcs;
struct sk_buff *skb;
- int inputstate; /* see INS_XXXX */
+ int inputstate; /* see INS_XXXX */
int channel;
struct cardstate *cs;
- unsigned chstate; /* bitmap (CHS_*) */
+ unsigned chstate; /* bitmap (CHS_*) */
int ignore;
- unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
- char *commands[AT_NUM]; /* see AT_XXXX */
+ unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
+ char *commands[AT_NUM]; /* see AT_XXXX */
#ifdef CONFIG_GIGASET_DEBUG
int emptycount;
@@ -428,37 +433,39 @@ struct bc_state {
int busy;
int use_count;
- /* hardware drivers */
+ /* private data of hardware drivers */
union {
- struct ser_bc_state *ser; /* private data of serial hardware driver */
- struct usb_bc_state *usb; /* private data of usb hardware driver */
- struct bas_bc_state *bas;
+ struct ser_bc_state *ser; /* serial hardware driver */
+ struct usb_bc_state *usb; /* usb hardware driver (m105) */
+ struct bas_bc_state *bas; /* usb hardware driver (base) */
} hw;
};
struct cardstate {
struct gigaset_driver *driver;
unsigned minor_index;
+ struct device *dev;
const struct gigaset_ops *ops;
/* Stuff to handle communication */
- //wait_queue_head_t initwait;
wait_queue_head_t waitqueue;
int waiting;
- atomic_t mode; /* see M_XXXX */
- atomic_t mstate; /* Modem state: see MS_XXXX */
- /* only changed by the event layer */
+ atomic_t mode; /* see M_XXXX */
+ atomic_t mstate; /* Modem state: see MS_XXXX */
+ /* only changed by the event layer */
int cmd_result;
int channels;
- struct bc_state *bcs; /* Array of struct bc_state */
+ struct bc_state *bcs; /* Array of struct bc_state */
- int onechannel; /* data and commands transmitted in one stream (M10x) */
+ int onechannel; /* data and commands transmitted in one
+ stream (M10x) */
spinlock_t lock;
- struct at_state_t at_state; /* at_state_t for cid == 0 */
- struct list_head temp_at_states; /* list of temporary "struct at_state_t"s without B channel */
+ struct at_state_t at_state; /* at_state_t for cid == 0 */
+ struct list_head temp_at_states;/* list of temporary "struct
+ at_state_t"s without B channel */
struct inbuf_t *inbuf;
@@ -474,58 +481,69 @@ struct cardstate {
unsigned fwver[4];
int gotfwver;
- atomic_t running; /* !=0 if events are handled */
- atomic_t connected; /* !=0 if hardware is connected */
+ unsigned running; /* !=0 if events are handled */
+ unsigned connected; /* !=0 if hardware is connected */
+ unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */
- atomic_t cidmode;
+ unsigned cidmode;
- int myid; /* id for communication with LL */
+ int myid; /* id for communication with LL */
isdn_if iif;
struct reply_t *tabnocid;
struct reply_t *tabcid;
int cs_init;
- int ignoreframes; /* frames to ignore after setting up the B channel */
- struct semaphore sem; /* locks this structure: */
- /* connected is not changed, */
- /* hardware_up is not changed, */
- /* MState is not changed to or from MS_LOCKED */
+ int ignoreframes; /* frames to ignore after setting up the
+ B channel */
+ struct mutex mutex; /* locks this structure:
+ * connected is not changed,
+ * hardware_up is not changed,
+ * MState is not changed to or from
+ * MS_LOCKED */
struct timer_list timer;
int retry_count;
- int dle; /* !=0 if modem commands/responses are dle encoded */
- int cur_at_seq; /* sequence of AT commands being processed */
- int curchannel; /* channel, those commands are meant for */
- atomic_t commands_pending; /* flag(s) in xxx.commands_pending have been set */
- struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. Scheduled
- * -> for modem reponses (and incomming data for M10x)
- * -> on timeout
- * -> after setting bits in xxx.at_state.pending_command
- * (e.g. command from LL) */
- struct tasklet_struct write_tasklet; /* tasklet for serial output
- * (not used in base driver) */
+ int dle; /* !=0 if modem commands/responses are
+ dle encoded */
+ int cur_at_seq; /* sequence of AT commands being
+ processed */
+ int curchannel; /* channel those commands are meant
+ for */
+ atomic_t commands_pending; /* flag(s) in xxx.commands_pending have
+ been set */
+ struct tasklet_struct event_tasklet;
+ /* tasklet for serializing AT commands.
+ * Scheduled
+ * -> for modem reponses (and
+ * incoming data for M10x)
+ * -> on timeout
+ * -> after setting bits in
+ * xxx.at_state.pending_command
+ * (e.g. command from LL) */
+ struct tasklet_struct write_tasklet;
+ /* tasklet for serial output
+ * (not used in base driver) */
/* event queue */
struct event_t events[MAX_EVENTS];
- atomic_t ev_tail, ev_head;
+ unsigned ev_tail, ev_head;
spinlock_t ev_lock;
/* current modem response */
unsigned char respdata[MAX_RESP_SIZE];
unsigned cbytes;
- /* hardware drivers */
+ /* private data of hardware drivers */
union {
- struct usb_cardstate *usb; /* private data of USB hardware driver */
- struct ser_cardstate *ser; /* private data of serial hardware driver */
- struct bas_cardstate *bas; /* private data of base hardware driver */
+ struct usb_cardstate *usb; /* USB hardware driver (m105) */
+ struct ser_cardstate *ser; /* serial hardware driver */
+ struct bas_cardstate *bas; /* USB hardware driver (base) */
} hw;
};
struct gigaset_driver {
struct list_head list;
- spinlock_t lock; /* locks minor tables and blocked */
- //struct semaphore sem; /* locks this structure */
+ spinlock_t lock; /* locks minor tables and blocked */
struct tty_driver *tty;
unsigned have_tty;
unsigned minor;
@@ -553,37 +571,42 @@ struct bas_bc_state {
struct isow_urbctx_t isoouturbs[BAS_OUTURBS];
struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl;
struct isowbuf_t *isooutbuf;
- unsigned numsub; /* submitted URB counter (for diagnostic messages only) */
+ unsigned numsub; /* submitted URB counter
+ (for diagnostic messages only) */
struct tasklet_struct sent_tasklet;
/* isochronous input state */
spinlock_t isoinlock;
struct urb *isoinurbs[BAS_INURBS];
unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS];
- struct urb *isoindone; /* completed isoc read URB */
- int loststatus; /* status of dropped URB */
- unsigned isoinlost; /* number of bytes lost */
- /* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */
- unsigned seqlen; /* number of '1' bits not yet unstuffed */
- unsigned inbyte, inbits; /* collected bits for next byte */
+ struct urb *isoindone; /* completed isoc read URB */
+ int loststatus; /* status of dropped URB */
+ unsigned isoinlost; /* number of bytes lost */
+ /* state of bit unstuffing algorithm
+ (in addition to BC_state.inputstate) */
+ unsigned seqlen; /* number of '1' bits not yet
+ unstuffed */
+ unsigned inbyte, inbits; /* collected bits for next byte */
/* statistics */
- unsigned goodbytes; /* bytes correctly received */
- unsigned alignerrs; /* frames with incomplete byte at end */
- unsigned fcserrs; /* FCS errors */
- unsigned frameerrs; /* framing errors */
- unsigned giants; /* long frames */
- unsigned runts; /* short frames */
- unsigned aborts; /* HDLC aborts */
- unsigned shared0s; /* '0' bits shared between flags */
- unsigned stolen0s; /* '0' stuff bits also serving as leading flag bits */
+ unsigned goodbytes; /* bytes correctly received */
+ unsigned alignerrs; /* frames with incomplete byte at end */
+ unsigned fcserrs; /* FCS errors */
+ unsigned frameerrs; /* framing errors */
+ unsigned giants; /* long frames */
+ unsigned runts; /* short frames */
+ unsigned aborts; /* HDLC aborts */
+ unsigned shared0s; /* '0' bits shared between flags */
+ unsigned stolen0s; /* '0' stuff bits also serving as
+ leading flag bits */
struct tasklet_struct rcvd_tasklet;
};
struct gigaset_ops {
- /* Called from ev-layer.c/interface.c for sending AT commands to the device */
+ /* Called from ev-layer.c/interface.c for sending AT commands to the
+ device */
int (*write_cmd)(struct cardstate *cs,
- const unsigned char *buf, int len,
- struct tasklet_struct *wake_tasklet);
+ const unsigned char *buf, int len,
+ struct tasklet_struct *wake_tasklet);
/* Called from interface.c for additional device control */
int (*write_room)(struct cardstate *cs);
@@ -604,7 +627,7 @@ struct gigaset_ops {
/* Called by gigaset_freecs() for freeing bcs->hw.xxx */
int (*freebcshw)(struct bc_state *bcs);
- /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */
+ /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */
void (*reinitbcshw)(struct bc_state *bcs);
/* Called by gigaset_initcs() for setting up cs->hw.xxx */
@@ -613,13 +636,10 @@ struct gigaset_ops {
/* Called by gigaset_freecs() for freeing cs->hw.xxx */
void (*freecshw)(struct cardstate *cs);
- ///* Called by gigaset_stop() for killing URBs, shutting down the device, ...
- // hardwareup: ==0: don't try to shut down the device, hardware is really not accessible
- // !=0: hardware still up */
- //void (*stophw)(struct cardstate *cs, int hardwareup);
-
- /* Called from common.c/interface.c for additional serial port control */
- int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state);
+ /* Called from common.c/interface.c for additional serial port
+ control */
+ int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state,
+ unsigned new_state);
int (*baud_rate)(struct cardstate *cs, unsigned cflag);
int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag);
@@ -639,7 +659,7 @@ struct gigaset_ops {
* <DLE_FLAG>: 0x10
* <EVENT>: ((a-z)* | (A-Z)* | (0-10)*)+
*/
-#define DLE_FLAG 0x10
+#define DLE_FLAG 0x10
/* ===========================================================================
* Functions implemented in asyncdata.c
@@ -667,7 +687,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf);
/* Called from bas-gigaset.c to process a block of data
* received through the isochronous channel */
-void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs);
+void gigaset_isoc_receive(unsigned char *src, unsigned count,
+ struct bc_state *bcs);
/* Called from bas-gigaset.c to put a block of data
* into the isochronous output buffer */
@@ -703,7 +724,7 @@ static inline void gigaset_isdn_rcv_err(struct bc_state *bcs)
isdn_ctrl response;
/* error -> LL */
- dbg(DEBUG_CMD, "sending L1ERR");
+ gig_dbg(DEBUG_CMD, "sending L1ERR");
response.driver = bcs->cs->myid;
response.command = ISDN_STAT_L1ERR;
response.arg = bcs->channel;
@@ -727,8 +748,8 @@ void gigaset_handle_modem_response(struct cardstate *cs);
*/
/* initialize sysfs for device */
-void gigaset_init_dev_sysfs(struct usb_interface *interface);
-void gigaset_free_dev_sysfs(struct usb_interface *interface);
+void gigaset_init_dev_sysfs(struct cardstate *cs);
+void gigaset_free_dev_sysfs(struct cardstate *cs);
/* ===========================================================================
* Functions implemented in common.c/gigaset.h
@@ -736,7 +757,7 @@ void gigaset_free_dev_sysfs(struct usb_interface *interface);
void gigaset_bcs_reinit(struct bc_state *bcs);
void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
- struct cardstate *cs, int cid);
+ struct cardstate *cs, int cid);
int gigaset_get_channel(struct bc_state *bcs);
void gigaset_free_channel(struct bc_state *bcs);
int gigaset_get_channels(struct cardstate *cs);
@@ -745,16 +766,15 @@ void gigaset_block_channels(struct cardstate *cs);
/* Allocate and initialize driver structure. */
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
- const char *procname,
- const char *devname,
- const char *devfsname,
- const struct gigaset_ops *ops,
- struct module *owner);
+ const char *procname,
+ const char *devname,
+ const char *devfsname,
+ const struct gigaset_ops *ops,
+ struct module *owner);
/* Deallocate driver structure. */
void gigaset_freedriver(struct gigaset_driver *drv);
void gigaset_debugdrivers(void);
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor);
struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
struct cardstate *gigaset_get_cs_by_id(int id);
@@ -763,7 +783,8 @@ struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv);
void gigaset_unassign(struct cardstate *cs);
void gigaset_blockdriver(struct gigaset_driver *drv);
-/* Allocate and initialize card state. Calls hardware dependent gigaset_init[b]cs(). */
+/* Allocate and initialize card state. Calls hardware dependent
+ gigaset_init[b]cs(). */
struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
int onechannel, int ignoreframes,
int cidmode, const char *modulename);
@@ -788,8 +809,8 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
* ptr must be kmalloc()ed (and not be freed by the caller).
*/
struct event_t *gigaset_add_event(struct cardstate *cs,
- struct at_state_t *at_state, int type,
- void *ptr, int parameter, void *arg);
+ struct at_state_t *at_state, int type,
+ void *ptr, int parameter, void *arg);
/* Called on CONFIG1 command from frontend. */
int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode
@@ -799,7 +820,7 @@ static inline void gigaset_schedule_event(struct cardstate *cs)
{
unsigned long flags;
spin_lock_irqsave(&cs->lock, flags);
- if (atomic_read(&cs->running))
+ if (cs->running)
tasklet_schedule(&cs->event_tasklet);
spin_unlock_irqrestore(&cs->lock, flags);
}
@@ -810,7 +831,7 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs)
{
gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL);
- dbg(DEBUG_CMD, "scheduling BC_CLOSED");
+ gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED");
gigaset_schedule_event(bcs->cs);
}
@@ -820,36 +841,19 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
{
gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL);
- dbg(DEBUG_CMD, "scheduling BC_OPEN");
+ gig_dbg(DEBUG_CMD, "scheduling BC_OPEN");
gigaset_schedule_event(bcs->cs);
}
/* handling routines for sk_buff */
/* ============================= */
-/* private version of __skb_put()
- * append 'len' bytes to the content of 'skb', already knowing that the
- * existing buffer can accomodate them
- * returns a pointer to the location where the new bytes should be copied to
- * This function does not take any locks so it must be called with the
- * appropriate locks held only.
- */
-static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb,
- unsigned int len)
-{
- unsigned char *tmp = skb->tail;
- /*SKB_LINEAR_ASSERT(skb);*/ /* not needed here */
- skb->tail += len;
- skb->len += len;
- return tmp;
-}
-
/* pass received skb to LL
* Warning: skb must not be accessed anymore!
*/
static inline void gigaset_rcv_skb(struct sk_buff *skb,
- struct cardstate *cs,
- struct bc_state *bcs)
+ struct cardstate *cs,
+ struct bc_state *bcs)
{
cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb);
bcs->trans_down++;
@@ -859,8 +863,8 @@ static inline void gigaset_rcv_skb(struct sk_buff *skb,
* Warning: skb must not be accessed anymore!
*/
static inline void gigaset_rcv_error(struct sk_buff *procskb,
- struct cardstate *cs,
- struct bc_state *bcs)
+ struct cardstate *cs,
+ struct bc_state *bcs)
{
if (procskb)
dev_kfree_skb(procskb);
@@ -877,46 +881,9 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb,
/* bitwise byte inversion table */
extern __u8 gigaset_invtab[]; /* in common.c */
-
/* append received bytes to inbuf */
-static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf,
- const unsigned char *src,
- unsigned numbytes)
-{
- unsigned n, head, tail, bytesleft;
-
- dbg(DEBUG_INTR, "received %u bytes", numbytes);
-
- if (!numbytes)
- return 0;
-
- bytesleft = numbytes;
- tail = atomic_read(&inbuf->tail);
- head = atomic_read(&inbuf->head);
- dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
-
- while (bytesleft) {
- if (head > tail)
- n = head - 1 - tail;
- else if (head == 0)
- n = (RBUFSIZE-1) - tail;
- else
- n = RBUFSIZE - tail;
- if (!n) {
- err("buffer overflow (%u bytes lost)", bytesleft);
- break;
- }
- if (n > bytesleft)
- n = bytesleft;
- memcpy(inbuf->data + tail, src, n);
- bytesleft -= n;
- tail = (tail + n) % RBUFSIZE;
- src += n;
- }
- dbg(DEBUG_INTR, "setting tail to %u", tail);
- atomic_set(&inbuf->tail, tail);
- return numbytes != bytesleft;
-}
+int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
+ unsigned numbytes);
/* ===========================================================================
* Functions implemented in interface.c
@@ -924,7 +891,7 @@ static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf,
/* initialize interface */
void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
- const char *devname, const char *devfsname);
+ const char *devname, const char *devfsname);
/* release interface */
void gigaset_if_freedriver(struct gigaset_driver *drv);
/* add minor */
@@ -933,6 +900,6 @@ void gigaset_if_init(struct cardstate *cs);
void gigaset_if_free(struct cardstate *cs);
/* device received data */
void gigaset_if_receive(struct cardstate *cs,
- unsigned char *buffer, size_t len);
+ unsigned char *buffer, size_t len);
#endif
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 731a675f21b0..1654fa413575 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -1,9 +1,9 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de),
- * Hansjoerg Lipp (hjlipp@web.de),
- * Tilman Schmidt (tilman@imap.cc).
+ * Copyright (c) 2001 by Stefan Eilers,
+ * Hansjoerg Lipp <hjlipp@web.de>,
+ * Tilman Schmidt <tilman@imap.cc>.
*
* =====================================================================
* This program is free software; you can redistribute it and/or
@@ -11,15 +11,11 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
-/* == Handling of I4L IO ============================================================================*/
+/* == Handling of I4L IO =====================================================*/
/* writebuf_from_LL
* called by LL to transmit data on an open channel
@@ -29,14 +25,16 @@
* parameters:
* driverID driver ID as assigned by LL
* channel channel number
- * ack if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT)
+ * ack if != 0 LL wants to be notified on completion via
+ * statcallb(ISDN_STAT_BSENT)
* skb skb containing data to send
* return value:
* number of accepted bytes
* 0 if temporarily unable to accept data (out of buffer space)
* <0 on error (eg. -EINVAL)
*/
-static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb)
+static int writebuf_from_LL(int driverID, int channel, int ack,
+ struct sk_buff *skb)
{
struct cardstate *cs;
struct bc_state *bcs;
@@ -54,28 +52,25 @@ static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *
bcs = &cs->bcs[channel];
len = skb->len;
- dbg(DEBUG_LLDATA,
- "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)",
- driverID, channel, ack, len);
+ gig_dbg(DEBUG_LLDATA,
+ "Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)",
+ driverID, channel, ack, len);
if (!len) {
if (ack)
- warn("not ACKing empty packet from LL");
+ notice("%s: not ACKing empty packet", __func__);
return 0;
}
if (len > MAX_BUF_SIZE) {
- err("%s: packet too large (%d bytes)", __func__, channel);
+ err("%s: packet too large (%d bytes)", __func__, len);
return -EINVAL;
}
- if (!atomic_read(&cs->connected))
- return -ENODEV;
-
skblen = ack ? len : 0;
skb->head[0] = skblen & 0xff;
skb->head[1] = skblen >> 8;
- dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen,
- (unsigned) skb->head[0], (unsigned) skb->head[1]);
+ gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
+ len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
/* pass to device-specific module */
return cs->ops->send_skb(bcs, skb);
@@ -89,14 +84,14 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
++bcs->trans_up;
if (skb->len)
- warn("%s: skb->len==%d", __func__, skb->len);
+ dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
+ __func__, skb->len);
len = (unsigned char) skb->head[0] |
(unsigned) (unsigned char) skb->head[1] << 8;
if (len) {
- dbg(DEBUG_MCMD,
- "Acknowledge sending to LL (id: %d, channel: %d size: %u)",
- bcs->cs->myid, bcs->channel, len);
+ gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
+ bcs->cs->myid, bcs->channel, len);
response.driver = bcs->cs->myid;
response.command = ISDN_STAT_BSENT;
@@ -119,15 +114,12 @@ static int command_from_LL(isdn_ctrl *cntrl)
struct bc_state *bcs;
int retval = 0;
struct setup_parm *sp;
+ unsigned param;
+ unsigned long flags;
- //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command");
gigaset_debugdrivers();
- /* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or
- * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent !
- */
- //FIXME "remove test for &connected"
- if ((!cs || !atomic_read(&cs->connected))) {
+ if (!cs) {
warn("LL tried to access unknown device with nr. %d",
cntrl->driver);
return -ENODEV;
@@ -135,29 +127,30 @@ static int command_from_LL(isdn_ctrl *cntrl)
switch (cntrl->command) {
case ISDN_CMD_IOCTL:
-
- dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)",
- cntrl->driver, cntrl->arg);
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
+ cntrl->driver, cntrl->arg);
warn("ISDN_CMD_IOCTL is not supported.");
return -EINVAL;
case ISDN_CMD_DIAL:
- dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, "
- "phone: %s,ownmsn: %s, si1: %d, si2: %d)",
- cntrl->driver, cntrl->arg,
- cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
- cntrl->parm.setup.si1, cntrl->parm.setup.si2);
+ gig_dbg(DEBUG_ANY,
+ "ISDN_CMD_DIAL (driver: %d, ch: %ld, "
+ "phone: %s, ownmsn: %s, si1: %d, si2: %d)",
+ cntrl->driver, cntrl->arg,
+ cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
+ cntrl->parm.setup.si1, cntrl->parm.setup.si2);
if (cntrl->arg >= cs->channels) {
- err("invalid channel (%d)", (int) cntrl->arg);
+ err("ISDN_CMD_DIAL: invalid channel (%d)",
+ (int) cntrl->arg);
return -EINVAL;
}
bcs = cs->bcs + cntrl->arg;
if (!gigaset_get_channel(bcs)) {
- err("channel not free");
+ err("ISDN_CMD_DIAL: channel not free");
return -EBUSY;
}
@@ -169,42 +162,46 @@ static int command_from_LL(isdn_ctrl *cntrl)
}
*sp = cntrl->parm.setup;
- if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
- atomic_read(&bcs->at_state.seq_index),
- NULL)) {
+ spin_lock_irqsave(&cs->lock, flags);
+ param = bcs->at_state.seq_index;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param,
+ NULL)) {
//FIXME what should we do?
kfree(sp);
gigaset_free_channel(bcs);
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling DIAL");
+ gig_dbg(DEBUG_CMD, "scheduling DIAL");
gigaset_schedule_event(cs);
break;
case ISDN_CMD_ACCEPTD: //FIXME
- dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
if (cntrl->arg >= cs->channels) {
- err("invalid channel (%d)", (int) cntrl->arg);
+ err("ISDN_CMD_ACCEPTD: invalid channel (%d)",
+ (int) cntrl->arg);
return -EINVAL;
}
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
- EV_ACCEPT, NULL, 0, NULL)) {
+ EV_ACCEPT, NULL, 0, NULL)) {
//FIXME what should we do?
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling ACCEPT");
+ gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
gigaset_schedule_event(cs);
break;
case ISDN_CMD_ACCEPTB:
- dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
break;
case ISDN_CMD_HANGUP:
- dbg(DEBUG_ANY,
- "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg);
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)",
+ (int) cntrl->arg);
if (cntrl->arg >= cs->channels) {
err("ISDN_CMD_HANGUP: invalid channel (%u)",
@@ -213,66 +210,68 @@ static int command_from_LL(isdn_ctrl *cntrl)
}
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
- EV_HUP, NULL, 0, NULL)) {
+ EV_HUP, NULL, 0, NULL)) {
//FIXME what should we do?
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling HUP");
+ gig_dbg(DEBUG_CMD, "scheduling HUP");
gigaset_schedule_event(cs);
break;
- case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
- dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
+ case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
break;
- case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
- dbg(DEBUG_ANY,
- "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)",
- cntrl->driver, cntrl->arg, cntrl->parm.num);
+ case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
+ gig_dbg(DEBUG_ANY,
+ "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)",
+ cntrl->driver, cntrl->arg, cntrl->parm.num);
break;
- case ISDN_CMD_SETL2: /* Set L2 to given protocol */
- dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)",
- cntrl->arg & 0xff, (cntrl->arg >> 8));
+ case ISDN_CMD_SETL2: /* Set L2 to given protocol */
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)",
+ cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("invalid channel (%u)",
+ err("ISDN_CMD_SETL2: invalid channel (%u)",
(unsigned) cntrl->arg & 0xff);
return -EINVAL;
}
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
- EV_PROTO_L2, NULL, cntrl->arg >> 8,
- NULL)) {
+ EV_PROTO_L2, NULL, cntrl->arg >> 8,
+ NULL)) {
//FIXME what should we do?
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling PROTO_L2");
+ gig_dbg(DEBUG_CMD, "scheduling PROTO_L2");
gigaset_schedule_event(cs);
break;
- case ISDN_CMD_SETL3: /* Set L3 to given protocol */
- dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)",
- cntrl->arg & 0xff, (cntrl->arg >> 8));
+ case ISDN_CMD_SETL3: /* Set L3 to given protocol */
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)",
+ cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("invalid channel (%u)",
+ err("ISDN_CMD_SETL3: invalid channel (%u)",
(unsigned) cntrl->arg & 0xff);
return -EINVAL;
}
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
- err("invalid protocol %lu", cntrl->arg >> 8);
+ err("ISDN_CMD_SETL3: invalid protocol %lu",
+ cntrl->arg >> 8);
return -EINVAL;
}
break;
case ISDN_CMD_PROCEED:
- dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
break;
case ISDN_CMD_ALERT:
- dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
if (cntrl->arg >= cs->channels) {
- err("invalid channel (%d)", (int) cntrl->arg);
+ err("ISDN_CMD_ALERT: invalid channel (%d)",
+ (int) cntrl->arg);
return -EINVAL;
}
//bcs = cs->bcs + cntrl->arg;
@@ -280,32 +279,31 @@ static int command_from_LL(isdn_ctrl *cntrl)
// FIXME
break;
case ISDN_CMD_REDIR:
- dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
break;
case ISDN_CMD_PROT_IO:
- dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
break;
case ISDN_CMD_FAXCMD:
- dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
break;
case ISDN_CMD_GETL2:
- dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
break;
case ISDN_CMD_GETL3:
- dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
break;
case ISDN_CMD_GETEAZ:
- dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
break;
case ISDN_CMD_SETSIL:
- dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
break;
case ISDN_CMD_GETSIL:
- dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
break;
default:
- err("unknown command %d from LL",
- cntrl->command);
+ err("unknown command %d from LL", cntrl->command);
return -EINVAL;
}
@@ -350,7 +348,8 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
break;
default:
- err("invalid protocol: %u", bcs->proto2);
+ dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n",
+ __func__, bcs->proto2);
return -EINVAL;
}
@@ -378,7 +377,7 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
bcs->commands[i] = NULL;
if (length[i] &&
!(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
- err("out of memory");
+ dev_err(bcs->cs->dev, "out of memory\n");
return -ENOMEM;
}
}
@@ -396,10 +395,14 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
}
if (bcs->commands[AT_MSN])
- snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn);
- snprintf(bcs->commands[AT_BC ], length[AT_BC ], "^SBC=%s\r", bc);
- snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
- snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned)bcs->channel + 1);
+ snprintf(bcs->commands[AT_MSN], length[AT_MSN],
+ "^SMSN=%s\r", sp->eazmsn);
+ snprintf(bcs->commands[AT_BC ], length[AT_BC ],
+ "^SBC=%s\r", bc);
+ snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
+ "^SBPR=%u\r", proto);
+ snprintf(bcs->commands[AT_ISO ], length[AT_ISO ],
+ "^SISO=%u\r", (unsigned)bcs->channel + 1);
return 0;
}
@@ -419,7 +422,8 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state)
proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
break;
default:
- err("invalid protocol: %u", bcs->proto2);
+ dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n",
+ __func__, bcs->proto2);
return -EINVAL;
}
@@ -436,13 +440,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state)
bcs->commands[i] = NULL;
if (length[i] &&
!(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
- err("out of memory");
+ dev_err(at_state->cs->dev, "out of memory\n");
return -ENOMEM;
}
}
- snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
- snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned) bcs->channel + 1);
+ snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
+ "^SBPR=%u\r", proto);
+ snprintf(bcs->commands[AT_ISO ], length[AT_ISO ],
+ "^SISO=%u\r", (unsigned) bcs->channel + 1);
return 0;
}
@@ -473,7 +479,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
response.parm.setup.si1 = 1;
response.parm.setup.si2 = 2;
} else {
- warn("RING ignored - unsupported BC %s",
+ dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",
at_state->str_var[STR_ZBC]);
return ICALL_IGNORE;
}
@@ -491,18 +497,17 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
response.parm.setup.eazmsn[0] = 0;
if (!bcs) {
- notice("no channel for incoming call");
- dbg(DEBUG_CMD, "Sending ICALLW");
+ dev_notice(cs->dev, "no channel for incoming call\n");
response.command = ISDN_STAT_ICALLW;
response.arg = 0; //FIXME
} else {
- dbg(DEBUG_CMD, "Sending ICALL");
+ gig_dbg(DEBUG_CMD, "Sending ICALL");
response.command = ISDN_STAT_ICALL;
response.arg = bcs->channel; //FIXME
}
response.driver = cs->myid;
retval = cs->iif.statcallb(&response);
- dbg(DEBUG_CMD, "Response: %d", retval);
+ gig_dbg(DEBUG_CMD, "Response: %d", retval);
switch (retval) {
case 0: /* no takers */
return ICALL_IGNORE;
@@ -512,7 +517,8 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
case 2: /* reject */
return ICALL_REJECT;
case 3: /* incomplete */
- warn("LL requested unsupported feature: Incomplete Number");
+ dev_warn(cs->dev,
+ "LL requested unsupported feature: Incomplete Number\n");
return ICALL_IGNORE;
case 4: /* proceeding */
/* Gigaset will send ALERTING anyway.
@@ -520,10 +526,11 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
*/
return ICALL_ACCEPT;
case 5: /* deflect */
- warn("LL requested unsupported feature: Call Deflection");
+ dev_warn(cs->dev,
+ "LL requested unsupported feature: Call Deflection\n");
return ICALL_IGNORE;
default:
- err("LL error %d on ICALL", retval);
+ dev_err(cs->dev, "LL error %d on ICALL\n", retval);
return ICALL_IGNORE;
}
}
@@ -533,7 +540,7 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
{
isdn_if *iif = &cs->iif;
- dbg(DEBUG_ANY, "Register driver capabilities to LL");
+ gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");
//iif->id[sizeof(iif->id) - 1]=0;
//strncpy(iif->id, isdnid, sizeof(iif->id) - 1);
@@ -542,26 +549,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
return -ENOMEM; //FIXME EINVAL/...??
iif->owner = THIS_MODULE;
- iif->channels = cs->channels; /* I am supporting just one channel *//* I was supporting...*/
+ iif->channels = cs->channels;
iif->maxbufsize = MAX_BUF_SIZE;
- iif->features = ISDN_FEATURE_L2_TRANS | /* Our device is very advanced, therefore */
+ iif->features = ISDN_FEATURE_L2_TRANS |
ISDN_FEATURE_L2_HDLC |
#ifdef GIG_X75
ISDN_FEATURE_L2_X75I |
#endif
ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_P_EURO;
- iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */
+ iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */
iif->command = command_from_LL;
iif->writebuf_skb = writebuf_from_LL;
- iif->writecmd = NULL; /* Don't support isdnctrl */
- iif->readstat = NULL; /* Don't support isdnctrl */
- iif->rcvcallb_skb = NULL; /* Will be set by LL */
- iif->statcallb = NULL; /* Will be set by LL */
+ iif->writecmd = NULL; /* Don't support isdnctrl */
+ iif->readstat = NULL; /* Don't support isdnctrl */
+ iif->rcvcallb_skb = NULL; /* Will be set by LL */
+ iif->statcallb = NULL; /* Will be set by LL */
if (!register_isdn(iif))
return 0;
- cs->myid = iif->channels; /* Set my device id */
+ cs->myid = iif->channels; /* Set my device id */
return 1;
}
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 3a81d9c65141..08e4c4eea14d 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -9,8 +9,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -24,7 +22,7 @@ static int if_lock(struct cardstate *cs, int *arg)
{
int cmd = *arg;
- dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
+ gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
if (cmd > 1)
return -EINVAL;
@@ -35,7 +33,7 @@ static int if_lock(struct cardstate *cs, int *arg)
}
if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED
- && atomic_read(&cs->connected)) {
+ && cs->connected) {
cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
cs->ops->baud_rate(cs, B115200);
cs->ops->set_line_ctrl(cs, CS8);
@@ -44,12 +42,12 @@ static int if_lock(struct cardstate *cs, int *arg)
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK,
- NULL, cmd, NULL)) {
+ NULL, cmd, NULL)) {
cs->waiting = 0;
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling IF_LOCK");
+ gig_dbg(DEBUG_CMD, "scheduling IF_LOCK");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
@@ -68,7 +66,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4])
static const unsigned compat[4] = GIG_COMPAT;
unsigned cmd = arg[0];
- dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
+ gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
switch (cmd) {
case GIGVER_DRIVER:
@@ -80,12 +78,12 @@ static int if_version(struct cardstate *cs, unsigned arg[4])
case GIGVER_FWBASE:
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER,
- NULL, 0, arg)) {
+ NULL, 0, arg)) {
cs->waiting = 0;
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling IF_VER");
+ gig_dbg(DEBUG_CMD, "scheduling IF_VER");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
@@ -101,7 +99,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4])
static int if_config(struct cardstate *cs, int *arg)
{
- dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
+ gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
if (*arg != 1)
return -EINVAL;
@@ -109,6 +107,11 @@ static int if_config(struct cardstate *cs, int *arg)
if (atomic_read(&cs->mstate) != MS_LOCKED)
return -EBUSY;
+ if (!cs->connected) {
+ err("not connected!");
+ return -ENODEV;
+ }
+
*arg = 0;
return gigaset_enterconfigmode(cs);
}
@@ -119,7 +122,7 @@ static int if_config(struct cardstate *cs, int *arg)
static int if_open(struct tty_struct *tty, struct file *filp);
static void if_close(struct tty_struct *tty, struct file *filp);
static int if_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
static int if_write_room(struct tty_struct *tty);
static int if_chars_in_buffer(struct tty_struct *tty);
static void if_throttle(struct tty_struct *tty);
@@ -127,9 +130,9 @@ static void if_unthrottle(struct tty_struct *tty);
static void if_set_termios(struct tty_struct *tty, struct termios *old);
static int if_tiocmget(struct tty_struct *tty, struct file *file);
static int if_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear);
+ unsigned int set, unsigned int clear);
static int if_write(struct tty_struct *tty,
- const unsigned char *buf, int count);
+ const unsigned char *buf, int count);
static struct tty_operations if_ops = {
.open = if_open,
@@ -153,8 +156,8 @@ static int if_open(struct tty_struct *tty, struct file *filp)
struct cardstate *cs;
unsigned long flags;
- dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index,
- __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%d+%d: %s()",
+ tty->driver->minor_start, tty->index, __func__);
tty->driver_data = NULL;
@@ -162,7 +165,7 @@ static int if_open(struct tty_struct *tty, struct file *filp)
if (!cs)
return -ENODEV;
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
tty->driver_data = cs;
@@ -173,10 +176,9 @@ static int if_open(struct tty_struct *tty, struct file *filp)
cs->tty = tty;
spin_unlock_irqrestore(&cs->lock, flags);
tty->low_latency = 1; //FIXME test
- //FIXME
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return 0;
}
@@ -187,30 +189,29 @@ static void if_close(struct tty_struct *tty, struct file *filp)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
if (!--cs->open_count) {
spin_lock_irqsave(&cs->lock, flags);
cs->tty = NULL;
spin_unlock_irqrestore(&cs->lock, flags);
- //FIXME
}
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
static int if_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct cardstate *cs;
int retval = -ENODEV;
@@ -220,17 +221,17 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd);
+ gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
retval = 0;
switch (cmd) {
@@ -250,37 +251,40 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
break;
case GIGASET_BRKCHARS:
//FIXME test if MS_LOCKED
- gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
- 6, (const unsigned char *) arg, 1);
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ if (!cs->connected) {
+ gig_dbg(DEBUG_ANY,
+ "can't communicate with unplugged device");
retval = -ENODEV;
break;
}
retval = copy_from_user(&buf,
- (const unsigned char __user *) arg, 6)
- ? -EFAULT : 0;
- if (retval >= 0)
+ (const unsigned char __user *) arg, 6)
+ ? -EFAULT : 0;
+ if (retval >= 0) {
+ gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
+ 6, (const unsigned char *) arg);
retval = cs->ops->brkchars(cs, buf);
+ }
break;
case GIGASET_VERSION:
- retval = copy_from_user(version, (unsigned __user *) arg,
- sizeof version) ? -EFAULT : 0;
+ retval = copy_from_user(version,
+ (unsigned __user *) arg, sizeof version)
+ ? -EFAULT : 0;
if (retval >= 0)
retval = if_version(cs, version);
if (retval >= 0)
- retval = copy_to_user((unsigned __user *) arg, version,
- sizeof version)
- ? -EFAULT : 0;
+ retval = copy_to_user((unsigned __user *) arg,
+ version, sizeof version)
+ ? -EFAULT : 0;
break;
- default:
- dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
- __FUNCTION__, cmd);
+ default:
+ gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
+ __func__, cmd);
retval = -ENOIOCTLCMD;
}
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -292,25 +296,25 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
// FIXME read from device?
retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
static int if_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
struct cardstate *cs;
int retval;
@@ -318,18 +322,18 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF,
- "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear);
+ gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)",
+ cs->minor_index, __func__, set, clear);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");
retval = -ENODEV;
} else {
mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR);
@@ -337,7 +341,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
cs->control_state = mc;
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -349,29 +353,29 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY;
- } else if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't write to unplugged device");
+ } else if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
} else {
retval = cs->ops->write_cmd(cs, buf, count,
- &cs->if_wake_tasklet);
+ &cs->if_wake_tasklet);
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -383,27 +387,27 @@ static int if_write_room(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY; //FIXME
- } else if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't write to unplugged device");
+ } else if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
} else
retval = cs->ops->write_room(cs);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -415,27 +419,27 @@ static int if_chars_in_buffer(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY;
- } else if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't write to unplugged device");
+ } else if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
} else
retval = cs->ops->chars_in_buffer(cs);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -446,21 +450,21 @@ static void if_throttle(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
//FIXME
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
static void if_unthrottle(struct tty_struct *tty)
@@ -469,21 +473,21 @@ static void if_unthrottle(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
//FIXME
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
static void if_set_termios(struct tty_struct *tty, struct termios *old)
@@ -496,21 +500,21 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count) {
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
goto out;
}
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");
goto out;
}
@@ -518,8 +522,8 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
iflag = tty->termios->c_iflag;
cflag = tty->termios->c_cflag;
old_cflag = old ? old->c_cflag : cflag; //FIXME?
- dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index,
- iflag, cflag, old_cflag);
+ gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
+ cs->minor_index, iflag, cflag, old_cflag);
/* get a local copy of the current port settings */
control_state = cs->control_state;
@@ -531,14 +535,15 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
* Premature optimization is the root of all evil.
*/
- /* reassert DTR and (maybe) RTS on transition from B0 */
+ /* reassert DTR and (maybe) RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
new_state = control_state | TIOCM_DTR;
/* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS))
new_state |= TIOCM_RTS;
- dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index,
- (new_state & TIOCM_RTS) ? " only" : "/RTS");
+ gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s",
+ cs->minor_index,
+ (new_state & TIOCM_RTS) ? " only" : "/RTS");
cs->ops->set_modem_ctrl(cs, control_state, new_state);
control_state = new_state;
}
@@ -547,7 +552,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
if ((cflag & CBAUD) == B0) {
/* Drop RTS and DTR */
- dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
+ gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS);
cs->ops->set_modem_ctrl(cs, control_state, new_state);
control_state = new_state;
@@ -567,15 +572,17 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
* Just do what we have seen with SniffUSB on Win98.
*/
/* Drop DTR/RTS if no flow control otherwise assert */
- dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state);
+ gig_dbg(DEBUG_IF, "%u: control_state %x",
+ cs->minor_index, control_state);
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) {
- dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state);
- gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug?
+ gig_dbg(DEBUG_IF, "%u: new_state %x",
+ cs->minor_index, new_state);
+ gigaset_set_modem_ctrl(cs, control_state, new_state);
control_state = new_state;
}
#endif
@@ -584,7 +591,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
cs->control_state = control_state;
out:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
@@ -600,7 +607,7 @@ static void if_wake(unsigned long data)
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup) {
- dbg(DEBUG_IF, "write wakeup call");
+ gig_dbg(DEBUG_IF, "write wakeup call");
tty->ldisc.write_wakeup(tty);
}
@@ -635,14 +642,14 @@ void gigaset_if_free(struct cardstate *cs)
}
void gigaset_if_receive(struct cardstate *cs,
- unsigned char *buffer, size_t len)
+ unsigned char *buffer, size_t len)
{
unsigned long flags;
struct tty_struct *tty;
spin_lock_irqsave(&cs->lock, flags);
if ((tty = cs->tty) == NULL)
- dbg(DEBUG_ANY, "receive on closed device");
+ gig_dbg(DEBUG_ANY, "receive on closed device");
else {
tty_buffer_request_room(tty, len);
tty_insert_flip_string(tty, buffer, len);
@@ -655,13 +662,13 @@ EXPORT_SYMBOL_GPL(gigaset_if_receive);
/* gigaset_if_initdriver
* Initialize tty interface.
* parameters:
- * drv Driver
- * procname Name of the driver (e.g. for /proc/tty/drivers)
- * devname Name of the device files (prefix without minor number)
- * devfsname Devfs name of the device files without %d
+ * drv Driver
+ * procname Name of the driver (e.g. for /proc/tty/drivers)
+ * devname Name of the device files (prefix without minor number)
+ * devfsname Devfs name of the device files without %d
*/
void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
- const char *devname, const char *devfsname)
+ const char *devname, const char *devfsname)
{
unsigned minors = drv->minors;
int ret;
@@ -696,7 +703,7 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
warn("failed to register tty driver (error %d)", ret);
goto error;
}
- dbg(DEBUG_IF, "tty driver initialized");
+ gig_dbg(DEBUG_IF, "tty driver initialized");
drv->have_tty = 1;
return;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 5744eb91b315..8667daaa1a82 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -10,10 +10,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -87,14 +83,14 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
{
if (!atomic_dec_and_test(&iwb->writesem)) {
atomic_inc(&iwb->writesem);
- dbg(DEBUG_ISO,
- "%s: couldn't acquire iso write semaphore", __func__);
+ gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
+ __func__);
return 0;
}
#ifdef CONFIG_GIGASET_DEBUG
- dbg(DEBUG_ISO,
- "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
- __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
+ gig_dbg(DEBUG_ISO,
+ "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
+ __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
#endif
return 1;
}
@@ -147,7 +143,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb)
/* recover the idle flag byte */
write = atomic_read(&iwb->write);
iwb->idle = iwb->data[write];
- dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
+ gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
/* mask extraneous bits in buffer */
iwb->data[write] &= (1 << iwb->wbits) - 1;
}
@@ -166,15 +162,14 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
read = atomic_read(&iwb->nextread);
write = atomic_read(&iwb->write);
if (likely(read == write)) {
- //dbg(DEBUG_STREAM, "%s: send buffer empty", __func__);
/* return idle frame */
return read < BAS_OUTBUFPAD ?
- BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
+ BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
}
limit = read + size;
- dbg(DEBUG_STREAM,
- "%s: read=%d write=%d limit=%d", __func__, read, write, limit);
+ gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d",
+ __func__, read, write, limit);
#ifdef CONFIG_GIGASET_DEBUG
if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) {
err("invalid size %d", size);
@@ -196,11 +191,12 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
return -EBUSY;
/* write position could have changed */
if (limit >= (write = atomic_read(&iwb->write))) {
- pbyte = iwb->data[write]; /* save partial byte */
+ pbyte = iwb->data[write]; /* save
+ partial byte */
limit = write + BAS_OUTBUFPAD;
- dbg(DEBUG_STREAM,
- "%s: filling %d->%d with %02x",
- __func__, write, limit, iwb->idle);
+ gig_dbg(DEBUG_STREAM,
+ "%s: filling %d->%d with %02x",
+ __func__, write, limit, iwb->idle);
if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE)
memset(iwb->data + write, iwb->idle,
BAS_OUTBUFPAD);
@@ -211,9 +207,11 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
- write);
limit = 0;
}
- dbg(DEBUG_STREAM, "%s: restoring %02x at %d",
- __func__, pbyte, limit);
- iwb->data[limit] = pbyte; /* restore partial byte */
+ gig_dbg(DEBUG_STREAM,
+ "%s: restoring %02x at %d",
+ __func__, pbyte, limit);
+ iwb->data[limit] = pbyte; /* restore
+ partial byte */
atomic_set(&iwb->write, limit);
}
isowbuf_donewrite(iwb);
@@ -242,19 +240,17 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
* write hex bytes to syslog for debugging
*/
static inline void dump_bytes(enum debuglevel level, const char *tag,
- unsigned char *bytes, int count)
+ unsigned char *bytes, int count)
{
#ifdef CONFIG_GIGASET_DEBUG
unsigned char c;
static char dbgline[3 * 32 + 1];
static const char hexdigit[] = "0123456789abcdef";
int i = 0;
- IFNULLRET(tag);
- IFNULLRET(bytes);
while (count-- > 0) {
if (i > sizeof(dbgline) - 4) {
dbgline[i] = '\0';
- dbg(level, "%s:%s", tag, dbgline);
+ gig_dbg(level, "%s:%s", tag, dbgline);
i = 0;
}
c = *bytes++;
@@ -264,7 +260,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag,
dbgline[i++] = hexdigit[c & 0x0f];
}
dbgline[i] = '\0';
- dbg(level, "%s:%s", tag, dbgline);
+ gig_dbg(level, "%s:%s", tag, dbgline);
#endif
}
@@ -380,7 +376,7 @@ static u16 stufftab[5 * 256] = {
*/
static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
- int ones)
+ int ones)
{
u16 stuff;
int shiftinc, newones;
@@ -422,7 +418,7 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
*/
static inline int hdlc_buildframe(struct isowbuf_t *iwb,
- unsigned char *in, int count)
+ unsigned char *in, int count)
{
int ones;
u16 fcs;
@@ -431,8 +427,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
!isowbuf_startwrite(iwb)) {
- dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
- __func__, isowbuf_freebytes(iwb));
+ gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
+ __func__, isowbuf_freebytes(iwb));
return -EAGAIN;
}
@@ -484,11 +480,11 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
if (isowbuf_freebytes(iwb) < count ||
!isowbuf_startwrite(iwb)) {
- dbg(DEBUG_ISO, "can't put %d bytes", count);
+ gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
return -EAGAIN;
}
- dbg(DEBUG_STREAM, "put %d bytes", count);
+ gig_dbg(DEBUG_STREAM, "put %d bytes", count);
write = atomic_read(&iwb->write);
do {
c = gigaset_invtab[*in++];
@@ -508,11 +504,13 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
switch (bcs->proto2) {
case ISDN_PROTO_L2_HDLC:
result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
- dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result);
+ gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
+ __func__, len, result);
break;
default: /* assume transparent */
result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len);
- dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result);
+ gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d",
+ __func__, len, result);
}
return result;
}
@@ -528,13 +526,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
return;
}
if (unlikely(bcs->skb->len == SBUFSIZE)) {
- warn("received oversized packet discarded");
+ dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
bcs->hw.bas->giants++;
dev_kfree_skb_any(bcs->skb);
bcs->skb = NULL;
return;
}
- *gigaset_skb_put_quick(bcs->skb, 1) = c;
+ *__skb_put(bcs->skb, 1) = c;
}
/* hdlc_flush
@@ -549,7 +547,7 @@ static inline void hdlc_flush(struct bc_state *bcs)
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
}
/* reset packet state */
@@ -571,23 +569,25 @@ static inline void hdlc_done(struct bc_state *bcs)
if ((procskb = bcs->skb) == NULL) {
/* previous error */
- dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
+ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
gigaset_rcv_error(NULL, bcs->cs, bcs);
} else if (procskb->len < 2) {
- notice("received short frame (%d octets)", procskb->len);
+ dev_notice(bcs->cs->dev, "received short frame (%d octets)\n",
+ procskb->len);
bcs->hw.bas->runts++;
gigaset_rcv_error(procskb, bcs->cs, bcs);
} else if (bcs->fcs != PPP_GOODFCS) {
- notice("frame check error (0x%04x)", bcs->fcs);
+ dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n",
+ bcs->fcs);
bcs->hw.bas->fcserrs++;
gigaset_rcv_error(procskb, bcs->cs, bcs);
} else {
procskb->len -= 2; /* subtract FCS */
procskb->tail -= 2;
- dbg(DEBUG_ISO,
- "%s: good frame (%d octets)", __func__, procskb->len);
+ gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
+ __func__, procskb->len);
dump_bytes(DEBUG_STREAM,
- "rcv data", procskb->data, procskb->len);
+ "rcv data", procskb->data, procskb->len);
bcs->hw.bas->goodbytes += procskb->len;
gigaset_rcv_skb(procskb, bcs->cs, bcs);
}
@@ -595,7 +595,7 @@ static inline void hdlc_done(struct bc_state *bcs)
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
bcs->fcs = PPP_INITFCS;
}
@@ -610,14 +610,14 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
return;
}
- notice("received partial byte (%d bits)", inbits);
+ dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
bcs->hw.bas->alignerrs++;
gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
bcs->fcs = PPP_INITFCS;
}
@@ -659,16 +659,12 @@ static unsigned char bitcounts[256] = {
* bcs receiving B channel structure
*/
static inline void hdlc_unpack(unsigned char *src, unsigned count,
- struct bc_state *bcs)
+ struct bc_state *bcs)
{
- struct bas_bc_state *ubc;
+ struct bas_bc_state *ubc = bcs->hw.bas;
int inputstate;
unsigned seqlen, inbyte, inbits;
- IFNULLRET(bcs);
- ubc = bcs->hw.bas;
- IFNULLRET(ubc);
-
/* load previous state:
* inputstate = set of flag bits:
* - INS_flag_hunt: no complete opening flag received since connection setup or last abort
@@ -856,7 +852,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
* bcs receiving B channel structure
*/
static inline void trans_receive(unsigned char *src, unsigned count,
- struct bc_state *bcs)
+ struct bc_state *bcs)
{
struct sk_buff *skb;
int dobytes;
@@ -870,7 +866,7 @@ static inline void trans_receive(unsigned char *src, unsigned count,
if (unlikely((skb = bcs->skb) == NULL)) {
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
if (!skb) {
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
return;
}
skb_reserve(skb, HW_HDR_LEN);
@@ -888,7 +884,8 @@ static inline void trans_receive(unsigned char *src, unsigned count,
gigaset_rcv_skb(skb, bcs->cs, bcs);
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
if (!skb) {
- err("could not allocate skb");
+ dev_err(bcs->cs->dev,
+ "could not allocate skb\n");
return;
}
skb_reserve(bcs->skb, HW_HDR_LEN);
@@ -921,8 +918,8 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
case '\r':
case '\n':
/* end of line */
- dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
- __func__, cbytes);
+ gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ __func__, cbytes);
cs->cbytes = cbytes;
gigaset_handle_modem_response(cs);
cbytes = 0;
@@ -932,7 +929,7 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
if (cbytes < MAX_RESP_SIZE - 1)
cbytes++;
else
- warn("response too large");
+ dev_warn(cs->dev, "response too large\n");
}
}
@@ -951,27 +948,27 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
head = atomic_read(&inbuf->head);
while (head != (tail = atomic_read(&inbuf->tail))) {
- dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
if (head > tail)
tail = RBUFSIZE;
src = inbuf->data + head;
numbytes = tail - head;
- dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+ gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
if (atomic_read(&cs->mstate) == MS_LOCKED) {
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
- numbytes, src, 0);
+ numbytes, src);
gigaset_if_receive(inbuf->cs, src, numbytes);
} else {
gigaset_dbg_buffer(DEBUG_CMD, "received response",
- numbytes, src, 0);
+ numbytes, src);
cmd_loop(src, numbytes, inbuf);
}
head += numbytes;
if (head == RBUFSIZE)
head = 0;
- dbg(DEBUG_INTR, "setting head to %u", head);
+ gig_dbg(DEBUG_INTR, "setting head to %u", head);
atomic_set(&inbuf->head, head);
}
}
@@ -992,18 +989,22 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
*/
int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
- int len;
+ int len = skb->len;
+ unsigned long flags;
- IFNULLRETVAL(bcs, -EFAULT);
- IFNULLRETVAL(skb, -EFAULT);
- len = skb->len;
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (!bcs->cs->connected) {
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return -ENODEV;
+ }
skb_queue_tail(&bcs->squeue, skb);
- dbg(DEBUG_ISO,
- "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue));
+ gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
+ __func__, skb_queue_len(&bcs->squeue));
/* tasklet submits URB if necessary */
tasklet_schedule(&bcs->hw.bas->sent_tasklet);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return len; /* ok so far */
}
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
index c6915fa2be6c..d267a636b53c 100644
--- a/drivers/isdn/gigaset/proc.c
+++ b/drivers/isdn/gigaset/proc.c
@@ -1,7 +1,7 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
* Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>.
*
@@ -11,26 +11,29 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
#include <linux/ctype.h>
-static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct usb_interface *intf = to_usb_interface(dev);
- struct cardstate *cs = usb_get_intfdata(intf);
- return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096)
+ int ret;
+ unsigned long flags;
+ struct cardstate *cs = dev_get_drvdata(dev);
+
+ spin_lock_irqsave(&cs->lock, flags);
+ ret = sprintf(buf, "%u\n", cs->cidmode);
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ return ret;
}
-static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct usb_interface *intf = to_usb_interface(dev);
- struct cardstate *cs = usb_get_intfdata(intf);
+ struct cardstate *cs = dev_get_drvdata(dev);
long int value;
char *end;
@@ -41,23 +44,23 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co
if (value < 0 || value > 1)
return -EINVAL;
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
- NULL, value, NULL)) {
+ NULL, value, NULL)) {
cs->waiting = 0;
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
+ gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return count;
}
@@ -65,17 +68,15 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co
static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
/* free sysfs for device */
-void gigaset_free_dev_sysfs(struct usb_interface *interface)
+void gigaset_free_dev_sysfs(struct cardstate *cs)
{
- dbg(DEBUG_INIT, "removing sysfs entries");
- device_remove_file(&interface->dev, &dev_attr_cidmode);
+ gig_dbg(DEBUG_INIT, "removing sysfs entries");
+ device_remove_file(cs->dev, &dev_attr_cidmode);
}
-EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs);
/* initialize sysfs for device */
-void gigaset_init_dev_sysfs(struct usb_interface *interface)
+void gigaset_init_dev_sysfs(struct cardstate *cs)
{
- dbg(DEBUG_INIT, "setting up sysfs");
- device_create_file(&interface->dev, &dev_attr_cidmode);
+ gig_dbg(DEBUG_INIT, "setting up sysfs");
+ device_create_file(cs->dev, &dev_attr_cidmode);
}
-EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 323fc7349dec..bfb73fd5077e 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -1,7 +1,7 @@
/*
* USB driver for Gigaset 307x directly or using M105 Data.
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Copyright (c) 2001 by Stefan Eilers
* and Hansjoerg Lipp <hjlipp@web.de>.
*
* This driver was derived from the USB skeleton driver by
@@ -13,10 +13,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -29,7 +25,7 @@
#include <linux/moduleparam.h>
/* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
#define DRIVER_DESC "USB Driver for Gigaset 307x using M105"
/* Module parameters */
@@ -62,10 +58,6 @@ static struct usb_device_id gigaset_table [] = {
MODULE_DEVICE_TABLE(usb, gigaset_table);
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE 200
-
-
/*
* Control requests (empty fields: 00)
*
@@ -114,7 +106,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
*/
static int gigaset_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
+ const struct usb_device_id *id);
static void gigaset_disconnect(struct usb_interface *interface);
static struct gigaset_driver *driver = NULL;
@@ -122,29 +114,29 @@ static struct cardstate *cardstate = NULL;
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver gigaset_usb_driver = {
- .name = GIGASET_MODULENAME,
- .probe = gigaset_probe,
- .disconnect = gigaset_disconnect,
- .id_table = gigaset_table,
+ .name = GIGASET_MODULENAME,
+ .probe = gigaset_probe,
+ .disconnect = gigaset_disconnect,
+ .id_table = gigaset_table,
};
struct usb_cardstate {
- struct usb_device *udev; /* save off the usb device pointer */
- struct usb_interface *interface; /* the interface for this device */
- atomic_t busy; /* bulk output in progress */
-
- /* Output buffer for commands (M105: and data)*/
- unsigned char *bulk_out_buffer; /* the buffer to send data */
- int bulk_out_size; /* the size of the send buffer */
- __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
- struct urb *bulk_out_urb; /* the urb used to transmit data */
-
- /* Input buffer for command responses (M105: and data)*/
- int rcvbuf_size; /* the size of the receive buffer */
- struct urb *read_urb; /* the urb used to receive data */
- __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */
-
- char bchars[6]; /* req. 0x19 */
+ struct usb_device *udev; /* usb device pointer */
+ struct usb_interface *interface; /* interface for this device */
+ atomic_t busy; /* bulk output in progress */
+
+ /* Output buffer */
+ unsigned char *bulk_out_buffer;
+ int bulk_out_size;
+ __u8 bulk_out_endpointAddr;
+ struct urb *bulk_out_urb;
+
+ /* Input buffer */
+ int rcvbuf_size;
+ struct urb *read_urb;
+ __u8 int_in_endpointAddr;
+
+ char bchars[6]; /* for request 0x19 */
};
struct usb_bc_state {};
@@ -157,19 +149,20 @@ static inline unsigned tiocm_to_gigaset(unsigned state)
#ifdef CONFIG_GIGASET_UNDOCREQ
/* WARNING: EXPERIMENTAL! */
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
- unsigned new_state)
+ unsigned new_state)
{
+ struct usb_device *udev = cs->hw.usb->udev;
unsigned mask, val;
int r;
mask = tiocm_to_gigaset(old_state ^ new_state);
val = tiocm_to_gigaset(new_state);
- dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
- r = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41,
- (val & 0xff) | ((mask & 0xff) << 8), 0,
- NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH
+ gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
+ // don't use this in an interrupt/BH
+ r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
+ (val & 0xff) | ((mask & 0xff) << 8), 0,
+ NULL, 0, 2000 /* timeout? */);
if (r < 0)
return r;
//..
@@ -178,30 +171,29 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
static int set_value(struct cardstate *cs, u8 req, u16 val)
{
+ struct usb_device *udev = cs->hw.usb->udev;
int r, r2;
- dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val);
- r = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41,
- 0xf /*?*/, 0,
- NULL, 0, 2000 /*?*/); /* no idea, what this does */
+ gig_dbg(DEBUG_USBREQ, "request %02x (%04x)",
+ (unsigned)req, (unsigned)val);
+ r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41,
+ 0xf /*?*/, 0, NULL, 0, 2000 /*?*/);
+ /* no idea what this does */
if (r < 0) {
- err("error %d on request 0x12", -r);
+ dev_err(&udev->dev, "error %d on request 0x12\n", -r);
return r;
}
- r = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41,
- val, 0,
- NULL, 0, 2000 /*?*/);
+ r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41,
+ val, 0, NULL, 0, 2000 /*?*/);
if (r < 0)
- err("error %d on request 0x%02x", -r, (unsigned)req);
+ dev_err(&udev->dev, "error %d on request 0x%02x\n",
+ -r, (unsigned)req);
- r2 = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
- 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
+ r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+ 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
if (r2 < 0)
- err("error %d on request 0x19", -r2);
+ dev_err(&udev->dev, "error %d on request 0x19\n", -r2);
return r < 0 ? r : (r2 < 0 ? r2 : 0);
}
@@ -229,8 +221,8 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
case B115200: rate = 115200; break;
default:
rate = 9600;
- err("unsupported baudrate request 0x%x,"
- " using default of B9600", cflag);
+ dev_err(cs->dev, "unsupported baudrate request 0x%x,"
+ " using default of B9600\n", cflag);
}
val = 0x383fff / rate + 1;
@@ -259,7 +251,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
case CS8:
val |= 8 << 8; break;
default:
- err("CSIZE was not CS5-CS8, using default of 8");
+ dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n");
val |= 8 << 8;
break;
}
@@ -277,7 +269,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
#else
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
- unsigned new_state)
+ unsigned new_state)
{
return -EINVAL;
}
@@ -309,15 +301,12 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
return 0;
}
-//void send_ack_to_LL(void *data);
static int write_modem(struct cardstate *cs);
static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb);
-/* Handling of send queue. If there is already a skb opened, put data to
- * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue.
- * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler
- * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data.
+/* Write tasklet handler: Continue sending current skb, or send command, or
+ * start sending an skb from the send queue.
*/
static void gigaset_modem_fill(unsigned long data)
{
@@ -327,10 +316,10 @@ static void gigaset_modem_fill(unsigned long data)
unsigned long flags;
int again;
- dbg(DEBUG_OUTPUT, "modem_fill");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill");
if (atomic_read(&cs->hw.usb->busy)) {
- dbg(DEBUG_OUTPUT, "modem_fill: busy");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill: busy");
return;
}
@@ -341,26 +330,27 @@ static void gigaset_modem_fill(unsigned long data)
cb = cs->cmdbuf;
spin_unlock_irqrestore(&cs->cmdlock, flags);
if (cb) { /* commands to send? */
- dbg(DEBUG_OUTPUT, "modem_fill: cb");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill: cb");
if (send_cb(cs, cb) < 0) {
- dbg(DEBUG_OUTPUT,
- "modem_fill: send_cb failed");
- again = 1; /* no callback will be called! */
+ gig_dbg(DEBUG_OUTPUT,
+ "modem_fill: send_cb failed");
+ again = 1; /* no callback will be
+ called! */
}
} else { /* skbs to send? */
bcs->tx_skb = skb_dequeue(&bcs->squeue);
if (bcs->tx_skb)
- dbg(DEBUG_INTR,
- "Dequeued skb (Adr: %lx)!",
- (unsigned long) bcs->tx_skb);
+ gig_dbg(DEBUG_INTR,
+ "Dequeued skb (Adr: %lx)!",
+ (unsigned long) bcs->tx_skb);
}
}
if (bcs->tx_skb) {
- dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
if (write_modem(cs) < 0) {
- dbg(DEBUG_OUTPUT,
- "modem_fill: write_modem failed");
+ gig_dbg(DEBUG_OUTPUT,
+ "modem_fill: write_modem failed");
// FIXME should we tell the LL?
again = 1; /* no callback will be called! */
}
@@ -371,88 +361,85 @@ static void gigaset_modem_fill(unsigned long data)
/**
* gigaset_read_int_callback
*
- * It is called if the data was received from the device. This is almost similiar to
- * the interrupt service routine in the serial device.
+ * It is called if the data was received from the device.
*/
static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
{
+ struct inbuf_t *inbuf = urb->context;
+ struct cardstate *cs = inbuf->cs;
int resubmit = 0;
int r;
- struct cardstate *cs;
unsigned numbytes;
unsigned char *src;
- //unsigned long flags;
- struct inbuf_t *inbuf;
-
- IFNULLRET(urb);
- inbuf = (struct inbuf_t *) urb->context;
- IFNULLRET(inbuf);
- //spin_lock_irqsave(&inbuf->lock, flags);
- cs = inbuf->cs;
- IFNULLGOTO(cs, exit);
- IFNULLGOTO(cardstate, exit);
-
- if (!atomic_read(&cs->connected)) {
- err("%s: disconnected", __func__);
- goto exit;
- }
+ unsigned long flags;
if (!urb->status) {
+ if (!cs->connected) {
+ err("%s: disconnected", __func__); /* should never happen */
+ return;
+ }
+
numbytes = urb->actual_length;
if (numbytes) {
src = inbuf->rcvbuf;
if (unlikely(*src))
- warn("%s: There was no leading 0, but 0x%02x!",
- __func__, (unsigned) *src);
+ dev_warn(cs->dev,
+ "%s: There was no leading 0, but 0x%02x!\n",
+ __func__, (unsigned) *src);
++src; /* skip leading 0x00 */
--numbytes;
if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
- dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
gigaset_schedule_event(inbuf->cs);
}
} else
- dbg(DEBUG_INTR, "Received zero block length");
+ gig_dbg(DEBUG_INTR, "Received zero block length");
resubmit = 1;
} else {
/* The urb might have been killed. */
- dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
- __func__, urb->status);
- if (urb->status != -ENOENT) /* not killed */
+ gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
+ __func__, urb->status);
+ if (urb->status != -ENOENT) { /* not killed */
+ if (!cs->connected) {
+ err("%s: disconnected", __func__); /* should never happen */
+ return;
+ }
resubmit = 1;
+ }
}
-exit:
- //spin_unlock_irqrestore(&inbuf->lock, flags);
+
if (resubmit) {
- r = usb_submit_urb(urb, SLAB_ATOMIC);
+ spin_lock_irqsave(&cs->lock, flags);
+ r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+ spin_unlock_irqrestore(&cs->lock, flags);
if (r)
- err("error %d when resubmitting urb.", -r);
+ dev_err(cs->dev, "error %d when resubmitting urb.\n",
+ -r);
}
}
-/* This callback routine is called when data was transmitted to a B-Channel.
- * Therefore it has to check if there is still data to transmit. This
- * happens by calling modem_fill via task queue.
- *
- */
+/* This callback routine is called when data was transmitted to the device. */
static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs = (struct cardstate *) urb->context;
+ struct cardstate *cs = urb->context;
+ unsigned long flags;
- IFNULLRET(cs);
-#ifdef CONFIG_GIGASET_DEBUG
- if (!atomic_read(&cs->connected)) {
- err("%s:not connected", __func__);
- return;
- }
-#endif
if (urb->status)
- err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems
- are handeled by timeouts or network protocols */
+ dev_err(cs->dev, "bulk transfer failed (status %d)\n",
+ -urb->status);
+ /* That's all we can do. Communication problems
+ are handled by timeouts or network protocols. */
- atomic_set(&cs->hw.usb->busy, 0);
- tasklet_schedule(&cs->write_tasklet);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!cs->connected) {
+ err("%s: not connected", __func__);
+ } else {
+ atomic_set(&cs->hw.usb->busy, 0);
+ tasklet_schedule(&cs->write_tasklet);
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
}
static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
@@ -469,8 +456,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
spin_lock_irqsave(&cs->cmdlock, flags);
cs->cmdbytes -= cs->curlen;
- dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
- cs->curlen, cs->cmdbytes);
+ gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
+ cs->curlen, cs->cmdbytes);
cs->cmdbuf = cb = cb->next;
if (cb) {
cb->prev = NULL;
@@ -487,52 +474,51 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
}
if (cb) {
count = min(cb->len, ucs->bulk_out_size);
+ gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
+
usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
- usb_sndbulkpipe(ucs->udev,
- ucs->bulk_out_endpointAddr & 0x0f),
- cb->buf + cb->offset, count,
- gigaset_write_bulk_callback, cs);
+ usb_sndbulkpipe(ucs->udev,
+ ucs->bulk_out_endpointAddr & 0x0f),
+ cb->buf + cb->offset, count,
+ gigaset_write_bulk_callback, cs);
cb->offset += count;
cb->len -= count;
atomic_set(&ucs->busy, 1);
- dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
- status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+ spin_lock_irqsave(&cs->lock, flags);
+ status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
if (status) {
atomic_set(&ucs->busy, 0);
- err("could not submit urb (error %d).",
+ err("could not submit urb (error %d)\n",
-status);
- cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */
+ cb->len = 0; /* skip urb => remove cb+wakeup
+ in next loop cycle */
}
}
- } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */
+ } while (cb && status); /* next command on error */
return status;
}
-/* Write string into transbuf and send it to modem.
- */
+/* Send command to device. */
static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
- int len, struct tasklet_struct *wake_tasklet)
+ int len, struct tasklet_struct *wake_tasklet)
{
struct cmdbuf_t *cb;
unsigned long flags;
gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
- DEBUG_TRANSCMD : DEBUG_LOCKCMD,
- "CMD Transmit", len, buf, 0);
-
- if (!atomic_read(&cs->connected)) {
- err("%s: not connected", __func__);
- return -ENODEV;
- }
+ DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+ "CMD Transmit", len, buf);
if (len <= 0)
return 0;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
- err("%s: out of memory", __func__);
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
return -ENOMEM;
}
@@ -554,7 +540,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
- tasklet_schedule(&cs->write_tasklet);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (cs->connected)
+ tasklet_schedule(&cs->write_tasklet);
+ spin_unlock_irqrestore(&cs->lock, flags);
return len;
}
@@ -578,11 +567,12 @@ static int gigaset_chars_in_buffer(struct cardstate *cs)
static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
{
#ifdef CONFIG_GIGASET_UNDOCREQ
- gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0);
+ struct usb_device *udev = cs->hw.usb->udev;
+
+ gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf);
memcpy(cs->hw.usb->bchars, buf, 6);
- return usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
- 0, 0, &buf, 6, 2000);
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+ 0, 0, &buf, 6, 2000);
#else
return -EINVAL;
#endif
@@ -604,7 +594,6 @@ static int gigaset_initbcshw(struct bc_state *bcs)
if (!bcs->hw.usb)
return 0;
- //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */
return 1;
}
@@ -614,7 +603,6 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
static void gigaset_freecshw(struct cardstate *cs)
{
- //FIXME
tasklet_kill(&cs->write_tasklet);
kfree(cs->hw.usb);
}
@@ -639,33 +627,21 @@ static int gigaset_initcshw(struct cardstate *cs)
//ucs->urb_cmd_out = NULL;
ucs->read_urb = NULL;
tasklet_init(&cs->write_tasklet,
- &gigaset_modem_fill, (unsigned long) cs);
+ &gigaset_modem_fill, (unsigned long) cs);
return 1;
}
-/* Writes the data of the current open skb into the modem.
- * We have to protect against multiple calls until the
- * callback handler () is called , due to the fact that we
- * are just allowed to send data once to an endpoint. Therefore
- * we using "trans_flg" to synchonize ...
- */
+/* Send data from current skb to the device. */
static int write_modem(struct cardstate *cs)
{
- int ret;
+ int ret = 0;
int count;
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
struct usb_cardstate *ucs = cs->hw.usb;
- //unsigned long flags;
-
- IFNULLRETVAL(bcs->tx_skb, -EINVAL);
-
- dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
+ unsigned long flags;
- ret = -ENODEV;
- IFNULLGOTO(ucs->bulk_out_buffer, error);
- IFNULLGOTO(ucs->bulk_out_urb, error);
- ret = 0;
+ gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
if (!bcs->tx_skb->len) {
dev_kfree_skb_any(bcs->tx_skb);
@@ -679,40 +655,42 @@ static int write_modem(struct cardstate *cs)
count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count);
skb_pull(bcs->tx_skb, count);
-
- usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
- usb_sndbulkpipe(ucs->udev,
- ucs->bulk_out_endpointAddr & 0x0f),
- ucs->bulk_out_buffer, count,
- gigaset_write_bulk_callback, cs);
atomic_set(&ucs->busy, 1);
- dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+ gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+
+ spin_lock_irqsave(&cs->lock, flags);
+ if (cs->connected) {
+ usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
+ usb_sndbulkpipe(ucs->udev,
+ ucs->bulk_out_endpointAddr & 0x0f),
+ ucs->bulk_out_buffer, count,
+ gigaset_write_bulk_callback, cs);
+ ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+ } else {
+ ret = -ENODEV;
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
- ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
if (ret) {
- err("could not submit urb (error %d).", -ret);
+ err("could not submit urb (error %d)\n", -ret);
atomic_set(&ucs->busy, 0);
}
+
if (!bcs->tx_skb->len) {
/* skb sent completely */
gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
- dbg(DEBUG_INTR,
- "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb);
+ gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
+ (unsigned long) bcs->tx_skb);
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
}
return ret;
-error:
- dev_kfree_skb_any(bcs->tx_skb);
- bcs->tx_skb = NULL;
- return ret;
-
}
static int gigaset_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
+ const struct usb_device_id *id)
{
int retval;
struct usb_device *udev = interface_to_usbdev(interface);
@@ -720,16 +698,14 @@ static int gigaset_probe(struct usb_interface *interface,
struct usb_host_interface *hostif;
struct cardstate *cs = NULL;
struct usb_cardstate *ucs = NULL;
- //struct usb_interface_descriptor *iface_desc;
struct usb_endpoint_descriptor *endpoint;
- //isdn_ctrl command;
int buffer_size;
int alt;
- //unsigned long flags;
- info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
- __func__, le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ gig_dbg(DEBUG_ANY,
+ "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
retval = -ENODEV; //FIXME
@@ -744,7 +720,7 @@ static int gigaset_probe(struct usb_interface *interface,
ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
if (alt != 0 || ifnum != 0) {
- warn("ifnum %d, alt %d", ifnum, alt);
+ dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt);
return -ENODEV;
}
@@ -752,42 +728,29 @@ static int gigaset_probe(struct usb_interface *interface,
*
*/
if (hostif->desc.bInterfaceClass != 255) {
- info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !",
- __func__, ifnum, hostif->desc.bInterfaceClass);
+ dev_info(&udev->dev,
+ "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n",
+ __func__, ifnum, hostif->desc.bInterfaceClass);
return -ENODEV;
}
- info("%s: Device matched ... !", __func__);
+ dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
cs = gigaset_getunassignedcs(driver);
if (!cs) {
- warn("No free cardstate!");
+ dev_warn(&udev->dev, "no free cardstate\n");
return -ENODEV;
}
ucs = cs->hw.usb;
-#if 0
- if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) {
- warn("set_configuration failed");
- goto error;
- }
-
-
- if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) {
- warn("usb_set_interface failed, device %d interface %d altsetting %d",
- udev->devnum, ifnum, alt);
- goto error;
- }
-#endif
+ /* save off device structure ptrs for later use */
+ usb_get_dev(udev);
+ ucs->udev = udev;
+ ucs->interface = interface;
+ cs->dev = &interface->dev;
- /* set up the endpoint information */
- /* check out the endpoints */
- /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to
- * poll messages from the device(int in).
- * Therefore we will have an almost similiar situation as with our serial port handler.
- * If an connection will be established, we will have to create data in/out pipes
- * dynamically...
- */
+ /* save address of controller structure */
+ usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs);
endpoint = &hostif->endpoint[0].desc;
@@ -796,14 +759,14 @@ static int gigaset_probe(struct usb_interface *interface,
ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!ucs->bulk_out_buffer) {
- err("Couldn't allocate bulk_out_buffer");
+ dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n");
retval = -ENOMEM;
goto error;
}
ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL);
if (!ucs->bulk_out_urb) {
- err("Couldn't allocate bulk_out_buffer");
+ dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n");
retval = -ENOMEM;
goto error;
}
@@ -811,12 +774,10 @@ static int gigaset_probe(struct usb_interface *interface,
endpoint = &hostif->endpoint[1].desc;
atomic_set(&ucs->busy, 0);
- ucs->udev = udev;
- ucs->interface = interface;
ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL);
if (!ucs->read_urb) {
- err("No free urbs available");
+ dev_err(cs->dev, "No free urbs available\n");
retval = -ENOMEM;
goto error;
}
@@ -825,38 +786,33 @@ static int gigaset_probe(struct usb_interface *interface,
ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
if (!cs->inbuf[0].rcvbuf) {
- err("Couldn't allocate rcvbuf");
+ dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
retval = -ENOMEM;
goto error;
}
/* Fill the interrupt urb and send it to the core */
usb_fill_int_urb(ucs->read_urb, udev,
- usb_rcvintpipe(udev,
- endpoint->bEndpointAddress & 0x0f),
- cs->inbuf[0].rcvbuf, buffer_size,
- gigaset_read_int_callback,
- cs->inbuf + 0, endpoint->bInterval);
+ usb_rcvintpipe(udev,
+ endpoint->bEndpointAddress & 0x0f),
+ cs->inbuf[0].rcvbuf, buffer_size,
+ gigaset_read_int_callback,
+ cs->inbuf + 0, endpoint->bInterval);
retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL);
if (retval) {
- err("Could not submit URB!");
+ dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval);
goto error;
}
/* tell common part that the device is ready */
if (startmode == SM_LOCKED)
atomic_set(&cs->mstate, MS_LOCKED);
+
if (!gigaset_start(cs)) {
tasklet_kill(&cs->write_tasklet);
retval = -ENODEV; //FIXME
goto error;
}
-
- /* save address of controller structure */
- usb_set_intfdata(interface, cs);
-
- /* set up device sysfs */
- gigaset_init_dev_sysfs(interface);
return 0;
error:
@@ -868,48 +824,45 @@ error:
kfree(cs->inbuf[0].rcvbuf);
if (ucs->read_urb != NULL)
usb_free_urb(ucs->read_urb);
+ usb_set_intfdata(interface, NULL);
ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ usb_put_dev(ucs->udev);
+ ucs->udev = NULL;
+ ucs->interface = NULL;
gigaset_unassign(cs);
return retval;
}
-/**
- * skel_disconnect
- */
static void gigaset_disconnect(struct usb_interface *interface)
{
struct cardstate *cs;
struct usb_cardstate *ucs;
cs = usb_get_intfdata(interface);
-
- /* clear device sysfs */
- gigaset_free_dev_sysfs(interface);
-
- usb_set_intfdata(interface, NULL);
ucs = cs->hw.usb;
usb_kill_urb(ucs->read_urb);
- //info("GigaSet USB device #%d will be disconnected", minor);
gigaset_stop(cs);
+ usb_set_intfdata(interface, NULL);
tasklet_kill(&cs->write_tasklet);
- usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */
- //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */
+ usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */
kfree(ucs->bulk_out_buffer);
if (ucs->bulk_out_urb != NULL)
usb_free_urb(ucs->bulk_out_urb);
- //if(ucs->urb_cmd_out != NULL)
- // usb_free_urb(ucs->urb_cmd_out);
kfree(cs->inbuf[0].rcvbuf);
if (ucs->read_urb != NULL)
usb_free_urb(ucs->read_urb);
- ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL;
+ ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ usb_put_dev(ucs->udev);
+ ucs->interface = NULL;
+ ucs->udev = NULL;
+ cs->dev = NULL;
gigaset_unassign(cs);
}
@@ -942,9 +895,9 @@ static int __init usb_gigaset_init(void)
/* allocate memory for our driver state and intialize it */
if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
- GIGASET_MODULENAME, GIGASET_DEVNAME,
- GIGASET_DEVFSNAME, &ops,
- THIS_MODULE)) == NULL)
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ GIGASET_DEVFSNAME, &ops,
+ THIS_MODULE)) == NULL)
goto error;
/* allocate memory for our device state and intialize it */
@@ -981,8 +934,8 @@ error: if (cardstate)
static void __exit usb_gigaset_exit(void)
{
gigaset_blockdriver(driver); /* => probe will fail
- * => no gigaset_start any more
- */
+ * => no gigaset_start any more
+ */
gigaset_shutdown(cardstate);
/* from now on, no isdn callback should be possible */
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 2a2b03ff096b..7bbfd85ab793 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -51,8 +51,8 @@ MODULE_LICENSE("GPL");
handler.
*/
-static void avmcs_config(dev_link_t *link);
-static void avmcs_release(dev_link_t *link);
+static int avmcs_config(struct pcmcia_device *link);
+static void avmcs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -65,10 +65,10 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the skeleton device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -78,7 +78,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
@@ -99,54 +99,38 @@ typedef struct local_info_t {
======================================================================*/
-static int avmcs_attach(struct pcmcia_device *p_dev)
+static int avmcs_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- goto err;
- memset(link, 0, sizeof(struct dev_link_t));
-
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 16;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts2 = 0;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.NumPorts2 = 0;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
- goto err_kfree;
+ goto err;
memset(local, 0, sizeof(local_info_t));
- link->priv = local;
+ p_dev->priv = local;
- link->handle = p_dev;
- p_dev->instance = link;
+ return avmcs_config(p_dev);
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- avmcs_config(link);
-
- return 0;
-
- err_kfree:
- kfree(link);
err:
- return -EINVAL;
+ return -ENOMEM;
} /* avmcs_attach */
/*======================================================================
@@ -158,15 +142,10 @@ static int avmcs_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void avmcs_detach(struct pcmcia_device *p_dev)
+static void avmcs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- if (link->state & DEV_CONFIG)
avmcs_release(link);
-
- kfree(link->priv);
- kfree(link);
+ kfree(link->priv);
} /* avmcs_detach */
/*======================================================================
@@ -177,7 +156,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -185,7 +164,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -193,7 +172,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -201,9 +180,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void avmcs_config(dev_link_t *link)
+static int avmcs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -213,8 +191,7 @@ static void avmcs_config(dev_link_t *link)
char devname[128];
int cardtype;
int (*addcard)(unsigned int port, unsigned irq);
-
- handle = link->handle;
+
dev = link->priv;
/*
@@ -223,25 +200,21 @@ static void avmcs_config(dev_link_t *link)
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
- i = pcmcia_get_first_tuple(handle, &tuple);
+ i = pcmcia_get_first_tuple(link, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- i = pcmcia_get_tuple_data(handle, &tuple);
+ i = pcmcia_get_tuple_data(link, &tuple);
if (i != CS_SUCCESS) break;
- i = pcmcia_parse_tuple(handle, &tuple, &parse);
+ i = pcmcia_parse_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
- cs_error(link->handle, ParseTuple, i);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ cs_error(link, ParseTuple, i);
+ return -ENODEV;
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
do {
@@ -252,7 +225,7 @@ static void avmcs_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
- if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+ if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
@@ -263,7 +236,7 @@ static void avmcs_config(dev_link_t *link)
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if (cf->io.nwin > 0) {
link->conf.ConfigIndex = cf->index;
@@ -273,36 +246,36 @@ static void avmcs_config(dev_link_t *link)
printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
break;
}
-
+
/*
* allocate an interrupt line
*/
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
- pcmcia_release_io(link->handle, &link->io);
+ cs_error(link, RequestIRQ, i);
+ /* undo */
+ pcmcia_disable_device(link);
break;
}
-
+
/*
* configure the PCMCIA socket
*/
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ cs_error(link, RequestConfiguration, i);
+ pcmcia_disable_device(link);
break;
}
@@ -331,13 +304,12 @@ found_port:
dev->node.major = 64;
dev->node.minor = 0;
- link->dev = &dev->node;
-
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &dev->node;
+
/* If any step failed, release any partially configured state */
if (i != 0) {
avmcs_release(link);
- return;
+ return -ENODEV;
}
@@ -351,9 +323,10 @@ found_port:
printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
avmcs_release(link);
- return;
+ return -ENODEV;
}
dev->node.minor = i;
+ return 0;
} /* avmcs_config */
@@ -365,56 +338,12 @@ found_port:
======================================================================*/
-static void avmcs_release(dev_link_t *link)
+static void avmcs_release(struct pcmcia_device *link)
{
- b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
-
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
+ pcmcia_disable_device(link);
} /* avmcs_release */
-static int avmcs_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int avmcs_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
-
-======================================================================*/
-
static struct pcmcia_device_id avmcs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
@@ -429,11 +358,9 @@ static struct pcmcia_driver avmcs_driver = {
.drv = {
.name = "avm_cs",
},
- .probe = avmcs_attach,
+ .probe = avmcs_probe,
.remove = avmcs_detach,
.id_table = avmcs_ids,
- .suspend= avmcs_suspend,
- .resume = avmcs_resume,
};
static int __init avmcs_init(void)
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 969da40c4248..ac28e3278ad9 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -67,8 +67,8 @@ module_param(isdnprot, int, 0);
handler.
*/
-static void avma1cs_config(dev_link_t *link);
-static void avma1cs_release(dev_link_t *link);
+static int avma1cs_config(struct pcmcia_device *link);
+static void avma1cs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -82,10 +82,10 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the skeleton device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -95,7 +95,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
@@ -116,55 +116,40 @@ typedef struct local_info_t {
======================================================================*/
-static int avma1cs_attach(struct pcmcia_device *p_dev)
+static int avma1cs_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "avma1cs_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
- memset(link, 0, sizeof(struct dev_link_t));
-
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
- if (!local) {
- kfree(link);
+ if (!local)
return -ENOMEM;
- }
+
memset(local, 0, sizeof(local_info_t));
- link->priv = local;
+ p_dev->priv = local;
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 16;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts2 = 16;
- link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
- link->io.IOAddrLines = 5;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.NumPorts2 = 16;
+ p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+ p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- avma1cs_config(link);
-
- return 0;
+ return avma1cs_config(p_dev);
} /* avma1cs_attach */
/*======================================================================
@@ -176,17 +161,11 @@ static int avma1cs_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void avma1cs_detach(struct pcmcia_device *p_dev)
+static void avma1cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-
- if (link->state & DEV_CONFIG)
- avma1cs_release(link);
-
- kfree(link->priv);
- kfree(link);
+ DEBUG(0, "avma1cs_detach(0x%p)\n", link);
+ avma1cs_release(link);
+ kfree(link->priv);
} /* avma1cs_detach */
/*======================================================================
@@ -197,7 +176,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -205,7 +184,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -213,7 +192,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -221,9 +200,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void avma1cs_config(dev_link_t *link)
+static int avma1cs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -233,8 +211,7 @@ static void avma1cs_config(dev_link_t *link)
char devname[128];
IsdnCard_t icard;
int busy = 0;
-
- handle = link->handle;
+
dev = link->priv;
DEBUG(0, "avma1cs_config(0x%p)\n", link);
@@ -245,25 +222,21 @@ static void avma1cs_config(dev_link_t *link)
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
- i = pcmcia_get_first_tuple(handle, &tuple);
+ i = pcmcia_get_first_tuple(link, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- i = pcmcia_get_tuple_data(handle, &tuple);
+ i = pcmcia_get_tuple_data(link, &tuple);
if (i != CS_SUCCESS) break;
- i = pcmcia_parse_tuple(handle, &tuple, &parse);
+ i = pcmcia_parse_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
- cs_error(link->handle, ParseTuple, i);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ cs_error(link, ParseTuple, i);
+ return -ENODEV;
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
do {
@@ -274,7 +247,7 @@ static void avma1cs_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
- if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+ if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
@@ -285,7 +258,7 @@ static void avma1cs_config(dev_link_t *link)
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if (cf->io.nwin > 0) {
link->conf.ConfigIndex = cf->index;
@@ -295,36 +268,36 @@ static void avma1cs_config(dev_link_t *link)
printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1 - 1);
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
break;
}
/*
* allocate an interrupt line
*/
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
- pcmcia_release_io(link->handle, &link->io);
+ cs_error(link, RequestIRQ, i);
+ /* undo */
+ pcmcia_disable_device(link);
break;
}
-
+
/*
* configure the PCMCIA socket
*/
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ cs_error(link, RequestConfiguration, i);
+ pcmcia_disable_device(link);
break;
}
@@ -336,13 +309,12 @@ found_port:
strcpy(dev->node.dev_name, "A1");
dev->node.major = 45;
dev->node.minor = 0;
- link->dev = &dev->node;
-
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &dev->node;
+
/* If any step failed, release any partially configured state */
if (i != 0) {
avma1cs_release(link);
- return;
+ return -ENODEV;
}
printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
@@ -357,10 +329,11 @@ found_port:
if (i < 0) {
printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
avma1cs_release(link);
- return;
+ return -ENODEV;
}
dev->node.minor = i;
+ return 0;
} /* avma1cs_config */
/*======================================================================
@@ -371,47 +344,18 @@ found_port:
======================================================================*/
-static void avma1cs_release(dev_link_t *link)
+static void avma1cs_release(struct pcmcia_device *link)
{
- local_info_t *local = link->priv;
+ local_info_t *local = link->priv;
- DEBUG(0, "avma1cs_release(0x%p)\n", link);
+ DEBUG(0, "avma1cs_release(0x%p)\n", link);
- /* no unregister function with hisax */
- HiSax_closecard(local->node.minor);
+ /* now unregister function with hisax */
+ HiSax_closecard(local->node.minor);
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* avma1cs_release */
-static int avma1cs_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int avma1cs_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
static struct pcmcia_device_id avma1cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -425,13 +369,11 @@ static struct pcmcia_driver avma1cs_driver = {
.drv = {
.name = "avma1_cs",
},
- .probe = avma1cs_attach,
+ .probe = avma1cs_probe,
.remove = avma1cs_detach,
.id_table = avma1cs_ids,
- .suspend = avma1cs_suspend,
- .resume = avma1cs_resume,
};
-
+
/*====================================================================*/
static int __init init_avma1_cs(void)
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 062fb8f0739f..e18e75be8ed3 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -94,8 +94,8 @@ module_param(protocol, int, 0);
handler.
*/
-static void elsa_cs_config(dev_link_t *link);
-static void elsa_cs_release(dev_link_t *link);
+static int elsa_cs_config(struct pcmcia_device *link);
+static void elsa_cs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -111,7 +111,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
In this case, we also provide a flag to indicate if a device is
@@ -121,7 +121,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int busy;
int cardnr;
@@ -139,9 +139,8 @@ typedef struct local_info_t {
======================================================================*/
-static int elsa_cs_attach(struct pcmcia_device *p_dev)
+static int elsa_cs_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "elsa_cs_attach()\n");
@@ -150,8 +149,11 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
+
+ local->p_dev = link;
+ link->priv = local;
+
local->cardnr = -1;
- link = &local->link; link->priv = local;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -170,16 +172,9 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
link->io.IOAddrLines = 3;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- elsa_cs_config(link);
-
- return 0;
+ return elsa_cs_config(link);
} /* elsa_cs_attach */
/*======================================================================
@@ -191,20 +186,16 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void elsa_cs_detach(struct pcmcia_device *p_dev)
+static void elsa_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- local_info_t *info = link->priv;
+ local_info_t *info = link->priv;
- DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
+ DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG) {
- info->busy = 1;
- elsa_cs_release(link);
- }
-
- kfree(info);
+ info->busy = 1;
+ elsa_cs_release(link);
+ kfree(info);
} /* elsa_cs_detach */
/*======================================================================
@@ -214,7 +205,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev)
device available to the system.
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -222,7 +213,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -230,7 +221,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -238,9 +229,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void elsa_cs_config(dev_link_t *link)
+static int elsa_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -250,7 +240,6 @@ static void elsa_cs_config(dev_link_t *link)
IsdnCard_t icard;
DEBUG(0, "elsa_config(0x%p)\n", link);
- handle = link->handle;
dev = link->priv;
/*
@@ -262,7 +251,7 @@ static void elsa_cs_config(dev_link_t *link)
tuple.TupleDataMax = 255;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -270,32 +259,29 @@ static void elsa_cs_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
} else {
printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
link->conf.ConfigIndex = cf->index;
for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
link->io.BasePort1 = j;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
break;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
if (i != CS_SUCCESS) {
@@ -303,14 +289,14 @@ static void elsa_cs_config(dev_link_t *link)
goto cs_failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
link->irq.AssignedIRQ = 0;
last_fn = RequestIRQ;
goto cs_failed;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
last_fn = RequestConfiguration;
goto cs_failed;
@@ -321,14 +307,11 @@ static void elsa_cs_config(dev_link_t *link)
sprintf(dev->node.dev_name, "elsa");
dev->node.major = dev->node.minor = 0x0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev->node.dev_name, link->conf.ConfigIndex);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -339,8 +322,6 @@ static void elsa_cs_config(dev_link_t *link)
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
icard.protocol = protocol;
@@ -354,10 +335,11 @@ static void elsa_cs_config(dev_link_t *link)
} else
((local_info_t*)link->priv)->cardnr = i;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, i);
+ cs_error(link, last_fn, i);
elsa_cs_release(link);
+ return -ENODEV;
} /* elsa_cs_config */
/*======================================================================
@@ -368,7 +350,7 @@ cs_failed:
======================================================================*/
-static void elsa_cs_release(dev_link_t *link)
+static void elsa_cs_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -380,39 +362,23 @@ static void elsa_cs_release(dev_link_t *link)
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+
+ pcmcia_disable_device(link);
} /* elsa_cs_release */
-static int elsa_suspend(struct pcmcia_device *p_dev)
+static int elsa_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->busy = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int elsa_resume(struct pcmcia_device *p_dev)
+static int elsa_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0;
return 0;
@@ -430,7 +396,7 @@ static struct pcmcia_driver elsa_cs_driver = {
.drv = {
.name = "elsa_cs",
},
- .probe = elsa_cs_attach,
+ .probe = elsa_cs_probe,
.remove = elsa_cs_detach,
.id_table = elsa_ids,
.suspend = elsa_suspend,
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 6f5213a18a8d..9bb18f3f7829 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -95,8 +95,8 @@ module_param(protocol, int, 0);
event handler.
*/
-static void sedlbauer_config(dev_link_t *link);
-static void sedlbauer_release(dev_link_t *link);
+static int sedlbauer_config(struct pcmcia_device *link);
+static void sedlbauer_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -119,7 +119,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
@@ -130,7 +130,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev);
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int stop;
int cardnr;
@@ -148,11 +148,10 @@ typedef struct local_info_t {
======================================================================*/
-static int sedlbauer_attach(struct pcmcia_device *p_dev)
+static int sedlbauer_probe(struct pcmcia_device *link)
{
local_info_t *local;
- dev_link_t *link;
-
+
DEBUG(0, "sedlbauer_attach()\n");
/* Allocate space for private device-specific data */
@@ -160,8 +159,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
- link = &local->link; link->priv = local;
-
+
+ local->p_dev = link;
+ link->priv = local;
+
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -182,18 +183,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = 3;
-
link->conf.Attributes = 0;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sedlbauer_config(link);
-
- return 0;
+ return sedlbauer_config(link);
} /* sedlbauer_attach */
/*======================================================================
@@ -205,19 +198,15 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void sedlbauer_detach(struct pcmcia_device *p_dev)
+static void sedlbauer_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
+ DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG) {
- ((local_info_t *)link->priv)->stop = 1;
- sedlbauer_release(link);
- }
+ ((local_info_t *)link->priv)->stop = 1;
+ sedlbauer_release(link);
- /* This points to the parent local_info_t struct */
- kfree(link->priv);
+ /* This points to the parent local_info_t struct */
+ kfree(link->priv);
} /* sedlbauer_detach */
/*======================================================================
@@ -230,9 +219,8 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void sedlbauer_config(dev_link_t *link)
+static int sedlbauer_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
local_info_t *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -254,18 +242,13 @@ static void sedlbauer_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
/*
In this loop, we scan the CIS for configuration table entries,
@@ -280,12 +263,12 @@ static void sedlbauer_config(dev_link_t *link)
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -309,10 +292,10 @@ static void sedlbauer_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
@@ -339,13 +322,13 @@ static void sedlbauer_config(dev_link_t *link)
link->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
/*
Now set up a common memory window, if needed. There is room
- in the dev_link_t structure for one memory window handle,
+ in the struct pcmcia_device structure for one memory window handle,
but if the base addresses need to be saved, or if multiple
windows are needed, the info should go in the private data
structure for this device.
@@ -366,7 +349,7 @@ static void sedlbauer_config(dev_link_t *link)
req.Size = 0x1000;
*/
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -374,29 +357,25 @@ static void sedlbauer_config(dev_link_t *link)
}
/* If we got this far, we're cool! */
break;
-
+
next_entry:
-/* new in dummy.cs 2001/01/28 MN
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
-*/
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
-
+
/*
Allocate an interrupt line. Note that this does not assign a
handler to the interrupt, unless the 'Handler' member of the
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
At this point, the dev_node_t structure(s) need to be
@@ -404,14 +383,13 @@ static void sedlbauer_config(dev_link_t *link)
*/
sprintf(dev->node.dev_name, "sedlbauer");
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x:",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -424,8 +402,6 @@ static void sedlbauer_config(dev_link_t *link)
printk(", mem 0x%06lx-0x%06lx", req.Base,
req.Base+req.Size-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
@@ -437,14 +413,16 @@ static void sedlbauer_config(dev_link_t *link)
printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
last_ret, link->io.BasePort1);
sedlbauer_release(link);
+ return -ENODEV;
} else
((local_info_t*)link->priv)->cardnr = last_ret;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
sedlbauer_release(link);
+ return -ENODEV;
} /* sedlbauer_config */
@@ -456,7 +434,7 @@ cs_failed:
======================================================================*/
-static void sedlbauer_release(dev_link_t *link)
+static void sedlbauer_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
DEBUG(0, "sedlbauer_release(0x%p)\n", link);
@@ -467,46 +445,23 @@ static void sedlbauer_release(dev_link_t *link)
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
- /*
- In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
- */
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* sedlbauer_release */
-static int sedlbauer_suspend(struct pcmcia_device *p_dev)
+static int sedlbauer_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int sedlbauer_resume(struct pcmcia_device *p_dev)
+static int sedlbauer_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->stop = 0;
return 0;
@@ -530,7 +485,7 @@ static struct pcmcia_driver sedlbauer_driver = {
.drv = {
.name = "sedlbauer_cs",
},
- .probe = sedlbauer_attach,
+ .probe = sedlbauer_probe,
.remove = sedlbauer_detach,
.id_table = sedlbauer_ids,
.suspend = sedlbauer_suspend,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 4e5c14c7240e..afcc2aeadb34 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -75,8 +75,8 @@ module_param(protocol, int, 0);
handler.
*/
-static void teles_cs_config(dev_link_t *link);
-static void teles_cs_release(dev_link_t *link);
+static int teles_cs_config(struct pcmcia_device *link);
+static void teles_cs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -89,10 +89,10 @@ static void teles_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the teles_cs device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -102,7 +102,7 @@ static void teles_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
In this case, we also provide a flag to indicate if a device is
@@ -112,7 +112,7 @@ static void teles_detach(struct pcmcia_device *p_dev);
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int busy;
int cardnr;
@@ -130,9 +130,8 @@ typedef struct local_info_t {
======================================================================*/
-static int teles_attach(struct pcmcia_device *p_dev)
+static int teles_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "teles_attach()\n");
@@ -142,7 +141,9 @@ static int teles_attach(struct pcmcia_device *p_dev)
if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
- link = &local->link; link->priv = local;
+
+ local->p_dev = link;
+ link->priv = local;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -161,16 +162,9 @@ static int teles_attach(struct pcmcia_device *p_dev)
link->io.IOAddrLines = 5;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- teles_cs_config(link);
-
- return 0;
+ return teles_cs_config(link);
} /* teles_attach */
/*======================================================================
@@ -182,20 +176,16 @@ static int teles_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void teles_detach(struct pcmcia_device *p_dev)
+static void teles_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- local_info_t *info = link->priv;
-
- DEBUG(0, "teles_detach(0x%p)\n", link);
+ local_info_t *info = link->priv;
- if (link->state & DEV_CONFIG) {
- info->busy = 1;
- teles_cs_release(link);
- }
+ DEBUG(0, "teles_detach(0x%p)\n", link);
- kfree(info);
+ info->busy = 1;
+ teles_cs_release(link);
+ kfree(info);
} /* teles_detach */
/*======================================================================
@@ -205,7 +195,7 @@ static void teles_detach(struct pcmcia_device *p_dev)
device available to the system.
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -213,7 +203,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -221,7 +211,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -229,9 +219,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void teles_cs_config(dev_link_t *link)
+static int teles_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -241,7 +230,6 @@ static void teles_cs_config(dev_link_t *link)
IsdnCard_t icard;
DEBUG(0, "teles_config(0x%p)\n", link);
- handle = link->handle;
dev = link->priv;
/*
@@ -253,7 +241,7 @@ static void teles_cs_config(dev_link_t *link)
tuple.TupleDataMax = 255;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -261,32 +249,29 @@ static void teles_cs_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
} else {
printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
link->conf.ConfigIndex = cf->index;
for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
link->io.BasePort1 = j;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
break;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
if (i != CS_SUCCESS) {
@@ -294,14 +279,14 @@ static void teles_cs_config(dev_link_t *link)
goto cs_failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
link->irq.AssignedIRQ = 0;
last_fn = RequestIRQ;
goto cs_failed;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
last_fn = RequestConfiguration;
goto cs_failed;
@@ -312,14 +297,11 @@ static void teles_cs_config(dev_link_t *link)
sprintf(dev->node.dev_name, "teles");
dev->node.major = dev->node.minor = 0x0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x:",
+ dev->node.dev_name, link->conf.ConfigIndex);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -330,8 +312,6 @@ static void teles_cs_config(dev_link_t *link)
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
icard.protocol = protocol;
@@ -342,13 +322,16 @@ static void teles_cs_config(dev_link_t *link)
printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
i, link->io.BasePort1);
teles_cs_release(link);
- } else
- ((local_info_t*)link->priv)->cardnr = i;
+ return -ENODEV;
+ }
+
+ ((local_info_t*)link->priv)->cardnr = i;
+ return 0;
- return;
cs_failed:
- cs_error(link->handle, last_fn, i);
+ cs_error(link, last_fn, i);
teles_cs_release(link);
+ return -ENODEV;
} /* teles_cs_config */
/*======================================================================
@@ -359,7 +342,7 @@ cs_failed:
======================================================================*/
-static void teles_cs_release(dev_link_t *link)
+static void teles_cs_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -371,39 +354,23 @@ static void teles_cs_release(dev_link_t *link)
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+
+ pcmcia_disable_device(link);
} /* teles_cs_release */
-static int teles_suspend(struct pcmcia_device *p_dev)
+static int teles_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->busy = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int teles_resume(struct pcmcia_device *p_dev)
+static int teles_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0;
return 0;
@@ -421,7 +388,7 @@ static struct pcmcia_driver teles_cs_driver = {
.drv = {
.name = "teles_cs",
},
- .probe = teles_attach,
+ .probe = teles_probe,
.remove = teles_detach,
.id_table = teles_ids,
.suspend = teles_suspend,
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index a0927d1b7a0c..918742271c79 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -109,7 +109,7 @@ isdn_ppp_free(isdn_net_local * lp)
{
struct ippp_struct *is;
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
__FUNCTION__, lp->ppp_slot);
return 0;
@@ -126,7 +126,7 @@ isdn_ppp_free(isdn_net_local * lp)
lp->netdev->pb->ref_ct--;
spin_unlock(&lp->netdev->pb->lock);
#endif /* CONFIG_ISDN_MPP */
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
__FUNCTION__, lp->ppp_slot);
return 0;
@@ -279,7 +279,7 @@ isdn_ppp_open(int min, struct file *file)
int slot;
struct ippp_struct *is;
- if (min < 0 || min > ISDN_MAX_CHANNELS)
+ if (min < 0 || min >= ISDN_MAX_CHANNELS)
return -ENODEV;
slot = isdn_ppp_get_slot();
@@ -1042,7 +1042,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
if (lp->master) { // FIXME?
mlp = (isdn_net_local *) lp->master->priv;
slot = mlp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
lp->ppp_slot);
goto drop_packet;
@@ -1264,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
/* we have our lp locked from now on */
slot = lp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
lp->ppp_slot);
kfree_skb(skb);
@@ -1603,7 +1603,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
mp = net_dev->pb;
stats = &mp->stats;
slot = lp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
__FUNCTION__, lp->ppp_slot);
stats->frame_drops++;
@@ -1640,7 +1640,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
is->last_link_seqno = minseq = newseq;
for (lpq = net_dev->queue;;) {
slot = lpq->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
__FUNCTION__, lpq->ppp_slot);
} else {
@@ -2648,7 +2648,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
lp->ppp_slot);
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__FUNCTION__, lp->ppp_slot);
return;
@@ -2658,7 +2658,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
if(lp->master) {
int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: slot(%d) out of range\n",
__FUNCTION__, slot);
return;
@@ -2845,7 +2845,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
if (lp->master) {
slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: slot(%d) out of range\n",
__FUNCTION__, slot);
return;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 2c4f20b7f021..3f5b64794542 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -14,13 +14,7 @@ config LEDS_CLASS
This option enables the led sysfs class in /sys/class/leds. You'll
need this to do anything useful with LEDs. If unsure, say N.
-config LEDS_TRIGGERS
- bool "LED Trigger support"
- depends NEW_LEDS
- help
- This option enables trigger support for the leds class.
- These triggers allow kernel events to drive the LEDs and can
- be configured via sysfs. If unsure, say Y.
+comment "LED drivers"
config LEDS_CORGI
tristate "LED Support for the Sharp SL-C7x0 series"
@@ -59,6 +53,23 @@ config LEDS_TOSA
This option enables support for the LEDs on Sharp Zaurus
SL-6000 series.
+config LEDS_S3C24XX
+ tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+ depends on LEDS_CLASS && ARCH_S3C2410
+ help
+ This option enables support for LEDs connected to GPIO lines
+ on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
+
+comment "LED Triggers"
+
+config LEDS_TRIGGERS
+ bool "LED Trigger support"
+ depends NEW_LEDS
+ help
+ This option enables trigger support for the leds class.
+ These triggers allow kernel events to drive the LEDs and can
+ be configured via sysfs. If unsure, say Y.
+
config LEDS_TRIGGER_TIMER
tristate "LED Timer Trigger"
depends LEDS_TRIGGERS
@@ -67,7 +78,7 @@ config LEDS_TRIGGER_TIMER
via sysfs. If unsure, say Y.
config LEDS_TRIGGER_IDE_DISK
- bool "LED Timer Trigger"
+ bool "LED IDE Disk Trigger"
depends LEDS_TRIGGERS && BLK_DEV_IDEDISK
help
This allows LEDs to be controlled by IDE disk activity.
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 40699d3cabbf..40f042633bf5 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o
obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
+obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
new file mode 100644
index 000000000000..650cf72dc675
--- /dev/null
+++ b/drivers/leds/leds-s3c24xx.c
@@ -0,0 +1,163 @@
+/* drivers/leds/leds-s3c24xx.c
+ *
+ * (c) 2006 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - LEDs GPIO driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
+
+/* our context */
+
+struct s3c24xx_gpio_led {
+ struct led_classdev cdev;
+ struct s3c24xx_led_platdata *pdata;
+};
+
+static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
+{
+ return platform_get_drvdata(dev);
+}
+
+static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
+{
+ return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
+}
+
+static void s3c24xx_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
+ struct s3c24xx_led_platdata *pd = led->pdata;
+
+ /* there will be a sort delay between setting the output and
+ * going from output to input when using tristate. */
+
+ s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^
+ (pd->flags & S3C24XX_LEDF_ACTLOW));
+
+ if (pd->flags & S3C24XX_LEDF_TRISTATE)
+ s3c2410_gpio_cfgpin(pd->gpio,
+ value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
+
+}
+
+static int s3c24xx_led_remove(struct platform_device *dev)
+{
+ struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+ led_classdev_unregister(&led->cdev);
+ kfree(led);
+
+ return 0;
+}
+
+static int s3c24xx_led_probe(struct platform_device *dev)
+{
+ struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
+ struct s3c24xx_gpio_led *led;
+ int ret;
+
+ led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL);
+ if (led == NULL) {
+ dev_err(&dev->dev, "No memory for device\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(dev, led);
+
+ led->cdev.brightness_set = s3c24xx_led_set;
+ led->cdev.default_trigger = pdata->def_trigger;
+ led->cdev.name = pdata->name;
+
+ led->pdata = pdata;
+
+ /* no point in having a pull-up if we are always driving */
+
+ if (pdata->flags & S3C24XX_LEDF_TRISTATE) {
+ s3c2410_gpio_setpin(pdata->gpio, 0);
+ s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT);
+ } else {
+ s3c2410_gpio_pullup(pdata->gpio, 0);
+ s3c2410_gpio_setpin(pdata->gpio, 0);
+ s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT);
+ }
+
+ /* register our new led device */
+
+ ret = led_classdev_register(&dev->dev, &led->cdev);
+ if (ret < 0) {
+ dev_err(&dev->dev, "led_classdev_register failed\n");
+ goto exit_err1;
+ }
+
+ return 0;
+
+ exit_err1:
+ kfree(led);
+ return ret;
+}
+
+
+#ifdef CONFIG_PM
+static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+ led_classdev_suspend(&led->cdev);
+ return 0;
+}
+
+static int s3c24xx_led_resume(struct platform_device *dev)
+{
+ struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+ led_classdev_resume(&led->cdev);
+ return 0;
+}
+#else
+#define s3c24xx_led_suspend NULL
+#define s3c24xx_led_resume NULL
+#endif
+
+static struct platform_driver s3c24xx_led_driver = {
+ .probe = s3c24xx_led_probe,
+ .remove = s3c24xx_led_remove,
+ .suspend = s3c24xx_led_suspend,
+ .resume = s3c24xx_led_resume,
+ .driver = {
+ .name = "s3c24xx_led",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c24xx_led_init(void)
+{
+ return platform_driver_register(&s3c24xx_led_driver);
+}
+
+static void __exit s3c24xx_led_exit(void)
+{
+ platform_driver_unregister(&s3c24xx_led_driver);
+}
+
+module_init(s3c24xx_led_init);
+module_exit(s3c24xx_led_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("S3C24XX LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 5ebfd1d138da..5282fec17075 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -627,8 +627,8 @@ thermostat_init(void)
if(therm_type == ADT7460)
device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
-#ifndef CONFIG_I2C_KEYWEST
- request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+ request_module("i2c-powermac");
#endif
return i2c_add_driver(&thermostat_driver);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index fd2aae150ccc..ac25a48362ac 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -139,11 +139,12 @@ config MD_RAID5_RESHAPE
is online. However it is still EXPERIMENTAL code. It should
work, but please be sure that you have backups.
- You will need a version of mdadm newer than 2.3.1. During the
- early stage of reshape there is a critical section where live data
- is being over-written. A crash during this time needs extra care
- for recovery. The newer mdadm takes a copy of the data in the
- critical section and will restore it, if necessary, after a crash.
+ You will need mdadm verion 2.4.1 or later to use this
+ feature safely. During the early stage of reshape there is
+ a critical section where live data is being over-written. A
+ crash during this time needs extra care for recovery. The
+ newer mdadm takes a copy of the data in the critical section
+ and will restore it, if necessary, after a crash.
The mdadm usage is e.g.
mdadm --grow /dev/md1 --raid-disks=6
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index aecd9e0c2616..64fd8e79ea4c 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -78,8 +78,7 @@ void dm_put_target_type(struct target_type *t)
if (--ti->use == 0)
module_put(ti->tt.module);
- if (ti->use < 0)
- BUG();
+ BUG_ON(ti->use < 0);
up_read(&_lock);
return;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1ed5152db450..d7316b829a62 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev)
{
atomic_inc(&md_event_count);
wake_up(&md_event_waiters);
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
}
EXPORT_SYMBOL_GPL(md_new_event);
@@ -278,11 +279,6 @@ static inline int mddev_lock(mddev_t * mddev)
return mutex_lock_interruptible(&mddev->reconfig_mutex);
}
-static inline void mddev_lock_uninterruptible(mddev_t * mddev)
-{
- mutex_lock(&mddev->reconfig_mutex);
-}
-
static inline int mddev_trylock(mddev_t * mddev)
{
return mutex_trylock(&mddev->reconfig_mutex);
@@ -2457,9 +2453,11 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
if (!entry->show)
return -EIO;
- mddev_lock(mddev);
- rv = entry->show(mddev, page);
- mddev_unlock(mddev);
+ rv = mddev_lock(mddev);
+ if (!rv) {
+ rv = entry->show(mddev, page);
+ mddev_unlock(mddev);
+ }
return rv;
}
@@ -2473,9 +2471,11 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
if (!entry->store)
return -EIO;
- mddev_lock(mddev);
- rv = entry->store(mddev, page, length);
- mddev_unlock(mddev);
+ rv = mddev_lock(mddev);
+ if (!rv) {
+ rv = entry->store(mddev, page, length);
+ mddev_unlock(mddev);
+ }
return rv;
}
@@ -4340,8 +4340,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
return 0;
}
- if (mddev_lock(mddev)!=0)
+ if (mddev_lock(mddev) < 0)
return -EINTR;
+
if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
seq_printf(seq, "%s : %sactive", mdname(mddev),
mddev->pers ? "" : "in");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 9b374c91db66..6081941de1b3 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1558,8 +1558,7 @@ static int init_resync(conf_t *conf)
int buffs;
buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
- if (conf->r1buf_pool)
- BUG();
+ BUG_ON(conf->r1buf_pool);
conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free,
conf->poolinfo);
if (!conf->r1buf_pool)
@@ -1732,8 +1731,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
!conf->fullsync &&
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
break;
- if (sync_blocks < (PAGE_SIZE>>9))
- BUG();
+ BUG_ON(sync_blocks < (PAGE_SIZE>>9));
if (len > (sync_blocks<<9))
len = sync_blocks<<9;
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ab90a6d12020..617012bc107a 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1117,8 +1117,7 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
for (i=0; i<conf->copies; i++)
if (r10_bio->devs[i].bio == bio)
break;
- if (i == conf->copies)
- BUG();
+ BUG_ON(i == conf->copies);
update_head_pos(i, r10_bio);
d = r10_bio->devs[i].devnum;
@@ -1518,8 +1517,7 @@ static int init_resync(conf_t *conf)
int buffs;
buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
- if (conf->r10buf_pool)
- BUG();
+ BUG_ON(conf->r10buf_pool);
conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
if (!conf->r10buf_pool)
return -ENOMEM;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index dae740adaf65..31843604049c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -73,10 +73,8 @@ static void print_raid5_conf (raid5_conf_t *conf);
static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
- if (atomic_read(&conf->active_stripes)==0)
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
+ BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
@@ -184,10 +182,8 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int
raid5_conf_t *conf = sh->raid_conf;
int i;
- if (atomic_read(&sh->count) != 0)
- BUG();
- if (test_bit(STRIPE_HANDLE, &sh->state))
- BUG();
+ BUG_ON(atomic_read(&sh->count) != 0);
+ BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
CHECK_DEVLOCK();
PRINTK("init_stripe called, stripe %llu\n",
@@ -269,8 +265,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
init_stripe(sh, sector, pd_idx, disks);
} else {
if (atomic_read(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
} else {
if (!test_bit(STRIPE_HANDLE, &sh->state))
atomic_inc(&conf->active_stripes);
@@ -465,8 +460,7 @@ static int drop_one_stripe(raid5_conf_t *conf)
spin_unlock_irq(&conf->device_lock);
if (!sh)
return 0;
- if (atomic_read(&sh->count))
- BUG();
+ BUG_ON(atomic_read(&sh->count));
shrink_buffers(sh, conf->pool_size);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
@@ -882,8 +876,7 @@ static void compute_parity(struct stripe_head *sh, int method)
ptr[0] = page_address(sh->dev[pd_idx].page);
switch(method) {
case READ_MODIFY_WRITE:
- if (!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags))
- BUG();
+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
for (i=disks ; i-- ;) {
if (i==pd_idx)
continue;
@@ -896,7 +889,7 @@ static void compute_parity(struct stripe_head *sh, int method)
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
- if (sh->dev[i].written) BUG();
+ BUG_ON(sh->dev[i].written);
sh->dev[i].written = chosen;
check_xor();
}
@@ -912,7 +905,7 @@ static void compute_parity(struct stripe_head *sh, int method)
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
- if (sh->dev[i].written) BUG();
+ BUG_ON(sh->dev[i].written);
sh->dev[i].written = chosen;
}
break;
@@ -995,8 +988,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
goto overlap;
- if (*bip && bi->bi_next && (*bip) != bi->bi_next)
- BUG();
+ BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
if (*bip)
bi->bi_next = *bip;
*bip = bi;
@@ -1430,8 +1422,7 @@ static void handle_stripe(struct stripe_head *sh)
set_bit(STRIPE_HANDLE, &sh->state);
if (failed == 0) {
char *pagea;
- if (uptodate != disks)
- BUG();
+ BUG_ON(uptodate != disks);
compute_parity(sh, CHECK_PARITY);
uptodate--;
pagea = page_address(sh->dev[sh->pd_idx].page);
@@ -2096,8 +2087,7 @@ static void raid5d (mddev_t *mddev)
list_del_init(first);
atomic_inc(&sh->count);
- if (atomic_read(&sh->count)!= 1)
- BUG();
+ BUG_ON(atomic_read(&sh->count)!= 1);
spin_unlock_irq(&conf->device_lock);
handled++;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index ab64b37e4996..bc69355e0100 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -91,10 +91,8 @@ static void print_raid6_conf (raid6_conf_t *conf);
static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
- if (atomic_read(&conf->active_stripes)==0)
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
+ BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
@@ -202,10 +200,8 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
raid6_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks, i;
- if (atomic_read(&sh->count) != 0)
- BUG();
- if (test_bit(STRIPE_HANDLE, &sh->state))
- BUG();
+ BUG_ON(atomic_read(&sh->count) != 0);
+ BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
CHECK_DEVLOCK();
PRINTK("init_stripe called, stripe %llu\n",
@@ -284,13 +280,11 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
init_stripe(sh, sector, pd_idx);
} else {
if (atomic_read(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
} else {
if (!test_bit(STRIPE_HANDLE, &sh->state))
atomic_inc(&conf->active_stripes);
- if (list_empty(&sh->lru))
- BUG();
+ BUG_ON(list_empty(&sh->lru));
list_del_init(&sh->lru);
}
}
@@ -353,8 +347,7 @@ static int drop_one_stripe(raid6_conf_t *conf)
spin_unlock_irq(&conf->device_lock);
if (!sh)
return 0;
- if (atomic_read(&sh->count))
- BUG();
+ BUG_ON(atomic_read(&sh->count));
shrink_buffers(sh, conf->raid_disks);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
@@ -780,7 +773,7 @@ static void compute_parity(struct stripe_head *sh, int method)
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
- if (sh->dev[i].written) BUG();
+ BUG_ON(sh->dev[i].written);
sh->dev[i].written = chosen;
}
break;
@@ -970,8 +963,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
goto overlap;
- if (*bip && bi->bi_next && (*bip) != bi->bi_next)
- BUG();
+ BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
if (*bip)
bi->bi_next = *bip;
*bip = bi;
@@ -1906,8 +1898,7 @@ static void raid6d (mddev_t *mddev)
list_del_init(first);
atomic_inc(&sh->count);
- if (atomic_read(&sh->count)!= 1)
- BUG();
+ BUG_ON(atomic_read(&sh->count)!= 1);
spin_unlock_irq(&conf->device_lock);
handled++;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index baa9f58beffc..fffc711c260c 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -51,18 +51,18 @@ config VIDEO_TVEEPROM
tristate
config USB_DABUSB
- tristate "DABUSB driver"
- depends on USB
- ---help---
- A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
- brought to you by the DAB-Team
- <http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
- as an example for URB-based bulk, control, and isochronous
- transactions. URB's are explained in
- <Documentation/usb/URB.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called dabusb.
+ tristate "DABUSB driver"
+ depends on USB
+ ---help---
+ A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+ brought to you by the DAB-Team
+ <http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
+ as an example for URB-based bulk, control, and isochronous
+ transactions. URB's are explained in
+ <Documentation/usb/URB.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dabusb.
endmenu
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 2337b41714e0..376ca48f1d1d 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -7,6 +7,7 @@ config DVB_BT8XX
select DVB_CX24110
select DVB_OR51211
select DVB_LGDT330X
+ select FW_LOADER
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 09e96e9ddbdf..04578df3f249 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -141,12 +141,18 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
}
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
- void *mem = vmalloc(DVR_BUFFER_SIZE);
+ void *mem;
+ if (!dvbdev->readers) {
+ mutex_unlock(&dmxdev->mutex);
+ return -EBUSY;
+ }
+ mem = vmalloc(DVR_BUFFER_SIZE);
if (!mem) {
mutex_unlock(&dmxdev->mutex);
return -ENOMEM;
}
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+ dvbdev->readers--;
}
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
@@ -184,6 +190,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
dmxdev->dvr_orig_fe);
}
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ dvbdev->readers++;
if (dmxdev->dvr_buffer.data) {
void *mem = dmxdev->dvr_buffer.data;
mb();
@@ -1029,8 +1036,7 @@ static struct file_operations dvb_dvr_fops = {
static struct dvb_device dvbdev_dvr = {
.priv = NULL,
- .users = 1,
- .writers = 1,
+ .readers = 1,
.fops = &dvb_dvr_fops
};
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 2c3ea8f95dcd..4f8f257e6795 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -105,6 +105,7 @@ struct dvb_frontend_private {
fe_status_t status;
unsigned long tune_mode_flags;
unsigned int delay;
+ unsigned int reinitialise;
/* swzigzag values */
unsigned int state;
@@ -121,6 +122,7 @@ struct dvb_frontend_private {
unsigned int check_wrapped;
};
+static void dvb_frontend_wakeup(struct dvb_frontend *fe);
static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
{
@@ -213,6 +215,15 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe);
}
+void dvb_frontend_reinitialise(struct dvb_frontend *fe)
+{
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+ fepriv->reinitialise = 1;
+ dvb_frontend_wakeup(fe);
+}
+EXPORT_SYMBOL(dvb_frontend_reinitialise);
+
static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{
int q2;
@@ -505,8 +516,8 @@ static int dvb_frontend_thread(void *data)
fepriv->quality = 0;
fepriv->delay = 3*HZ;
fepriv->status = 0;
- dvb_frontend_init(fe);
fepriv->wakeup = 0;
+ fepriv->reinitialise = 1;
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
@@ -524,6 +535,11 @@ static int dvb_frontend_thread(void *data)
if (down_interruptible(&fepriv->sem))
break;
+ if (fepriv->reinitialise) {
+ dvb_frontend_init(fe);
+ fepriv->reinitialise = 0;
+ }
+
/* do an iteration of the tuning loop */
if (fe->ops->tune) {
/* have we been asked to retune? */
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index d5aee5ad67a0..5926a3b745c9 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -112,6 +112,8 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
+extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
+
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index a14e737ec848..7edd6362b9cc 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -233,6 +233,45 @@ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x4e, KEY_POWER },
};
+static struct dvb_usb_rc_key dvico_portable_rc_keys[] = {
+ { 0xfc, 0x02, KEY_SETUP }, /* Profile */
+ { 0xfc, 0x43, KEY_POWER2 },
+ { 0xfc, 0x06, KEY_EPG },
+ { 0xfc, 0x5a, KEY_BACK },
+ { 0xfc, 0x05, KEY_MENU },
+ { 0xfc, 0x47, KEY_INFO },
+ { 0xfc, 0x01, KEY_TAB },
+ { 0xfc, 0x42, KEY_PREVIOUSSONG },/* Replay */
+ { 0xfc, 0x49, KEY_VOLUMEUP },
+ { 0xfc, 0x09, KEY_VOLUMEDOWN },
+ { 0xfc, 0x54, KEY_CHANNELUP },
+ { 0xfc, 0x0b, KEY_CHANNELDOWN },
+ { 0xfc, 0x16, KEY_CAMERA },
+ { 0xfc, 0x40, KEY_TUNER }, /* ATV/DTV */
+ { 0xfc, 0x45, KEY_OPEN },
+ { 0xfc, 0x19, KEY_1 },
+ { 0xfc, 0x18, KEY_2 },
+ { 0xfc, 0x1b, KEY_3 },
+ { 0xfc, 0x1a, KEY_4 },
+ { 0xfc, 0x58, KEY_5 },
+ { 0xfc, 0x59, KEY_6 },
+ { 0xfc, 0x15, KEY_7 },
+ { 0xfc, 0x14, KEY_8 },
+ { 0xfc, 0x17, KEY_9 },
+ { 0xfc, 0x44, KEY_ANGLE }, /* Aspect */
+ { 0xfc, 0x55, KEY_0 },
+ { 0xfc, 0x07, KEY_ZOOM },
+ { 0xfc, 0x0a, KEY_REWIND },
+ { 0xfc, 0x08, KEY_PLAYPAUSE },
+ { 0xfc, 0x4b, KEY_FASTFORWARD },
+ { 0xfc, 0x5b, KEY_MUTE },
+ { 0xfc, 0x04, KEY_STOP },
+ { 0xfc, 0x56, KEY_RECORD },
+ { 0xfc, 0x57, KEY_POWER },
+ { 0xfc, 0x41, KEY_UNKNOWN }, /* INPUT */
+ { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */
+};
+
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
@@ -511,6 +550,11 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
.i2c_algo = &cxusb_i2c_algo,
+ .rc_interval = 100,
+ .rc_key_map = dvico_portable_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
+ .rc_query = cxusb_rc_query,
+
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
@@ -600,6 +644,11 @@ static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = {
.i2c_algo = &cxusb_i2c_algo,
+ .rc_interval = 100,
+ .rc_key_map = dvico_portable_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
+ .rc_query = cxusb_rc_query,
+
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
@@ -640,6 +689,11 @@ static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = {
.i2c_algo = &cxusb_i2c_algo,
+ .rc_interval = 100,
+ .rc_key_map = dvico_portable_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
+ .rc_query = cxusb_rc_query,
+
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 12ebaf8bddca..70afcfd141ca 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -94,12 +94,14 @@ static int dtt200u_frontend_attach(struct dvb_usb_device *d)
static struct dvb_usb_properties dtt200u_properties;
static struct dvb_usb_properties wt220u_properties;
+static struct dvb_usb_properties wt220u_zl0353_properties;
static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0)
+ dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
return 0;
return -ENODEV;
@@ -110,6 +112,8 @@ static struct usb_device_id dtt200u_usb_table [] = {
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) },
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) },
{ 0 },
};
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -196,6 +200,47 @@ static struct dvb_usb_properties wt220u_properties = {
}
};
+static struct dvb_usb_properties wt220u_zl0353_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+ .pid_filter_count = 15,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-wt220u-zl0353-01.fw",
+
+ .power_ctrl = dtt200u_power_ctrl,
+ .streaming_ctrl = dtt200u_streaming_ctrl,
+ .pid_filter = dtt200u_pid_filter,
+ .frontend_attach = dtt200u_frontend_attach,
+
+ .rc_interval = 300,
+ .rc_key_map = dtt200u_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+ .rc_query = dtt200u_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "WideView WT-220U PenType Receiver (based on ZL353)",
+ .cold_ids = { &dtt200u_usb_table[4], NULL },
+ .warm_ids = { &dtt200u_usb_table[5], NULL },
+ },
+ { NULL },
+ }
+};
+
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver dtt200u_usb_driver = {
.name = "dvb_usb_dtt200u",
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 4a1b9e77e339..cb239049b098 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -83,6 +83,8 @@
#define USB_PID_DTT200U_WARM 0x0301
#define USB_PID_WT220U_COLD 0x0222
#define USB_PID_WT220U_WARM 0x0221
+#define USB_PID_WT220U_ZL0353_COLD 0x022a
+#define USB_PID_WT220U_ZL0353_WARM 0x022b
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_NEBULA_DIGITV 0x0201
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index b6d95e1c9c52..2a89f8c5da99 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -147,8 +147,9 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
cmd[4] = (sr >> 4) & 0xff;
cmd[5] = (sr << 4) & 0xf0;
- deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %Lu (%Lx)\n",
- fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, sr, sr);
+ deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
+ fep->frequency,freq,freq, fep->u.qpsk.symbol_rate,
+ (unsigned long) sr, (unsigned long) sr);
/* if (fep->inversion == INVERSION_ON)
cmd[6] |= 0x80; */
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 94233168d241..37d5e0af1683 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -181,6 +181,11 @@ config DVB_OR51211
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+ download it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_OR51132
tristate "Oren OR51132 based"
depends on DVB_CORE
@@ -189,6 +194,13 @@ config DVB_OR51132
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
+ download firmwares for 8VSB and QAM64/256, respectively. Copy them to
+ /usr/lib/hotplug/firmware or /lib/firmware (depending on
+ configuration of firmware hotplug).
+
config DVB_BCM3510
tristate "Broadcom BCM3510"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 8e8df7b4ca0e..b83dafa4e12c 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -52,7 +52,6 @@ struct tda1004x_state {
struct dvb_frontend frontend;
/* private demod data */
- u8 initialised;
enum tda1004x_demod demod_type;
};
@@ -594,9 +593,6 @@ static int tda10045_init(struct dvb_frontend* fe)
dprintk("%s\n", __FUNCTION__);
- if (state->initialised)
- return 0;
-
if (tda10045_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
return -EIO;
@@ -626,7 +622,6 @@ static int tda10045_init(struct dvb_frontend* fe)
tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
- state->initialised = 1;
return 0;
}
@@ -635,9 +630,6 @@ static int tda10046_init(struct dvb_frontend* fe)
struct tda1004x_state* state = fe->demodulator_priv;
dprintk("%s\n", __FUNCTION__);
- if (state->initialised)
- return 0;
-
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
return -EIO;
@@ -697,7 +689,6 @@ static int tda10046_init(struct dvb_frontend* fe)
// tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
- state->initialised = 1;
return 0;
}
@@ -1207,7 +1198,6 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
break;
}
- state->initialised = 0;
return 0;
}
@@ -1271,7 +1261,6 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
state->demod_type = TDA1004X_DEMOD_TDA10045;
/* check if the demod is there */
@@ -1330,7 +1319,6 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
state->demod_type = TDA1004X_DEMOD_TDA10046;
/* check if the demod is there */
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 840efec32cb6..d028245c8eed 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -87,6 +87,7 @@ static int volume = 255;
static int budgetpatch;
static int wss_cfg_4_3 = 0x4008;
static int wss_cfg_16_9 = 0x0007;
+static int tv_standard;
module_param_named(debug, av7110_debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -109,6 +110,8 @@ module_param(wss_cfg_4_3, int, 0444);
MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
module_param(wss_cfg_16_9, int, 0444);
MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(tv_standard, int, 0444);
+MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
static void restart_feeds(struct av7110 *av7110);
@@ -2123,7 +2126,7 @@ static int frontend_init(struct av7110 *av7110)
read_pwm(av7110));
break;
case 0x0003:
- /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */
+ /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
read_pwm(av7110));
break;
@@ -2543,6 +2546,9 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
av7110->osdwin = 1;
mutex_init(&av7110->osd_mutex);
+ /* TV standard */
+ av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
+
/* ARM "watchdog" */
init_waitqueue_head(&av7110->arm_wait);
av7110->arm_thread = NULL;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 400facec7407..2eff09f638d3 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1479,8 +1479,6 @@ int av7110_av_init(struct av7110 *av7110)
void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
int i, ret;
- av7110->vidmode = VIDEO_MODE_PAL;
-
for (i = 0; i < 2; i++) {
struct ipack *ipack = av7110->ipack + i;
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9dd4745f5312..8efe3ce5f66c 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -60,11 +60,11 @@ struct budget_av {
struct dvb_ca_en50221 ca;
};
-/* GPIO CI Connections:
- * 0 - Vcc/Reset (Reset is controlled by capacitor)
- * 1 - Attribute Memory
- * 2 - Card Enable (Active Low)
- * 3 - Card Detect
+/* GPIO Connections:
+ * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
+ * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
+ * 2 - CI Card Enable (Active Low)
+ * 3 - CI Card Detect
*/
/****************************************************************************
@@ -214,6 +214,9 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
msleep(100);
+ /* reinitialise the frontend */
+ dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+
if (timeout <= 0)
{
printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 633e68c341c8..ea2066d461fc 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -39,9 +39,21 @@
#include "budget.h"
#include "ttpci-eeprom.h"
+#define TS_WIDTH (2 * TS_SIZE)
+#define TS_WIDTH_ACTIVY TS_SIZE
+#define TS_HEIGHT_MASK 0xf00
+#define TS_HEIGHT_MASK_ACTIVY 0xc00
+#define TS_MIN_BUFSIZE_K 188
+#define TS_MAX_BUFSIZE_K 1410
+#define TS_MAX_BUFSIZE_K_ACTIVY 564
+#define BUFFER_WARNING_WAIT (30*HZ)
+
int budget_debug;
+static int dma_buffer_size = TS_MIN_BUFSIZE_K;
module_param_named(debug, budget_debug, int, 0644);
+module_param_named(bufsize, dma_buffer_size, int, 0444);
MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
+MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
/****************************************************************************
* TT budget / WinTV Nova
@@ -70,11 +82,10 @@ static int start_ts_capture(struct budget *budget)
saa7146_write(dev, MC1, MASK_20); // DMA3 off
- memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
+ memset(budget->grabbing, 0x00, budget->buffer_size);
saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
- budget->tsf = 0xff;
budget->ttbp = 0;
/*
@@ -115,16 +126,12 @@ static int start_ts_capture(struct budget *budget)
saa7146_write(dev, BASE_ODD3, 0);
saa7146_write(dev, BASE_EVEN3, 0);
- saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
- if (budget->card->type == BUDGET_FS_ACTIVY) {
- saa7146_write(dev, PITCH3, TS_WIDTH / 2);
- saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT * 2) << 16) | (TS_WIDTH / 2));
- } else {
- saa7146_write(dev, PITCH3, TS_WIDTH);
- saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
- }
+ saa7146_write(dev, PITCH3, budget->buffer_width);
+ saa7146_write(dev, NUM_LINE_BYTE3,
+ (budget->buffer_height << 16) | budget->buffer_width);
saa7146_write(dev, MC2, (MASK_04 | MASK_20));
@@ -141,11 +148,12 @@ static void vpeirq(unsigned long data)
u8 *mem = (u8 *) (budget->grabbing);
u32 olddma = budget->ttbp;
u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+ u32 count;
/* nearest lower position divisible by 188 */
newdma -= newdma % 188;
- if (newdma >= TS_BUFLEN)
+ if (newdma >= budget->buffer_size)
return;
budget->ttbp = newdma;
@@ -154,11 +162,24 @@ static void vpeirq(unsigned long data)
return;
if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
- dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188);
+ count = newdma - olddma;
+ dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
} else { /* wraparound, dump olddma..buflen and 0..newdma */
- dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
+ count = budget->buffer_size - olddma;
+ dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
+ count += newdma;
dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
}
+
+ if (count > budget->buffer_warning_threshold)
+ budget->buffer_warnings++;
+
+ if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
+ printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
+ budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
+ budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
+ budget->buffer_warnings = 0;
+ }
}
@@ -341,9 +362,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner)
{
- int length = TS_WIDTH * TS_HEIGHT;
int ret = 0;
struct budget_info *bi = info->ext_priv;
+ int max_bufsize;
+ int height_mask;
memset(budget, 0, sizeof(struct budget));
@@ -352,6 +374,32 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
budget->card = bi;
budget->dev = (struct saa7146_dev *) dev;
+ if (budget->card->type == BUDGET_FS_ACTIVY) {
+ budget->buffer_width = TS_WIDTH_ACTIVY;
+ max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
+ height_mask = TS_HEIGHT_MASK_ACTIVY;
+ } else {
+ budget->buffer_width = TS_WIDTH;
+ max_bufsize = TS_MAX_BUFSIZE_K;
+ height_mask = TS_HEIGHT_MASK;
+ }
+
+ if (dma_buffer_size < TS_MIN_BUFSIZE_K)
+ dma_buffer_size = TS_MIN_BUFSIZE_K;
+ else if (dma_buffer_size > max_bufsize)
+ dma_buffer_size = max_bufsize;
+
+ budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
+ budget->buffer_height &= height_mask;
+ budget->buffer_size = budget->buffer_height * budget->buffer_width;
+ budget->buffer_warning_threshold = budget->buffer_size * 80/100;
+ budget->buffer_warnings = 0;
+ budget->buffer_warning_time = jiffies;
+
+ dprintk(2, "%s: width = %d, height = %d\n",
+ budget->dev->name, budget->buffer_width, budget->buffer_height);
+ printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
+
dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
/* set dd1 stream a & b */
@@ -392,7 +440,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
if (NULL ==
- (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) {
+ (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) {
ret = -ENOMEM;
goto err;
}
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 9fc9185a8426..1b3aaac5e763 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -577,6 +577,17 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
// Set RPS1 Address register to point to RPS code (r108 p42)
saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+
+ if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
+ return -ENOMEM;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
+ kfree (budget);
+ return err;
+ }
+
// Set Source Line Counter Threshold, using BRS (rCC p43)
// It generates HS event every TS_HEIGHT lines
// this is related to TS_WIDTH set in register
@@ -585,24 +596,13 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
//,then RPS_THRESH1
// should be set to trigger every TS_HEIGHT (512) lines.
//
- saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
+ saa7146_write(dev, RPS_THRESH1, budget->buffer_height | MASK_12 );
// saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
// Enable RPS1 (rFC p33)
saa7146_write(dev, MC1, (MASK_13 | MASK_29));
- if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
- return -ENOMEM;
-
- dprintk(2, "budget: %p\n", budget);
-
- if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
- kfree (budget);
- return err;
- }
-
-
dev->ext_priv = budget;
budget->dvb_adapter.priv = budget;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 4ac0f4d08025..ecea3a13030e 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -58,7 +58,13 @@ struct budget {
int ci_present;
int video_port;
- u8 tsf;
+ u32 buffer_width;
+ u32 buffer_height;
+ u32 buffer_size;
+ u32 buffer_warning_threshold;
+ u32 buffer_warnings;
+ unsigned long buffer_warning_time;
+
u32 ttbp;
int feeding;
@@ -79,11 +85,6 @@ static struct saa7146_pci_extension_data x_var = { \
.ext_priv = &x_var ## _info, \
.ext = &budget_extension };
-#define TS_WIDTH (376)
-#define TS_HEIGHT (512)
-#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
-#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
-
#define BUDGET_TT 0
#define BUDGET_TT_HW_DISEQC 1
#define BUDGET_PATCH 3
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f31a19890b15..85888a8a93c9 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -300,7 +300,7 @@ config VIDEO_OVCAMCHIP
camera drivers.
To compile this driver as a module, choose M here: the
- module will be called ovcamchip
+ module will be called ovcamchip.
config VIDEO_M32R_AR
tristate "AR devices"
@@ -316,6 +316,13 @@ config VIDEO_M32R_AR_M64278
Say Y here to use the Renesas M64278E-800 camera module,
which supports VGA(640x480 pixcels) size of images.
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders and Decoders"
+ depends on VIDEO_DEV
+
config VIDEO_MSP3400
tristate "Micronas MSP34xx audio decoders"
depends on VIDEO_DEV && I2C
@@ -323,7 +330,7 @@ config VIDEO_MSP3400
Support for the Micronas MSP34xx series of audio decoders.
To compile this driver as a module, choose M here: the
- module will be called msp3400
+ module will be called msp3400.
config VIDEO_CS53L32A
tristate "Cirrus Logic CS53L32A audio ADC"
@@ -333,17 +340,27 @@ config VIDEO_CS53L32A
stereo A/D converter.
To compile this driver as a module, choose M here: the
- module will be called cs53l32a
+ module will be called cs53l32a.
config VIDEO_WM8775
- tristate "Wolfson Microelectronics WM8775 audio ADC"
+ tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
depends on VIDEO_DEV && I2C && EXPERIMENTAL
---help---
- Support for the Wolfson Microelectronics WM8775
- high performance stereo A/D Converter.
+ Support for the Wolfson Microelectronics WM8775 high
+ performance stereo A/D Converter with a 4 channel input mixer.
To compile this driver as a module, choose M here: the
- module will be called wm8775
+ module will be called wm8775.
+
+config VIDEO_WM8739
+ tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+ depends on VIDEO_DEV && I2C && EXPERIMENTAL
+ ---help---
+ Support for the Wolfson Microelectronics WM8739
+ stereo A/D Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wm8739.
source "drivers/media/video/cx25840/Kconfig"
@@ -354,7 +371,7 @@ config VIDEO_SAA711X
Support for the Philips SAA7113/4/5 video decoders.
To compile this driver as a module, choose M here: the
- module will be called saa7115
+ module will be called saa7115.
config VIDEO_SAA7127
tristate "Philips SAA7127/9 digital video encoders"
@@ -363,7 +380,32 @@ config VIDEO_SAA7127
Support for the Philips SAA7127/9 digital video encoders.
To compile this driver as a module, choose M here: the
- module will be called saa7127
+ module will be called saa7127.
+
+config VIDEO_UPD64031A
+ tristate "NEC Electronics uPD64031A Ghost Reduction"
+ depends on VIDEO_DEV && I2C && EXPERIMENTAL
+ ---help---
+ Support for the NEC Electronics uPD64031A Ghost Reduction
+ video chip. It is most often found in NTSC TV cards made for
+ Japan and is used to reduce the 'ghosting' effect that can
+ be present in analog TV broadcasts.
+
+ To compile this driver as a module, choose M here: the
+ module will be called upd64031a.
+
+config VIDEO_UPD64083
+ tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+ depends on VIDEO_DEV && I2C && EXPERIMENTAL
+ ---help---
+ Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+ separation video chip. It is used to improve the quality of
+ the colors of a composite signal.
+
+ To compile this driver as a module, choose M here: the
+ module will be called upd64083.
+
+endmenu # encoder / decoder chips
#
# USB Multimedia device configuration
@@ -374,20 +416,6 @@ menu "V4L USB devices"
source "drivers/media/video/em28xx/Kconfig"
-config USB_VICAM
- tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
- depends on USB && VIDEO_DEV && EXPERIMENTAL
- ---help---
- Say Y here if you have 3com homeconnect camera (vicam).
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called vicam.
-
config USB_DSBR
tristate "D-Link USB FM radio support (EXPERIMENTAL)"
depends on USB && VIDEO_DEV && EXPERIMENTAL
@@ -397,79 +425,20 @@ config USB_DSBR
you must connect the line out connector to a sound card or a
set of speakers.
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
To compile this driver as a module, choose M here: the
module will be called dsbr100.
-config USB_ET61X251
- tristate "USB ET61X[12]51 PC Camera Controller support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on Etoms ET61X151
- or ET61X251 PC Camera Controllers.
-
- See <file:Documentation/usb/et61x251.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called et61x251.
+source "drivers/media/video/usbvideo/Kconfig"
-config USB_IBMCAM
- tristate "USB IBM (Xirlink) C-it Camera support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want to connect a IBM "C-It" camera, also known as
- "Xirlink PC Camera" to your computer's USB port. For more
- information, read <file:Documentation/usb/ibmcam.txt>.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called ibmcam.
-
- This camera has several configuration options which
- can be specified when you load the module. Read
- <file:Documentation/usb/ibmcam.txt> to learn more.
-
-config USB_KONICAWC
- tristate "USB Konica Webcam support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for webcams based on a Konica
- chipset. This is known to work with the Intel YC76 webcam.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called konicawc.
+source "drivers/media/video/et61x251/Kconfig"
config USB_OV511
tristate "USB OV511 Camera support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/ov511.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Character Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+ computer's USB port. See <file:Documentation/video4linux/ov511.txt>
+ for more information and for a list of supported cameras.
To compile this driver as a module, choose M here: the
module will be called ov511.
@@ -479,31 +448,13 @@ config USB_SE401
depends on USB && VIDEO_DEV
---help---
Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/se401.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+ computer's USB port. See <file:Documentation/video4linux/se401.txt>
+ for more information and for a list of supported cameras.
To compile this driver as a module, choose M here: the
module will be called se401.
-config USB_SN9C102
- tristate "USB SN9C10x PC Camera Controller support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on SONiX SN9C101,
- SN9C102 or SN9C103 PC Camera Controllers.
-
- See <file:Documentation/usb/sn9c102.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called sn9c102.
+source "drivers/media/video/sn9c102/Kconfig"
config USB_STV680
tristate "USB STV680 (Pencam) Camera support"
@@ -511,20 +462,16 @@ config USB_STV680
---help---
Say Y here if you want to connect this type of camera to your
computer's USB port. This includes the Pencam line of cameras.
- See <file:Documentation/usb/stv680.txt> for more information and for
- a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+ See <file:Documentation/video4linux/stv680.txt> for more information
+ and for a list of supported cameras.
To compile this driver as a module, choose M here: the
module will be called stv680.
config USB_W9968CF
tristate "USB W996[87]CF JPEG Dual Mode Camera support"
- depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP
+ depends on USB && VIDEO_DEV && I2C
+ select VIDEO_OVCAMCHIP
---help---
Say Y here if you want support for cameras based on OV681 or
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
@@ -534,64 +481,14 @@ config USB_W9968CF
resolutions and framerates, but cannot be included in the official
Linux kernel for performance purposes.
- See <file:Documentation/usb/w9968cf.txt> for more informations.
-
- This driver uses the Video For Linux and the I2C APIs. It needs the
- OmniVision Camera Chip support as well. You must say Y or M to
- "Video For Linux", "I2C Support" and "OmniVision Camera Chip
- support" to use this driver.
+ See <file:Documentation/video4linux/w9968cf.txt> for more info.
To compile this driver as a module, choose M here: the
module will be called w9968cf.
-config USB_ZC0301
- tristate "USB ZC0301 Image Processor and Control Chip support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on the ZC0301
- Image Processor and Control Chip.
-
- See <file:Documentation/usb/zc0301.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called zc0301.
-
-config USB_PWC
- tristate "USB Philips Cameras"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y or M here if you want to use one of these Philips & OEM
- webcams:
- * Philips PCA645, PCA646
- * Philips PCVC675, PCVC680, PCVC690
- * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
- * Askey VC010
- * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
- and 'Orbit'/'Sphere'
- * Samsung MPC-C10, MPC-C30
- * Creative Webcam 5, Pro Ex
- * SOTEC Afina Eye
- * Visionite VCS-UC300, VCS-UM100
-
- The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
- and never will be, but the 665 and 720/20 are supported by other
- drivers.
-
- See <file:Documentation/usb/philips.txt> for more information and
- installation instructions.
-
- The built-in microphone is enabled by selecting USB Audio support.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Character Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+source "drivers/media/video/zc0301/Kconfig"
- To compile this driver as a module, choose M here: the
- module will be called pwc.
+source "drivers/media/video/pwc/Kconfig"
endmenu # V4L USB devices
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 1c0e72e5a593..b3ea2d63db9b 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o
@@ -64,9 +65,8 @@ obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
obj-$(CONFIG_VIDEO_CX25840) += cx25840/
obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
-
-et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
-zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
@@ -84,4 +84,4 @@ obj-$(CONFIG_USB_IBMCAM) += usbvideo/
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
index 94350f21cdc0..db641a36b197 100644
--- a/drivers/media/video/bt8xx/Makefile
+++ b/drivers/media/video/bt8xx/Makefile
@@ -9,4 +9,4 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
obj-$(CONFIG_VIDEO_BT848) += bttv.o
EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 74def9c23952..423e954948be 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -973,12 +973,12 @@ audio_mux(struct bttv *btv, int input, int mute)
For now this is sufficient. */
switch (input) {
case TVAUDIO_INPUT_RADIO:
- route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
break;
case TVAUDIO_INPUT_EXTERN:
- route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
break;
case TVAUDIO_INPUT_INTERN:
/* Yes, this is the same input as for RADIO. I doubt
@@ -986,8 +986,8 @@ audio_mux(struct bttv *btv, int input, int mute)
input is the BTTV_BOARD_AVERMEDIA98. I wonder how
that was tested. My guess is that the whole INTERN
input does not work. */
- route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
break;
case TVAUDIO_INPUT_TUNER:
default:
@@ -1023,14 +1023,11 @@ audio_input(struct bttv *btv, int input)
static void
i2c_vidiocschan(struct bttv *btv)
{
- struct video_channel c;
+ v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;
- memset(&c,0,sizeof(c));
- c.norm = btv->tvnorm;
- c.channel = btv->input;
- bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c);
+ bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);
if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
- bttv_tda9880_setnorm(btv,c.norm);
+ bttv_tda9880_setnorm(btv,btv->tvnorm);
}
static int
@@ -1184,11 +1181,27 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
break;
if (i == BTTV_CTLS)
return -EINVAL;
- if (i >= 4 && i <= 8) {
+ if (btv->audio_hook && i >= 4 && i <= 8) {
memset(&va,0,sizeof(va));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
+ switch (c->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+ c->value = va.volume;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ c->value = va.balance;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ c->value = va.bass;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ c->value = va.treble;
+ break;
+ }
+ return 0;
}
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
@@ -1205,19 +1218,11 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
break;
case V4L2_CID_AUDIO_MUTE:
- c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
- break;
case V4L2_CID_AUDIO_VOLUME:
- c->value = va.volume;
- break;
case V4L2_CID_AUDIO_BALANCE:
- c->value = va.balance;
- break;
case V4L2_CID_AUDIO_BASS:
- c->value = va.bass;
- break;
case V4L2_CID_AUDIO_TREBLE:
- c->value = va.treble;
+ bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1269,11 +1274,35 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
break;
if (i == BTTV_CTLS)
return -EINVAL;
- if (i >= 4 && i <= 8) {
+ if (btv->audio_hook && i >= 4 && i <= 8) {
memset(&va,0,sizeof(va));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
+ switch (c->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (c->value) {
+ va.flags |= VIDEO_AUDIO_MUTE;
+ audio_mute(btv, 1);
+ } else {
+ va.flags &= ~VIDEO_AUDIO_MUTE;
+ audio_mute(btv, 0);
+ }
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ va.volume = c->value;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ va.balance = c->value;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ va.bass = c->value;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ va.treble = c->value;
+ break;
+ }
+ btv->audio_hook(btv,&va,1);
+ return 0;
}
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
@@ -1289,26 +1318,13 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
bt848_sat(btv,c->value);
break;
case V4L2_CID_AUDIO_MUTE:
- if (c->value) {
- va.flags |= VIDEO_AUDIO_MUTE;
- audio_mute(btv, 1);
- } else {
- va.flags &= ~VIDEO_AUDIO_MUTE;
- audio_mute(btv, 0);
- }
- break;
-
+ audio_mute(btv, c->value);
+ /* fall through */
case V4L2_CID_AUDIO_VOLUME:
- va.volume = c->value;
- break;
case V4L2_CID_AUDIO_BALANCE:
- va.balance = c->value;
- break;
case V4L2_CID_AUDIO_BASS:
- va.bass = c->value;
- break;
case V4L2_CID_AUDIO_TREBLE:
- va.treble = c->value;
+ bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1364,11 +1380,6 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
default:
return -EINVAL;
}
- if (i >= 4 && i <= 8) {
- bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,1);
- }
return 0;
}
@@ -1591,12 +1602,16 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
case VIDIOCSFREQ:
{
- unsigned long *freq = arg;
+ struct v4l2_frequency freq;
+
+ memset(&freq, 0, sizeof(freq));
+ freq.frequency = *(unsigned long *)arg;
mutex_lock(&btv->lock);
- btv->freq=*freq;
- bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
+ freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ btv->freq = *(unsigned long *)arg;
+ bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq);
if (btv->has_matchbox && btv->radio_user)
- tea5757_set_freq(btv,*freq);
+ tea5757_set_freq(btv,*(unsigned long *)arg);
mutex_unlock(&btv->lock);
return 0;
}
@@ -1827,33 +1842,26 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
mutex_lock(&btv->lock);
memset(t,0,sizeof(*t));
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
strcpy(t->name, "Television");
- t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM;
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ t->type = V4L2_TUNER_ANALOG_TV;
if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
t->signal = 0xffff;
- {
- struct video_tuner tuner;
-
- memset(&tuner, 0, sizeof (tuner));
- tuner.rangehigh = 0xffffffffUL;
- bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner);
- t->rangelow = tuner.rangelow;
- t->rangehigh = tuner.rangehigh;
- }
- {
+
+ if (btv->audio_hook) {
/* Hmmm ... */
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
+ t->audmode = V4L2_TUNER_MODE_MONO;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
if(va.mode & VIDEO_SOUND_STEREO) {
- t->audmode = V4L2_TUNER_MODE_STEREO;
- t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans = V4L2_TUNER_SUB_STEREO;
}
- if(va.mode & VIDEO_SOUND_LANG1) {
+ if(va.mode & VIDEO_SOUND_LANG2) {
t->audmode = V4L2_TUNER_MODE_LANG1;
t->rxsubchans = V4L2_TUNER_SUB_LANG1
| V4L2_TUNER_SUB_LANG2;
@@ -1872,10 +1880,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (0 != t->index)
return -EINVAL;
mutex_lock(&btv->lock);
- {
+ bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+ if (btv->audio_hook) {
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
if (t->audmode == V4L2_TUNER_MODE_MONO)
va.mode = VIDEO_SOUND_MONO;
else if (t->audmode == V4L2_TUNER_MODE_STEREO ||
@@ -1885,9 +1893,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
va.mode = VIDEO_SOUND_LANG1;
else if (t->audmode == V4L2_TUNER_MODE_LANG2)
va.mode = VIDEO_SOUND_LANG2;
- bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,1);
+ btv->audio_hook(btv,&va,1);
}
mutex_unlock(&btv->lock);
return 0;
@@ -1912,7 +1918,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
mutex_lock(&btv->lock);
btv->freq = f->frequency;
- bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
+ bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,btv->freq);
mutex_unlock(&btv->lock);
@@ -1920,7 +1926,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
case VIDIOC_LOG_STATUS:
{
+ printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr);
bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
+ printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr);
return 0;
}
@@ -2870,12 +2878,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
*c = bttv_ctls[i];
- if (i >= 4 && i <= 8) {
+ if (btv->audio_hook && i >= 4 && i <= 8) {
struct video_audio va;
memset(&va,0,sizeof(va));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
switch (bttv_ctls[i].id) {
case V4L2_CID_AUDIO_VOLUME:
if (!(va.flags & VIDEO_AUDIO_VOLUME))
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index e20ff238e409..8c9f0f7cf467 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -184,7 +184,7 @@ void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
- tvnorm->vbistart[0];
count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
- tvnorm->vbistart[1];
- count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
+ count = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES);
f->fmt.vbi.start[0] = tvnorm->vbistart[0];
f->fmt.vbi.start[1] = tvnorm->vbistart[1];
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 2227c5640c12..85d84e89d8f4 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -64,14 +64,13 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("video");
#endif
-static unsigned short colorspace_conv = 0;
+static unsigned short colorspace_conv;
module_param(colorspace_conv, ushort, 0444);
MODULE_PARM_DESC(colorspace_conv,
- "\n<n> Colorspace conversion:"
- "\n0 = disable"
- "\n1 = enable"
- "\nDefault value is 0"
- "\n");
+ " Colorspace conversion:"
+ "\n 0 = disable, 1 = enable"
+ "\n Default value is 0"
+ );
#define ABOUT "V4L-Driver for Vision CPiA based cameras"
@@ -4042,7 +4041,7 @@ static int __init cpia_init(void)
"allowed, it is disabled by default now. Users should fix the "
"applications in case they don't work without conversion "
"reenabled by setting the 'colorspace_conv' module "
- "parameter to 1");
+ "parameter to 1\n");
#ifdef CONFIG_PROC_FS
proc_cpia_create();
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
index 8394283993f6..1764991b0ac9 100644
--- a/drivers/media/video/cpia2/cpia2.h
+++ b/drivers/media/video/cpia2/cpia2.h
@@ -456,7 +456,7 @@ int cpia2_init_camera(struct camera_data *cam);
int cpia2_allocate_buffers(struct camera_data *cam);
void cpia2_free_buffers(struct camera_data *cam);
long cpia2_read(struct camera_data *cam,
- char *buf, unsigned long count, int noblock);
+ char __user *buf, unsigned long count, int noblock);
unsigned int cpia2_poll(struct camera_data *cam,
struct file *filp, poll_table *wait);
int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma);
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile
index 32a896c23d1e..6e8665be8954 100644
--- a/drivers/media/video/cx25840/Makefile
+++ b/drivers/media/video/cx25840/Makefile
@@ -3,4 +3,4 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
-EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index a4540e858f21..9a4b813152e5 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -19,8 +19,9 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
static int set_audclk_freq(struct i2c_client *client, u32 freq)
{
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index a65b3cc4bf03..a961bb2ab0fd 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -32,8 +32,9 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
@@ -668,6 +669,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
{
struct cx25840_state *state = i2c_get_clientdata(client);
struct v4l2_tuner *vt = arg;
+ struct v4l2_routing *route = arg;
switch (cmd) {
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -749,19 +751,21 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
state->radio = 1;
break;
- case VIDIOC_G_INPUT:
- *(int *)arg = state->vid_input;
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = state->vid_input;
+ route->output = 0;
break;
- case VIDIOC_S_INPUT:
- return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ return set_input(client, route->input, state->aud_input);
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *input = arg;
+ case VIDIOC_INT_G_AUDIO_ROUTING:
+ route->input = state->aud_input;
+ route->output = 0;
+ break;
- return set_input(client, state->vid_input, input->index);
- }
+ case VIDIOC_INT_S_AUDIO_ROUTING:
+ return set_input(client, state->vid_input, route->input);
case VIDIOC_S_FREQUENCY:
input_change(client);
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840-core.h
index dd70664d1dd9..1736929fc204 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -1,4 +1,4 @@
-/* cx25840 API header
+/* cx25840 internal API header
*
* Copyright (C) 2003-2004 Chris Kennedy
*
@@ -17,8 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef _CX25840_H_
-#define _CX25840_H_
+#ifndef _CX25840_CORE_H_
+#define _CX25840_CORE_H_
#include <linux/videodev2.h>
@@ -32,46 +32,6 @@
providing this information. */
#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
-enum cx25840_video_input {
- /* Composite video inputs In1-In8 */
- CX25840_COMPOSITE1 = 1,
- CX25840_COMPOSITE2,
- CX25840_COMPOSITE3,
- CX25840_COMPOSITE4,
- CX25840_COMPOSITE5,
- CX25840_COMPOSITE6,
- CX25840_COMPOSITE7,
- CX25840_COMPOSITE8,
-
- /* S-Video inputs consist of one luma input (In1-In4) ORed with one
- chroma input (In5-In8) */
- CX25840_SVIDEO_LUMA1 = 0x10,
- CX25840_SVIDEO_LUMA2 = 0x20,
- CX25840_SVIDEO_LUMA3 = 0x30,
- CX25840_SVIDEO_LUMA4 = 0x40,
- CX25840_SVIDEO_CHROMA4 = 0x400,
- CX25840_SVIDEO_CHROMA5 = 0x500,
- CX25840_SVIDEO_CHROMA6 = 0x600,
- CX25840_SVIDEO_CHROMA7 = 0x700,
- CX25840_SVIDEO_CHROMA8 = 0x800,
-
- /* S-Video aliases for common luma/chroma combinations */
- CX25840_SVIDEO1 = 0x510,
- CX25840_SVIDEO2 = 0x620,
- CX25840_SVIDEO3 = 0x730,
- CX25840_SVIDEO4 = 0x840,
-};
-
-enum cx25840_audio_input {
- /* Audio inputs: serial or In4-In8 */
- CX25840_AUDIO_SERIAL,
- CX25840_AUDIO4 = 4,
- CX25840_AUDIO5,
- CX25840_AUDIO6,
- CX25840_AUDIO7,
- CX25840_AUDIO8,
-};
-
struct cx25840_state {
int pvr150_workaround;
int radio;
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
index e1a7823d82cd..f59ced181c55 100644
--- a/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/drivers/media/video/cx25840/cx25840-firmware.c
@@ -20,11 +20,22 @@
#include <linux/i2c-algo-bit.h>
#include <linux/firmware.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
#define FWFILE "v4l-cx25840.fw"
-#define FWSEND 1024
+
+/*
+ * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the
+ * size of the firmware chunks sent down the I2C bus to the chip.
+ * Previously this had been set to 1024 but unfortunately some I2C
+ * implementations can't transfer data in such big gulps.
+ * Specifically, the pvrusb2 driver has a hard limit of around 60
+ * bytes, due to the encapsulation there of I2C traffic into USB
+ * messages. So we have to significantly reduce this parameter.
+ */
+#define FWSEND 48
#define FWDEV(x) &((x)->adapter->dev)
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index e96fd1f1d6dc..57feca288d2b 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -19,8 +19,9 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
static int odd_parity(u8 c)
{
@@ -151,7 +152,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
case VIDIOC_G_FMT:
{
static u16 lcr2vbi[] = {
- 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */
+ 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
0, V4L2_SLICED_WSS_625, 0, /* 4 */
V4L2_SLICED_CAPTION_525, /* 6 */
0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
@@ -231,7 +232,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
for (i = 7; i <= 23; i++) {
for (x = 0; x <= 1; x++) {
switch (svbi->service_lines[1-x][i]) {
- case V4L2_SLICED_TELETEXT_PAL_B:
+ case V4L2_SLICED_TELETEXT_B:
lcr[i] |= 1 << (4 * x);
break;
case V4L2_SLICED_WSS_625:
@@ -282,7 +283,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
switch (id2) {
case 1:
- id2 = V4L2_SLICED_TELETEXT_PAL_B;
+ id2 = V4L2_SLICED_TELETEXT_B;
break;
case 4:
id2 = V4L2_SLICED_WSS_625;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index ff0f72340d69..630273992a41 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -1,3 +1,7 @@
+config VIDEO_CX88_VP3054
+ tristate
+ depends on VIDEO_CX88_DVB && DVB_MT352
+
config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
depends on VIDEO_DEV && PCI && I2C
@@ -25,7 +29,7 @@ config VIDEO_CX88_ALSA
It only works with boards with function 01 enabled.
To check if your board supports, use lspci -n.
- If supported, you should see 1471:8801 or 1471:8811
+ If supported, you should see 14f1:8801 or 14f1:8811
PCI device.
To compile this driver as a module, choose M here: the
@@ -73,10 +77,11 @@ config VIDEO_CX88_DVB_MT352
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator.
-config VIDEO_CX88_VP3054
- tristate "VP-3054 Secondary I2C Bus Support"
- default m
- depends on DVB_MT352
+config VIDEO_CX88_DVB_VP3054
+ bool "VP-3054 Secondary I2C Bus Support"
+ default y
+ depends on VIDEO_CX88_DVB_MT352
+ select VIDEO_CX88_VP3054
---help---
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator,
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 6482b9aa6a1f..0dcd09b9b727 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -8,9 +8,9 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
extra-cflags-$(CONFIG_DVB_CX22702) += -DHAVE_CX22702=1
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
index da457a05b0dd..826d0e340753 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
@@ -3,4 +3,4 @@ em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \
obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
-EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index f62fd706b45a..3ba3439db580 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -151,8 +151,8 @@ struct em28xx_board em28xx_boards[] = {
},{
.type = EM28XX_VMUX_SVIDEO,
.vmux = 2,
- .amux = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
+ .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
}},
},
[EM2820_BOARD_MSI_VOX_USB_2] = {
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index dfba33d0fa61..ddc92cbb5276 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -222,7 +222,7 @@ static void video_mux(struct em28xx *dev, int index)
if (dev->i2s_speed)
em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
route.input = dev->ctl_ainput;
- route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
+ route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
ainput = EM28XX_AUDIO_SRC_TUNER;
@@ -1141,26 +1141,16 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *t = arg;
- int status = 0;
if (0 != t->index)
return -EINVAL;
memset(t, 0, sizeof(*t));
strcpy(t->name, "Tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */
-/* t->signal = 0xffff;*/
-/* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/
- /* No way to get signal strength? */
mutex_lock(&dev->lock);
- em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,
- &status);
+ /* let clients fill in the remainder of this struct */
+ em28xx_i2c_call_clients(dev, cmd, t);
mutex_unlock(&dev->lock);
- t->signal =
- (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;
-
em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal,
t->afc);
return 0;
@@ -1168,26 +1158,13 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *t = arg;
- int status = 0;
if (0 != t->index)
return -EINVAL;
- memset(t, 0, sizeof(*t));
- strcpy(t->name, "Tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */
-/* t->signal = 0xffff; */
- /* No way to get signal strength? */
mutex_lock(&dev->lock);
- em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,
- &status);
+ /* let clients handle this */
+ em28xx_i2c_call_clients(dev, cmd, t);
mutex_unlock(&dev->lock);
- t->signal =
- (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;
-
- em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n",
- t->signal, t->afc);
return 0;
}
case VIDIOC_G_FREQUENCY:
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig
new file mode 100644
index 000000000000..6c43a90c6569
--- /dev/null
+++ b/drivers/media/video/et61x251/Kconfig
@@ -0,0 +1,14 @@
+config USB_ET61X251
+ tristate "USB ET61X[12]51 PC Camera Controller support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on Etoms ET61X151
+ or ET61X251 PC Camera Controllers.
+
+ See <file:Documentation/video4linux/et61x251.txt> for more info.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called et61x251.
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 95bacf435414..7e66d83fe0ce 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -411,6 +411,9 @@ static int ir_probe(struct i2c_adapter *adap)
case I2C_HW_B_BT848:
probe = probe_bttv;
break;
+ case I2C_HW_B_CX2341X:
+ probe = probe_bttv;
+ break;
case I2C_HW_SAA7134:
probe = probe_saa7134;
break;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index c40e8ba9a2ea..b806999d6e0f 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -279,20 +279,8 @@ void msp_set_scart(struct i2c_client *client, int in, int out)
msp_write_dsp(client, 0x13, state->acb);
/* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
- msp_write_dem(client, 0x40, state->i2s_mode);
-}
-
-void msp_set_mute(struct i2c_client *client)
-{
- struct msp_state *state = i2c_get_clientdata(client);
-
- v4l_dbg(1, msp_debug, client, "mute audio\n");
- msp_write_dsp(client, 0x0000, 0);
- msp_write_dsp(client, 0x0007, 1);
- if (state->has_scart2_out_volume)
- msp_write_dsp(client, 0x0040, 1);
- if (state->has_headphones)
- msp_write_dsp(client, 0x0006, 0);
+ if (state->has_i2s_conf)
+ msp_write_dem(client, 0x40, state->i2s_mode);
}
void msp_set_audio(struct i2c_client *client)
@@ -300,17 +288,19 @@ void msp_set_audio(struct i2c_client *client)
struct msp_state *state = i2c_get_clientdata(client);
int bal = 0, bass, treble, loudness;
int val = 0;
+ int reallymuted = state->muted | state->scan_in_progress;
- if (!state->muted)
+ if (!reallymuted)
val = (state->volume * 0x7f / 65535) << 8;
- v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n",
- state->muted ? "on" : "off", state->volume);
+ v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
+ state->muted ? "on" : "off", state->scan_in_progress ? "yes" : "no",
+ state->volume);
msp_write_dsp(client, 0x0000, val);
- msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
+ msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
if (state->has_scart2_out_volume)
- msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
+ msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
if (state->has_headphones)
msp_write_dsp(client, 0x0006, val);
if (!state->has_sound_processing)
@@ -346,7 +336,6 @@ static void msp_wake_thread(struct i2c_client *client)
if (NULL == state->kthread)
return;
- msp_set_mute(client);
state->watch_stereo = 0;
state->restart = 1;
wake_up_interruptible(&state->wq);
@@ -374,19 +363,15 @@ int msp_sleep(struct msp_state *state, int timeout)
/* ------------------------------------------------------------------------ */
-static int msp_mode_v4l2_to_v4l1(int rxsubchans)
+static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
{
- int mode = 0;
-
- if (rxsubchans & V4L2_TUNER_SUB_STEREO)
- mode |= VIDEO_SOUND_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG2)
- mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG1)
- mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO;
- if (mode == 0)
- mode |= VIDEO_SOUND_MONO;
- return mode;
+ if (rxsubchans == V4L2_TUNER_SUB_MONO)
+ return VIDEO_SOUND_MONO;
+ if (rxsubchans == V4L2_TUNER_SUB_STEREO)
+ return VIDEO_SOUND_STEREO;
+ if (audmode == V4L2_TUNER_MODE_LANG2)
+ return VIDEO_SOUND_LANG2;
+ return VIDEO_SOUND_LANG1;
}
static int msp_mode_v4l1_to_v4l2(int mode)
@@ -605,7 +590,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
if (state->opmode == OPMODE_AUTOSELECT)
msp_detect_stereo(client);
- va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
+ va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode);
break;
}
@@ -620,7 +605,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
state->treble = va->treble;
msp_set_audio(client);
- if (va->mode != 0 && state->radio == 0) {
+ if (va->mode != 0 && state->radio == 0 &&
+ state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) {
state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
msp_set_audmode(client);
}
@@ -687,21 +673,23 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
int sc_in = rt->input & 0x7;
int sc1_out = rt->output & 0xf;
int sc2_out = (rt->output >> 4) & 0xf;
- u16 val;
+ u16 val, reg;
+ if (state->routing.input == rt->input &&
+ state->routing.output == rt->output)
+ break;
state->routing = *rt;
- if (state->opmode == OPMODE_AUTOSELECT) {
- val = msp_read_dem(client, 0x30) & ~0x100;
- msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
- } else {
- val = msp_read_dem(client, 0xbb) & ~0x100;
- msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
- }
msp_set_scart(client, sc_in, 0);
msp_set_scart(client, sc1_out, 1);
msp_set_scart(client, sc2_out, 2);
msp_set_audmode(client);
- msp_wake_thread(client);
+ reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
+ val = msp_read_dem(client, reg);
+ if (tuner != ((val >> 8) & 1)) {
+ msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
+ /* wake thread when a new tuner input is chosen */
+ msp_wake_thread(client);
+ }
break;
}
@@ -715,7 +703,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp_detect_stereo(client);
vt->audmode = state->audmode;
vt->rxsubchans = state->rxsubchans;
- vt->capability = V4L2_TUNER_CAP_STEREO |
+ vt->capability |= V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
break;
}
@@ -726,6 +714,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio) /* TODO: add mono/stereo support for radio */
break;
+ if (state->audmode == vt->audmode)
+ break;
state->audmode = vt->audmode;
/* only set audmode */
msp_set_audmode(client);
@@ -887,7 +877,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
memset(state, 0, sizeof(*state));
state->v4l2_std = V4L2_STD_NTSC;
- state->audmode = V4L2_TUNER_MODE_LANG1;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
state->volume = 58880; /* 0db gain */
state->balance = 32768; /* 0db gain */
state->bass = 32768;
@@ -931,13 +921,16 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
state->has_radio = msp_revision >= 'G';
/* Has headphones output: not for stripped down products */
state->has_headphones = msp_prod_lo < 5;
+ /* Has scart2 input: not in stripped down products of the '3' family */
+ state->has_scart2 = msp_family >= 4 || msp_prod_lo < 7;
+ /* Has scart3 input: not in stripped down products of the '3' family */
+ state->has_scart3 = msp_family >= 4 || msp_prod_lo < 5;
/* Has scart4 input: not in pre D revisions, not in stripped D revs */
state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
- /* Has scart2 and scart3 inputs and scart2 output: not in stripped
- down products of the '3' family */
- state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
+ /* Has scart2 output: not in stripped down products of the '3' family */
+ state->has_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
/* Has scart2 a volume control? Not in pre-D revisions. */
- state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
+ state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart2_out;
/* Has a configurable i2s out? */
state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7;
/* Has subwoofer output: not in pre-D revs and not in stripped down products */
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index 1940748bb633..4e451049013d 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -54,8 +54,10 @@ struct msp_state {
u8 has_radio;
u8 has_headphones;
u8 has_ntsc_jp_d_k3;
+ u8 has_scart2;
+ u8 has_scart3;
u8 has_scart4;
- u8 has_scart23_in_scart2_out;
+ u8 has_scart2_out;
u8 has_scart2_out_volume;
u8 has_i2s_conf;
u8 has_subwoofer;
@@ -83,6 +85,7 @@ struct msp_state {
int volume, muted;
int balance, loudness;
int bass, treble;
+ int scan_in_progress;
/* thread */
struct task_struct *kthread;
@@ -98,7 +101,6 @@ int msp_read_dem(struct i2c_client *client, int addr);
int msp_read_dsp(struct i2c_client *client, int addr);
int msp_reset(struct i2c_client *client);
void msp_set_scart(struct i2c_client *client, int in, int out);
-void msp_set_mute(struct i2c_client *client);
void msp_set_audio(struct i2c_client *client);
int msp_sleep(struct msp_state *state, int timeout);
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index c3984ea9ca07..633a10213789 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -170,7 +170,7 @@ static void msp_set_source(struct i2c_client *client, u16 src)
msp_write_dsp(client, 0x000a, src);
msp_write_dsp(client, 0x000b, src);
msp_write_dsp(client, 0x000c, src);
- if (state->has_scart23_in_scart2_out)
+ if (state->has_scart2_out)
msp_write_dsp(client, 0x0041, src);
}
@@ -228,6 +228,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
strmode[state->audmode] : "unknown";
int src = 0; /* channel source: FM/AM, nicam or SCART */
+ int audmode = state->audmode;
if (state->opmode == OPMODE_AUTOSELECT) {
/* this method would break everything, let's make sure
@@ -239,11 +240,29 @@ static void msp3400c_set_audmode(struct i2c_client *client)
return;
}
+ /* Note: for the C and D revs no NTSC stereo + SAP is possible as
+ the hardware does not support SAP. So the rxsubchans combination
+ of STEREO | LANG2 does not occur. */
+
+ /* switch to mono if only mono is available */
+ if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
+ audmode = V4L2_TUNER_MODE_MONO;
+ /* if bilingual */
+ else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
+ /* and mono or stereo, then fallback to lang1 */
+ if (audmode == V4L2_TUNER_MODE_MONO ||
+ audmode == V4L2_TUNER_MODE_STEREO)
+ audmode = V4L2_TUNER_MODE_LANG1;
+ }
+ /* if stereo, and audmode is not mono, then switch to stereo */
+ else if (audmode != V4L2_TUNER_MODE_MONO)
+ audmode = V4L2_TUNER_MODE_STEREO;
+
/* switch demodulator */
switch (state->mode) {
case MSP_MODE_FM_TERRA:
v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr);
- switch (state->audmode) {
+ switch (audmode) {
case V4L2_TUNER_MODE_STEREO:
msp_write_dsp(client, 0x000e, 0x3001);
break;
@@ -257,7 +276,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
break;
case MSP_MODE_FM_SAT:
v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr);
- switch (state->audmode) {
+ switch (audmode) {
case V4L2_TUNER_MODE_MONO:
msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
break;
@@ -296,7 +315,8 @@ static void msp3400c_set_audmode(struct i2c_client *client)
}
/* switch audio */
- switch (state->audmode) {
+ v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode);
+ switch (audmode) {
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
src |= 0x0020;
@@ -314,10 +334,6 @@ static void msp3400c_set_audmode(struct i2c_client *client)
src = 0x0030;
break;
case V4L2_TUNER_MODE_LANG1:
- /* switch to stereo for stereo transmission, otherwise
- keep first language */
- if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
- src |= 0x0020;
break;
case V4L2_TUNER_MODE_LANG2:
src |= 0x0010;
@@ -367,7 +383,7 @@ static int msp3400c_detect_stereo(struct i2c_client *client)
if (val > 32767)
val -= 65536;
v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
- if (val > 4096) {
+ if (val > 8192) {
rxsubchans = V4L2_TUNER_SUB_STEREO;
} else if (val < -4096) {
rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
@@ -464,19 +480,22 @@ int msp3400c_thread(void *data)
if (state->radio || MSP_MODE_EXTERN == state->mode) {
/* no carrier scan, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ state->scan_in_progress = 0;
msp_set_audio(client);
continue;
}
- /* mute */
- msp_set_mute(client);
+ /* mute audio */
+ state->scan_in_progress = 1;
+ msp_set_audio(client);
+
msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
val1 = val2 = 0;
max1 = max2 = -1;
state->watch_stereo = 0;
state->nicam_on = 0;
- /* some time for the tuner to sync */
+ /* wait for tuner to settle down after a channel change */
if (msp_sleep(state, 200))
goto restart;
@@ -552,7 +571,6 @@ int msp3400c_thread(void *data)
/* B/G NICAM */
state->second = msp3400c_carrier_detect_55[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
- msp3400c_set_carrier(client, state->second, state->main);
state->nicam_on = 1;
state->watch_stereo = 1;
} else {
@@ -563,7 +581,6 @@ int msp3400c_thread(void *data)
/* PAL I NICAM */
state->second = MSP_CARRIER(6.552);
msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
- msp3400c_set_carrier(client, state->second, state->main);
state->nicam_on = 1;
state->watch_stereo = 1;
break;
@@ -577,13 +594,11 @@ int msp3400c_thread(void *data)
/* L NICAM or AM-mono */
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
- msp3400c_set_carrier(client, state->second, state->main);
state->watch_stereo = 1;
} else if (max2 == 0 && state->has_nicam) {
/* D/K NICAM */
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
- msp3400c_set_carrier(client, state->second, state->main);
state->nicam_on = 1;
state->watch_stereo = 1;
} else {
@@ -595,25 +610,25 @@ int msp3400c_thread(void *data)
no_second:
state->second = msp3400c_carrier_detect_main[max1].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
- msp3400c_set_carrier(client, state->second, state->main);
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
}
+ msp3400c_set_carrier(client, state->second, state->main);
/* unmute */
- msp_set_audio(client);
+ state->scan_in_progress = 0;
msp3400c_set_audmode(client);
+ msp_set_audio(client);
if (msp_debug)
msp3400c_print_mode(client);
/* monitor tv audio mode, the first time don't wait
so long to get a quick stereo/bilingual result */
- if (msp_sleep(state, 1000))
- goto restart;
+ count = 3;
while (state->watch_stereo) {
- if (msp_sleep(state, 5000))
+ if (msp_sleep(state, count ? 1000 : 5000))
goto restart;
+ if (count) count--;
watch_stereo(client);
}
}
@@ -626,7 +641,7 @@ int msp3410d_thread(void *data)
{
struct i2c_client *client = data;
struct msp_state *state = i2c_get_clientdata(client);
- int val, i, std;
+ int val, i, std, count;
v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
@@ -644,16 +659,14 @@ int msp3410d_thread(void *data)
if (state->mode == MSP_MODE_EXTERN) {
/* no carrier scan needed, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ state->scan_in_progress = 0;
msp_set_audio(client);
continue;
}
- /* put into sane state (and mute) */
- msp_reset(client);
-
- /* some time for the tuner to sync */
- if (msp_sleep(state,200))
- goto restart;
+ /* mute audio */
+ state->scan_in_progress = 1;
+ msp_set_audio(client);
/* start autodetect. Note: autodetect is not supported for
NTSC-M and radio, hence we force the standard in those cases. */
@@ -664,6 +677,10 @@ int msp3410d_thread(void *data)
state->watch_stereo = 0;
state->nicam_on = 0;
+ /* wait for tuner to settle down after a channel change */
+ if (msp_sleep(state, 200))
+ goto restart;
+
if (msp_debug)
v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n",
msp_standard_std_name(std), std);
@@ -693,6 +710,7 @@ int msp3410d_thread(void *data)
state->main = msp_stdlist[i].main;
state->second = msp_stdlist[i].second;
state->std = val;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
(val != 0x0009)) {
@@ -714,20 +732,17 @@ int msp3410d_thread(void *data)
else
state->mode = MSP_MODE_FM_NICAM1;
/* just turn on stereo */
- state->rxsubchans = V4L2_TUNER_SUB_STEREO;
state->nicam_on = 1;
state->watch_stereo = 1;
break;
case 0x0009:
state->mode = MSP_MODE_AM_NICAM;
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
state->nicam_on = 1;
state->watch_stereo = 1;
break;
case 0x0020: /* BTSC */
/* The pre-'G' models only have BTSC-mono */
state->mode = MSP_MODE_BTSC;
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
case 0x0040: /* FM radio */
state->mode = MSP_MODE_FM_RADIO;
@@ -737,15 +752,12 @@ int msp3410d_thread(void *data)
msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
msp3400c_set_carrier(client, MSP_CARRIER(10.7),
MSP_CARRIER(10.7));
- /* scart routing (this doesn't belong here I think) */
- msp_set_scart(client,SCART_IN2,0);
break;
case 0x0002:
case 0x0003:
case 0x0004:
case 0x0005:
state->mode = MSP_MODE_FM_TERRA;
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
state->watch_stereo = 1;
break;
}
@@ -759,20 +771,19 @@ int msp3410d_thread(void *data)
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
- /* unmute, restore misc registers */
- msp_set_audio(client);
-
- msp_write_dsp(client, 0x13, state->acb);
+ /* unmute */
msp3400c_set_audmode(client);
+ state->scan_in_progress = 0;
+ msp_set_audio(client);
/* monitor tv audio mode, the first time don't wait
so long to get a quick stereo/bilingual result */
- if (msp_sleep(state, 1000))
- goto restart;
+ count = 3;
while (state->watch_stereo) {
- watch_stereo(client);
- if (msp_sleep(state, 5000))
+ if (msp_sleep(state, count ? 1000 : 5000))
goto restart;
+ if (count) count--;
+ watch_stereo(client);
}
}
v4l_dbg(1, msp_debug, client, "thread: exit\n");
@@ -829,27 +840,27 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
source = 0; /* mono only */
matrix = 0x30;
break;
- case V4L2_TUNER_MODE_LANG1:
- source = 3; /* stereo or A */
- matrix = 0x00;
- break;
case V4L2_TUNER_MODE_LANG2:
source = 4; /* stereo or B */
matrix = 0x10;
break;
- case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
- default:
source = 1; /* stereo or A|B */
matrix = 0x20;
break;
+ case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1:
+ default:
+ source = 3; /* stereo or A */
+ matrix = 0x00;
+ break;
}
- if (in == MSP_DSP_OUT_TUNER)
+ if (in == MSP_DSP_IN_TUNER)
source = (source << 8) | 0x20;
/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
instead of 11, 12, 13. So we add one for that msp version. */
- else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
+ else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic)
source = ((in + 1) << 8) | matrix;
else
source = (in << 8) | matrix;
@@ -869,7 +880,7 @@ static void msp34xxg_set_sources(struct i2c_client *client)
msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
- if (state->has_scart23_in_scart2_out)
+ if (state->has_scart2_out)
msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
}
@@ -887,10 +898,6 @@ static void msp34xxg_reset(struct i2c_client *client)
msp_reset(client);
- /* make sure that input/output is muted (paranoid mode) */
- /* ACB, mute DSP input, mute SCART 1 */
- msp_write_dsp(client, 0x13, 0x0f20);
-
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
@@ -1028,7 +1035,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client)
if (state->std == 0x20) {
if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
- (state->audmode == V4L2_TUNER_MODE_STEREO ||
+ (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 ||
state->audmode == V4L2_TUNER_MODE_LANG2)) {
msp_write_dem(client, 0x20, 0x21);
} else {
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
new file mode 100644
index 000000000000..86376556f108
--- /dev/null
+++ b/drivers/media/video/pwc/Kconfig
@@ -0,0 +1,28 @@
+config USB_PWC
+ tristate "USB Philips Cameras"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y or M here if you want to use one of these Philips & OEM
+ webcams:
+ * Philips PCA645, PCA646
+ * Philips PCVC675, PCVC680, PCVC690
+ * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+ * Askey VC010
+ * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+ and 'Orbit'/'Sphere'
+ * Samsung MPC-C10, MPC-C30
+ * Creative Webcam 5, Pro Ex
+ * SOTEC Afina Eye
+ * Visionite VCS-UC300, VCS-UM100
+
+ The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+ and never will be, but the 665 and 720/20 are supported by other
+ drivers.
+
+ See <file:Documentation/usb/philips.txt> for more information and
+ installation instructions.
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pwc.
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index b05015282601..dceebc0b1250 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -40,6 +40,7 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/saa7115.h>
#include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");
@@ -53,7 +54,7 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
static unsigned short normal_i2c[] = {
- 0x4a >>1, 0x48 >>1, /* SAA7113 */
+ 0x4a >> 1, 0x48 >> 1, /* SAA7113 */
0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */
I2C_CLIENT_END };
@@ -722,16 +723,16 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
100 reserved NTSC-Japan (3.58MHz)
*/
if (state->ident == V4L2_IDENT_SAA7113) {
- u8 reg = saa7115_read(client, 0x0e) & 0x8f;
+ u8 reg = saa7115_read(client, 0x0e) & 0x8f;
if (std == V4L2_STD_PAL_M) {
- reg|=0x30;
+ reg |= 0x30;
} else if (std == V4L2_STD_PAL_N) {
- reg|=0x20;
+ reg |= 0x20;
} else if (std == V4L2_STD_PAL_60) {
- reg|=0x10;
+ reg |= 0x10;
} else if (std == V4L2_STD_NTSC_M_JP) {
- reg|=0x40;
+ reg |= 0x40;
}
saa7115_write(client, 0x0e, reg);
}
@@ -811,7 +812,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
u8 lcr[24];
int i, x;
- /* saa7113/71144 doesn't yet support VBI */
+ /* saa7113/7114 doesn't yet support VBI */
if (state->ident != V4L2_IDENT_SAA7115)
return;
@@ -851,7 +852,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
case 0:
lcr[i] |= 0xf << (4 * x);
break;
- case V4L2_SLICED_TELETEXT_PAL_B:
+ case V4L2_SLICED_TELETEXT_B:
lcr[i] |= 1 << (4 * x);
break;
case V4L2_SLICED_CAPTION_525:
@@ -880,7 +881,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
{
static u16 lcr2vbi[] = {
- 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */
+ 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
0, V4L2_SLICED_CAPTION_525, /* 4 */
V4L2_SLICED_WSS_625, 0, /* 5 */
V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
@@ -1045,7 +1046,7 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
/* decode payloads */
switch (id2) {
case 1:
- vbi->type = V4L2_SLICED_TELETEXT_PAL_B;
+ vbi->type = V4L2_SLICED_TELETEXT_B;
break;
case 4:
if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
@@ -1180,6 +1181,46 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
state->radio = 1;
break;
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ {
+ struct v4l2_routing *route = arg;
+
+ route->input = state->input;
+ route->output = 0;
+ break;
+ }
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ struct v4l2_routing *route = arg;
+
+ v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
+ /* saa7113 does not have these inputs */
+ if (state->ident == V4L2_IDENT_SAA7113 &&
+ (route->input == SAA7115_COMPOSITE4 ||
+ route->input == SAA7115_COMPOSITE5)) {
+ return -EINVAL;
+ }
+ if (route->input > SAA7115_SVIDEO3)
+ return -EINVAL;
+ if (state->input == route->input)
+ break;
+ v4l_dbg(1, debug, client, "now setting %s input\n",
+ (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
+ state->input = route->input;
+
+ /* select mode */
+ saa7115_write(client, 0x02,
+ (saa7115_read(client, 0x02) & 0xf0) |
+ state->input);
+
+ /* bypass chrominance trap for S-Video modes */
+ saa7115_write(client, 0x09,
+ (saa7115_read(client, 0x09) & 0x7f) |
+ (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+ break;
+ }
+
case VIDIOC_G_INPUT:
*(int *)arg = state->input;
break;
@@ -1321,7 +1362,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
saa7115_write(client, 0, 5);
chip_id = saa7115_read(client, 0) & 0x0f;
- if (chip_id <3 && chip_id > 5) {
+ if (chip_id < 3 && chip_id > 5) {
v4l_dbg(1, debug, client, "saa7115 not found\n");
kfree(client);
return 0;
@@ -1360,7 +1401,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
v4l_dbg(1, debug, client, "writing init values\n");
/* init to 60hz/48khz */
- if (state->ident==V4L2_IDENT_SAA7113)
+ if (state->ident == V4L2_IDENT_SAA7113)
saa7115_writeregs(client, saa7113_init_auto_input);
else
saa7115_writeregs(client, saa7115_init_auto_input);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 992c71774f30..133f9e5252fe 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -54,6 +54,7 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/saa7127.h>
static int debug = 0;
static int test_image = 0;
@@ -222,22 +223,6 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = {
{ 0, 0 }
};
-/* Enumeration for the Supported input types */
-enum saa7127_input_type {
- SAA7127_INPUT_TYPE_NORMAL,
- SAA7127_INPUT_TYPE_TEST_IMAGE
-};
-
-/* Enumeration for the Supported Output signal types */
-enum saa7127_output_type {
- SAA7127_OUTPUT_TYPE_BOTH,
- SAA7127_OUTPUT_TYPE_COMPOSITE,
- SAA7127_OUTPUT_TYPE_SVIDEO,
- SAA7127_OUTPUT_TYPE_RGB,
- SAA7127_OUTPUT_TYPE_YUV_C,
- SAA7127_OUTPUT_TYPE_YUV_V
-};
-
/*
**********************************************************************
*
@@ -561,7 +546,7 @@ static int saa7127_command(struct i2c_client *client,
{
struct saa7127_state *state = i2c_get_clientdata(client);
struct v4l2_format *fmt = arg;
- int *iarg = arg;
+ struct v4l2_routing *route = arg;
switch (cmd) {
case VIDIOC_S_STD:
@@ -573,15 +558,23 @@ static int saa7127_command(struct i2c_client *client,
*(v4l2_std_id *)arg = state->std;
break;
- case VIDIOC_S_INPUT:
- if (state->input_type == *iarg)
- break;
- return saa7127_set_input_type(client, *iarg);
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = state->input_type;
+ route->output = state->output_type;
+ break;
- case VIDIOC_S_OUTPUT:
- if (state->output_type == *iarg)
- break;
- return saa7127_set_output_type(client, *iarg);
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ int rc = 0;
+
+ if (state->input_type != route->input) {
+ rc = saa7127_set_input_type(client, route->input);
+ }
+ if (rc == 0 && state->output_type != route->output) {
+ rc = saa7127_set_output_type(client, route->output);
+ }
+ return rc;
+ }
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 86671a43e769..e1c1805df1fb 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -39,6 +39,7 @@ config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
select VIDEO_BUF_DVB
+ select FW_LOADER
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 1ba998424bbd..be7b9ee697d6 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -11,9 +11,9 @@ obj-$(CONFIG_VIDEO_SAA7134_OSS) += saa7134-oss.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index fdd7f48f3b76..e666a4465ca4 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -208,7 +208,7 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_FLYTVPLATINUM_FM] = {
/* LifeView FlyTV Platinum FM (LR214WF) */
/* "Peter Missel <peter.missel@onlinehome.de> */
- .name = "LifeView FlyTV Platinum FM",
+ .name = "LifeView FlyTV Platinum FM / Gold",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
@@ -2660,7 +2660,7 @@ struct saa7134_board saa7134_boards[] = {
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_comp1,
- .vmux = 0,
+ .vmux = 1,
.amux = LINE1,
},{
.name = name_svideo,
@@ -2671,7 +2671,7 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_FLYDVBT_LR301] = {
/* LifeView FlyDVB-T */
/* Giampiero Giancipoli <gianci@libero.it> */
- .name = "LifeView FlyDVB-T",
+ .name = "LifeView FlyDVB-T / Genius VideoWonder DVB-T",
.audio_clock = 0x00200000,
.tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
@@ -2808,6 +2808,40 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
+ [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
+ .name = "LifeView FlyDVB-T Hybrid Cardbus",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x200000, /* GPIO21=High for TV input */
+ .tv = 1,
+ },{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ },{
+ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3333,6 +3367,30 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x0005,
.driver_data = SAA7134_BOARD_MD7134_BRIDGE_2,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1489,
+ .subdevice = 0x0301,
+ .driver_data = SAA7134_BOARD_FLYDVBT_LR301,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168, /* Animation Technologies (LifeView) */
+ .subdevice = 0x0304,
+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168,
+ .subdevice = 0x3306,
+ .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168,
+ .subdevice = 0x3502, /* whats the difference to 0x3306 ?*/
+ .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3462,6 +3520,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
break;
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00);
break;
@@ -3633,6 +3692,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
/* make the tda10046 find its eeprom */
{
u8 data[] = { 0x3c, 0x33, 0x62};
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index c98571c9d5a6..13de05532e0a 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -870,7 +871,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat,pci_resource_start(pci_dev,0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev,0xffffffff)) {
+ if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) {
printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
err = -EIO;
goto fail1;
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 86cfdb8514cb..222a36c38917 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1064,6 +1064,10 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
&dev->i2c_adap);
break;
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+ dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
+ &dev->i2c_adap);
+ break;
#endif
#ifdef HAVE_NXT200X
case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 31ba293854c1..353af3a8b766 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -220,6 +220,7 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_A169_B 91
#define SAA7134_BOARD_AVERMEDIA_A169_B1 92
#define SAA7134_BOARD_MD7134_BRIDGE_2 93
+#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
new file mode 100644
index 000000000000..55f2bc11964b
--- /dev/null
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -0,0 +1,11 @@
+config USB_SN9C102
+ tristate "USB SN9C10x PC Camera Controller support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on SONiX SN9C101,
+ SN9C102 or SN9C103 PC Camera Controllers.
+
+ See <file:Documentation/video4linux/sn9c102.txt> for more info.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sn9c102.
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index df195c905366..1013b4de89a2 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -401,7 +401,7 @@ static void tuner_status(struct i2c_client *client)
}
tuner_info("Tuner mode: %s\n", p);
tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
- tuner_info("Standard: 0x%08llx\n", t->std);
+ tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
if (t->mode != V4L2_TUNER_RADIO)
return;
if (t->has_signal) {
@@ -558,10 +558,10 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
static inline int check_v4l2(struct tuner *t)
{
- if (t->using_v4l2) {
- tuner_dbg ("ignore v4l1 call\n");
- return EINVAL;
- }
+ /* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
+ TV, v4l1 for radio), until that is fixed this code is disabled.
+ Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
+ first. */
return 0;
}
@@ -744,6 +744,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch_v4l2();
tuner->type = t->mode;
+ if (t->mode == V4L2_TUNER_ANALOG_TV)
+ tuner->capability |= V4L2_TUNER_CAP_NORM;
if (t->mode != V4L2_TUNER_RADIO) {
tuner->rangelow = tv_range[0] * 16;
tuner->rangehigh = tv_range[1] * 16;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 356bff455ad1..c2b756107548 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1706,21 +1706,6 @@ static int chip_command(struct i2c_client *client,
break;
}
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *sarg = arg;
-
- if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4)
- return -EINVAL;
- /* There are four inputs: tuner, radio, extern and intern. */
- chip->input = sarg->index;
- if (chip->muted)
- break;
- chip_write_masked(chip, desc->inputreg,
- desc->inputmap[chip->input], desc->inputmask);
- break;
- }
-
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *vt = arg;
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index e0d2ff83fc91..431c3e2f6c42 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -757,9 +757,9 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
static int
tveeprom_attach_adapter (struct i2c_adapter *adapter)
{
- if (adapter->id != I2C_HW_B_BT848)
- return 0;
- return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+ return 0;
}
static int
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 69d0fe159f4d..dab4973bcf82 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -53,7 +53,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = 0,
.maximum = 255,
.step = 1,
- .default_value = 0,
+ .default_value = 128,
.flags = 0,
}, {
.id = V4L2_CID_CONTRAST,
@@ -62,7 +62,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = 0,
.maximum = 255,
.step = 0x1,
- .default_value = 0x10,
+ .default_value = 128,
.flags = 0,
}, {
.id = V4L2_CID_SATURATION,
@@ -71,7 +71,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = 0,
.maximum = 255,
.step = 0x1,
- .default_value = 0x10,
+ .default_value = 128,
.flags = 0,
}, {
.id = V4L2_CID_HUE,
@@ -80,7 +80,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = -128,
.maximum = 127,
.step = 0x1,
- .default_value = 0x10,
+ .default_value = 0,
.flags = 0,
}
};
@@ -500,16 +500,21 @@ struct i2c_vbi_ram_value {
static struct i2c_vbi_ram_value vbi_ram_default[] =
{
+ /* FIXME: Current api doesn't handle all VBI types, those not
+ yet supported are placed under #if 0 */
+#if 0
{0x010, /* Teletext, SECAM, WST System A */
{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
+#endif
{0x030, /* Teletext, PAL, WST System B */
- {V4L2_SLICED_TELETEXT_PAL_B,6,22,1},
+ {V4L2_SLICED_TELETEXT_B,6,22,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
+#if 0
{0x050, /* Teletext, PAL, WST System C */
{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
@@ -535,6 +540,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
},
+#endif
{0x0f0, /* Closed Caption, NTSC */
{V4L2_SLICED_CAPTION_525,21,21,1},
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
@@ -545,6 +551,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
},
+#if 0
{0x130, /* Wide Screen Signal, NTSC C */
{V4L2_SLICED_WSS_525,20,20,1},
{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
@@ -560,6 +567,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
},
+#endif
{0x190, /* Video Program System (VPS), PAL */
{V4L2_SLICED_VPS,16,16,0},
{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
@@ -850,7 +858,6 @@ static int tvp5150_command(struct i2c_client *c,
case 0:
case VIDIOC_INT_RESET:
- case DECODER_INIT:
tvp5150_reset(c);
break;
case VIDIOC_S_STD:
@@ -949,99 +956,15 @@ static int tvp5150_command(struct i2c_client *c,
#endif
case VIDIOC_LOG_STATUS:
- case DECODER_DUMP:
dump_reg(c);
break;
- case DECODER_GET_CAPABILITIES:
+ case VIDIOC_G_TUNER:
{
- struct video_decoder_capability *cap = arg;
-
- cap->flags = VIDEO_DECODER_PAL |
- VIDEO_DECODER_NTSC |
- VIDEO_DECODER_SECAM |
- VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
- cap->inputs = 3;
- cap->outputs = 1;
- break;
- }
- case DECODER_GET_STATUS:
- {
- int *iarg = arg;
- int status;
- int res=0;
- status = tvp5150_read(c, 0x88);
- if(status&0x08){
- res |= DECODER_STATUS_COLOR;
- }
- if(status&0x04 && status&0x02){
- res |= DECODER_STATUS_GOOD;
- }
- *iarg=res;
- break;
- }
-
- case DECODER_SET_GPIO:
- break;
-
- case DECODER_SET_VBI_BYPASS:
- break;
-
- case DECODER_SET_NORM:
- {
- int *iarg = arg;
-
- switch (*iarg) {
-
- case VIDEO_MODE_NTSC:
- break;
-
- case VIDEO_MODE_PAL:
- break;
-
- case VIDEO_MODE_SECAM:
- break;
-
- case VIDEO_MODE_AUTO:
- break;
-
- default:
- return -EINVAL;
-
- }
- decoder->norm = *iarg;
- break;
- }
- case DECODER_SET_INPUT:
- {
- int *iarg = arg;
- if (*iarg < 0 || *iarg > 3) {
- return -EINVAL;
- }
-
- decoder->input = *iarg;
- tvp5150_selmux(c, decoder->input);
-
- break;
- }
- case DECODER_SET_OUTPUT:
- {
- int *iarg = arg;
-
- /* not much choice of outputs */
- if (*iarg != 0) {
- return -EINVAL;
- }
- break;
- }
- case DECODER_ENABLE_OUTPUT:
- {
- int *iarg = arg;
-
- decoder->enable = (*iarg != 0);
-
- tvp5150_selmux(c, decoder->input);
+ struct v4l2_tuner *vt = arg;
+ int status = tvp5150_read(c, 0x88);
+ vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0;
break;
}
case VIDIOC_QUERYCTRL:
@@ -1087,35 +1010,6 @@ static int tvp5150_command(struct i2c_client *c,
return -EINVAL;
}
- case DECODER_SET_PICTURE:
- {
- struct video_picture *pic = arg;
- if (decoder->bright != pic->brightness) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->bright = pic->brightness;
- tvp5150_write(c, TVP5150_BRIGHT_CTL,
- decoder->bright >> 8);
- }
- if (decoder->contrast != pic->contrast) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->contrast = pic->contrast;
- tvp5150_write(c, TVP5150_CONTRAST_CTL,
- decoder->contrast >> 8);
- }
- if (decoder->sat != pic->colour) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->sat = pic->colour;
- tvp5150_write(c, TVP5150_SATURATION_CTL,
- decoder->contrast >> 8);
- }
- if (decoder->hue != pic->hue) {
- /* We want -128 to 127 we get 0-65535 */
- decoder->hue = pic->hue;
- tvp5150_write(c, TVP5150_HUE_CTL,
- (decoder->hue - 32768) >> 8);
- }
- break;
- }
default:
return -EINVAL;
}
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
new file mode 100644
index 000000000000..fc52201d607e
--- /dev/null
+++ b/drivers/media/video/upd64031a.c
@@ -0,0 +1,286 @@
+/*
+ * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan
+ *
+ * 2003 by T.Adachi <tadachi@tadachi-net.com>
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/upd64031a.h>
+
+// --------------------- read registers functions define -----------------------
+
+/* bit masks */
+#define GR_MODE_MASK 0xc0
+#define DIRECT_3DYCS_CONNECT_MASK 0xc0
+#define SYNC_CIRCUIT_MASK 0xa0
+
+// -----------------------------------------------------------------------------
+
+MODULE_DESCRIPTION("uPD64031A driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static unsigned short normal_i2c[] = { 0x24 >> 1, 0x26 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+enum {
+ R00 = 0, R01, R02, R03, R04,
+ R05, R06, R07, R08, R09,
+ R0A, R0B, R0C, R0D, R0E, R0F,
+ /* unused registers
+ R10, R11, R12, R13, R14,
+ R15, R16, R17,
+ */
+ TOT_REGS
+};
+
+struct upd64031a_state {
+ u8 regs[TOT_REGS];
+ u8 gr_mode;
+ u8 direct_3dycs_connect;
+ u8 ext_comp_sync;
+ u8 ext_vert_sync;
+};
+
+static u8 upd64031a_init[] = {
+ 0x00, 0xb8, 0x48, 0xd2, 0xe6,
+ 0x03, 0x10, 0x0b, 0xaf, 0x7f,
+ 0x00, 0x00, 0x1d, 0x5e, 0x00,
+ 0xd0
+};
+
+/* ------------------------------------------------------------------------ */
+
+static u8 upd64031a_read(struct i2c_client *client, u8 reg)
+{
+ u8 buf[2];
+
+ if (reg >= sizeof(buf))
+ return 0xff;
+ i2c_master_recv(client, buf, 2);
+ return buf[reg];
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64031a_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ u8 buf[2];
+
+ buf[0] = reg;
+ buf[1] = val;
+ v4l_dbg(1, debug, client, "writing reg addr: %02X val: %02X\n", reg, val);
+ if (i2c_master_send(client, buf, 2) != 2)
+ v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* The input changed due to new input or channel changed */
+static void upd64031a_change(struct i2c_client *client)
+{
+ struct upd64031a_state *state = i2c_get_clientdata(client);
+ u8 reg = state->regs[R00];
+
+ v4l_dbg(1, debug, client, "changed input or channel\n");
+ upd64031a_write(client, R00, reg | 0x10);
+ upd64031a_write(client, R00, reg & ~0x10);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct upd64031a_state *state = i2c_get_clientdata(client);
+ struct v4l2_routing *route = arg;
+
+ switch (cmd) {
+ case VIDIOC_S_FREQUENCY:
+ upd64031a_change(client);
+ break;
+
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = (state->gr_mode >> 6) |
+ (state->direct_3dycs_connect >> 4) |
+ (state->ext_comp_sync >> 1) |
+ (state->ext_vert_sync >> 2);
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ u8 r00, r05, r08;
+
+ state->gr_mode = (route->input & 3) << 6;
+ state->direct_3dycs_connect = (route->input & 0xc) << 4;
+ state->ext_comp_sync = (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1;
+ state->ext_vert_sync = (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2;
+ r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode;
+ r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) |
+ state->ext_comp_sync | state->ext_vert_sync;
+ r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) |
+ state->direct_3dycs_connect;
+ upd64031a_write(client, R00, r00);
+ upd64031a_write(client, R05, r05);
+ upd64031a_write(client, R08, r08);
+ upd64031a_change(client);
+ break;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ v4l_info(client, "Status: SA00=0x%02x SA01=0x%02x\n",
+ upd64031a_read(client, 0), upd64031a_read(client, 1));
+ break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+ return -EINVAL;
+ reg->val = upd64031a_read(client, reg->reg & 0xff);
+ break;
+ }
+
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ u8 addr = reg->reg & 0xff;
+ u8 val = reg->val & 0xff;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ upd64031a_write(client, addr, val);
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int upd64031a_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct upd64031a_state *state;
+ int i;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL) {
+ return -ENOMEM;
+ }
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "uPD64031A");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, state);
+ memcpy(state->regs, upd64031a_init, sizeof(state->regs));
+ state->gr_mode = UPD64031A_GR_ON << 6;
+ state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4;
+ state->ext_comp_sync = state->ext_vert_sync = 0;
+ for (i = 0; i < TOT_REGS; i++) {
+ upd64031a_write(client, i, state->regs[i]);
+ }
+
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int upd64031a_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, upd64031a_attach);
+ return 0;
+}
+
+static int upd64031a_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err)
+ return err;
+
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "upd64031a",
+ },
+ .id = I2C_DRIVERID_UPD64031A,
+ .attach_adapter = upd64031a_probe,
+ .detach_client = upd64031a_detach,
+ .command = upd64031a_command,
+};
+
+
+static int __init upd64031a_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit upd64031a_exit_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(upd64031a_init_module);
+module_exit(upd64031a_exit_module);
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
new file mode 100644
index 000000000000..c3a7ffe5c267
--- /dev/null
+++ b/drivers/media/video/upd64083.c
@@ -0,0 +1,262 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation driver
+ *
+ * 2003 by T.Adachi (tadachi@tadachi-net.com)
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/upd64083.h>
+
+MODULE_DESCRIPTION("uPD64083 driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+enum {
+ R00 = 0, R01, R02, R03, R04,
+ R05, R06, R07, R08, R09,
+ R0A, R0B, R0C, R0D, R0E, R0F,
+ R10, R11, R12, R13, R14,
+ R15, R16,
+ TOT_REGS
+};
+
+struct upd64083_state {
+ u8 mode;
+ u8 ext_y_adc;
+ u8 regs[TOT_REGS];
+};
+
+/* Initial values when used in combination with the
+ NEC upd64031a ghost reduction chip. */
+static u8 upd64083_init[] = {
+ 0x1f, 0x01, 0xa0, 0x2d, 0x29, /* we use EXCSS=0 */
+ 0x36, 0xdd, 0x05, 0x56, 0x48,
+ 0x00, 0x3a, 0xa0, 0x05, 0x08,
+ 0x44, 0x60, 0x08, 0x52, 0xf8,
+ 0x53, 0x60, 0x10
+};
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_log_status(struct i2c_client *client)
+{
+ u8 buf[7];
+
+ i2c_master_recv(client, buf, 7);
+ v4l_info(client, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x "
+ "SA04=%02x SA05=%02x SA06=%02x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ u8 buf[2];
+
+ buf[0] = reg;
+ buf[1] = val;
+ v4l_dbg(1, debug, client, "writing reg addr: %02x val: %02x\n", reg, val);
+ if (i2c_master_send(client, buf, 2) != 2)
+ v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u8 upd64083_read(struct i2c_client *client, u8 reg)
+{
+ u8 buf[7];
+
+ if (reg >= sizeof(buf))
+ return 0xff;
+ i2c_master_recv(client, buf, sizeof(buf));
+ return buf[reg];
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct upd64083_state *state = i2c_get_clientdata(client);
+ struct v4l2_routing *route = arg;
+
+ switch (cmd) {
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = (state->mode >> 6) | (state->ext_y_adc >> 3);
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ u8 r00, r02;
+
+ if (route->input > 7 || (route->input & 6) == 6)
+ return -EINVAL;
+ state->mode = (route->input & 3) << 6;
+ state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3;
+ r00 = (state->regs[R00] & ~(3 << 6)) | state->mode;
+ r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc;
+ upd64083_write(client, R00, r00);
+ upd64083_write(client, R02, r02);
+ break;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ upd64083_log_status(client);
+ break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+ return -EINVAL;
+ reg->val = upd64083_read(client, reg->reg & 0xff);
+ break;
+ }
+
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ u8 addr = reg->reg & 0xff;
+ u8 val = reg->val & 0xff;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ upd64083_write(client, addr, val);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int upd64083_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct upd64083_state *state;
+ int i;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL) {
+ return -ENOMEM;
+ }
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "uPD64083");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, state);
+ /* Initially assume that a ghost reduction chip is present */
+ state->mode = 0; /* YCS mode */
+ state->ext_y_adc = (1 << 5);
+ memcpy(state->regs, upd64083_init, TOT_REGS);
+ for (i = 0; i < TOT_REGS; i++) {
+ upd64083_write(client, i, state->regs[i]);
+ }
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int upd64083_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, upd64083_attach);
+ return 0;
+}
+
+static int upd64083_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err)
+ return err;
+
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "upd64083",
+ },
+ .id = I2C_DRIVERID_UPD64083,
+ .attach_adapter = upd64083_probe,
+ .detach_client = upd64083_detach,
+ .command = upd64083_command,
+};
+
+
+static int __init upd64083_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit upd64083_exit_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(upd64083_init_module);
+module_exit(upd64083_exit_module);
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
new file mode 100644
index 000000000000..08a5d20bb2c0
--- /dev/null
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -0,0 +1,38 @@
+config VIDEO_USBVIDEO
+ tristate
+
+config USB_VICAM
+ tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
+ depends on USB && VIDEO_DEV && EXPERIMENTAL
+ select VIDEO_USBVIDEO
+ ---help---
+ Say Y here if you have 3com homeconnect camera (vicam).
+
+ To compile this driver as a module, choose M here: the
+ module will be called vicam.
+
+config USB_IBMCAM
+ tristate "USB IBM (Xirlink) C-it Camera support"
+ depends on USB && VIDEO_DEV
+ select VIDEO_USBVIDEO
+ ---help---
+ Say Y here if you want to connect a IBM "C-It" camera, also known as
+ "Xirlink PC Camera" to your computer's USB port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmcam.
+
+ This camera has several configuration options which
+ can be specified when you load the module. Read
+ <file:Documentation/video4linux/ibmcam.txt> to learn more.
+
+config USB_KONICAWC
+ tristate "USB Konica Webcam support"
+ depends on USB && VIDEO_DEV
+ select VIDEO_USBVIDEO
+ ---help---
+ Say Y here if you want support for webcams based on a Konica
+ chipset. This is known to work with the Intel YC76 webcam.
+
+ To compile this driver as a module, choose M here: the
+ module will be called konicawc.
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
index ed410a5ee8c9..bb52eb8dc2f9 100644
--- a/drivers/media/video/usbvideo/Makefile
+++ b/drivers/media/video/usbvideo/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
-obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o
-obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
-
+obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o
+obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o
+obj-$(CONFIG_USB_KONICAWC) += konicawc.o
+obj-$(CONFIG_USB_VICAM) += vicam.o
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 11a97f30b876..d330fa985bcc 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -317,6 +317,7 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
[_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG",
+ [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE",
[_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER",
[_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER",
[_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
@@ -325,7 +326,12 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT",
- [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ"
+ [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ",
+ [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY",
+ [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
+ [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
+ [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
+ [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING"
};
#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index d2ca0f08d0df..acc5ea936687 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -399,19 +399,25 @@ void videobuf_queue_pci(struct videobuf_queue* q)
int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
{
struct videobuf_queue q;
+ struct videobuf_queue_ops qops;
q.dev=pci;
- q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+ qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+ qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+ q.ops = &qops;
- return (videobuf_dma_unmap(&q,dma));
+ return (videobuf_dma_map(&q,dma));
}
int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
{
struct videobuf_queue q;
+ struct videobuf_queue_ops qops;
q.dev=pci;
- q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+ qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+ qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+ q.ops = &qops;
return (videobuf_dma_unmap(&q,dma));
}
@@ -923,7 +929,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
/* need to capture a new frame */
retval = -ENOMEM;
q->read_buf = videobuf_alloc(q->msize);
- dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf);
+ dprintk(1,"video alloc=0x%p\n", q->read_buf);
if (NULL == q->read_buf)
goto done;
q->read_buf->memory = V4L2_MEMORY_USERPTR;
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
new file mode 100644
index 000000000000..a9b59c35cd67
--- /dev/null
+++ b/drivers/media/video/wm8739.c
@@ -0,0 +1,355 @@
+/*
+ * wm8739
+ *
+ * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com>
+ *
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ * - Cleanup
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("wm8739 driver");
+MODULE_AUTHOR("T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static unsigned short normal_i2c[] = { 0x34 >> 1, 0x36 >> 1, I2C_CLIENT_END };
+
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+I2C_CLIENT_INSMOD;
+
+/* ------------------------------------------------------------------------ */
+
+enum {
+ R0 = 0, R1,
+ R5 = 5, R6, R7, R8, R9, R15 = 15,
+ TOT_REGS
+};
+
+struct wm8739_state {
+ u32 clock_freq;
+ u8 muted;
+ u16 volume;
+ u16 balance;
+ u8 vol_l; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+ u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_write(struct i2c_client *client, int reg, u16 val)
+{
+ int i;
+
+ if (reg < 0 || reg >= TOT_REGS) {
+ v4l_err(client, "Invalid register R%d\n", reg);
+ return -1;
+ }
+
+ v4l_dbg(1, debug, client, "write: %02x %02x\n", reg, val);
+
+ for (i = 0; i < 3; i++) {
+ if (i2c_smbus_write_byte_data(client, (reg << 1) |
+ (val >> 8), val & 0xff) == 0) {
+ return 0;
+ }
+ }
+ v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+ return -1;
+}
+
+/* write regs to set audio volume etc */
+static void wm8739_set_audio(struct i2c_client *client)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+ u16 mute = state->muted ? 0x80 : 0;
+
+ /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
+ * Default setting: 0x17 = 0 dB
+ */
+ wm8739_write(client, R0, (state->vol_l & 0x1f) | mute);
+ wm8739_write(client, R1, (state->vol_r & 0x1f) | mute);
+}
+
+static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = state->muted;
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = state->volume;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ ctrl->value = state->balance;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+ unsigned int work_l, work_r;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ state->muted = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ state->volume = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ state->balance = ctrl->value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
+ work_l = (min(65536 - state->balance, 32768) * state->volume) / 32768;
+ work_r = (min(state->balance, (u16)32768) * state->volume) / 32768;
+
+ state->vol_l = (long)work_l * 31 / 65535;
+ state->vol_r = (long)work_r * 31 / 65535;
+
+ /* set audio volume etc. */
+ wm8739_set_audio(client);
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct v4l2_queryctrl wm8739_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 58880,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },{
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ {
+ u32 audiofreq = *(u32 *)arg;
+
+ state->clock_freq = audiofreq;
+ wm8739_write(client, R9, 0x000); /* de-activate */
+ switch (audiofreq) {
+ case 44100:
+ wm8739_write(client, R8, 0x020); /* 256fps, fs=44.1k */
+ break;
+ case 48000:
+ wm8739_write(client, R8, 0x000); /* 256fps, fs=48k */
+ break;
+ case 32000:
+ wm8739_write(client, R8, 0x018); /* 256fps, fs=32k */
+ break;
+ default:
+ break;
+ }
+ wm8739_write(client, R9, 0x001); /* activate */
+ break;
+ }
+
+ case VIDIOC_G_CTRL:
+ return wm8739_get_ctrl(client, arg);
+
+ case VIDIOC_S_CTRL:
+ return wm8739_set_ctrl(client, arg);
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++)
+ if (qc->id && qc->id == wm8739_qctrl[i].id) {
+ memcpy(qc, &wm8739_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ v4l_info(client, "Frequency: %u Hz\n", state->clock_freq);
+ v4l_info(client, "Volume L: %02x%s\n", state->vol_l & 0x1f,
+ state->muted ? " (muted)" : "");
+ v4l_info(client, "Volume R: %02x%s\n", state->vol_r & 0x1f,
+ state->muted ? " (muted)" : "");
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int wm8739_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct wm8739_state *state;
+
+ /* Check if the adapter supports the needed features */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "wm8739");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ state->vol_l = 0x17; /* 0dB */
+ state->vol_r = 0x17; /* 0dB */
+ state->muted = 0;
+ state->balance = 32768;
+ /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */
+ state->volume = ((long)state->vol_l + 1) * 65535 / 31;
+ state->clock_freq = 48000;
+ i2c_set_clientdata(client, state);
+
+ /* initialize wm8739 */
+ wm8739_write(client, R15, 0x00); /* reset */
+ wm8739_write(client, R5, 0x000); /* filter setting, high path, offet clear */
+ wm8739_write(client, R6, 0x000); /* ADC, OSC, Power Off mode Disable */
+ wm8739_write(client, R7, 0x049); /* Digital Audio interface format */
+ /* Enable Master mode */
+ /* 24 bit, MSB first/left justified */
+ wm8739_write(client, R8, 0x000); /* sampling control */
+ /* normal, 256fs, 48KHz sampling rate */
+ wm8739_write(client, R9, 0x001); /* activate */
+ wm8739_set_audio(client); /* set volume/mute */
+
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int wm8739_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, wm8739_attach);
+ return 0;
+}
+
+static int wm8739_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err)
+ return err;
+
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "wm8739",
+ },
+ .id = I2C_DRIVERID_WM8739,
+ .attach_adapter = wm8739_probe,
+ .detach_client = wm8739_detach,
+ .command = wm8739_command,
+};
+
+
+static int __init wm8739_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit wm8739_cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(wm8739_init_module);
+module_exit(wm8739_cleanup_module);
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig
new file mode 100644
index 000000000000..c3bf886b80cd
--- /dev/null
+++ b/drivers/media/video/zc0301/Kconfig
@@ -0,0 +1,11 @@
+config USB_ZC0301
+ tristate "USB ZC0301 Image Processor and Control Chip support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on the ZC0301
+ Image Processor and Control Chip.
+
+ See <file:Documentation/video4linux/zc0301.txt> for more info.
+
+ To compile this driver as a module, choose M here: the
+ module will be called zc0301.
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 010d4a39269b..e9716b10acea 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -366,7 +366,15 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
static int
mptsas_slave_configure(struct scsi_device *sdev)
{
- sas_read_port_mode_page(sdev);
+ struct Scsi_Host *host = sdev->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+
+ /*
+ * RAID volumes placed beyond the last expected port.
+ * Ignore sending sas mode pages in that case..
+ */
+ if (sdev->channel < hd->ioc->num_ports)
+ sas_read_port_mode_page(sdev);
return mptscsih_slave_configure(sdev);
}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 7cc162e8978b..003b077c2324 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -91,4 +91,22 @@ config MMC_AU1X
If unsure, say N.
+config MMC_AT91RM9200
+ tristate "AT91RM9200 SD/MMC Card Interface support"
+ depends on ARCH_AT91RM9200 && MMC
+ help
+ This selects the AT91RM9200 MCI controller.
+
+ If unsure, say N.
+
+config MMC_IMX
+ tristate "Motorola i.MX Multimedia Card Interface support"
+ depends on ARCH_IMX && MMC
+ help
+ This selects the Motorola i.MX Multimedia card Interface.
+ If you have a i.MX platform with a Multimedia Card slot,
+ say Y or M here.
+
+ If unsure, say N.
+
endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c7c34aadfc92..d2957e35cc6f 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -17,10 +17,12 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
#
obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
obj-$(CONFIG_MMC_PXA) += pxamci.o
+obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o
+obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o
mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
new file mode 100644
index 000000000000..6061c2d101a0
--- /dev/null
+++ b/drivers/mmc/at91_mci.c
@@ -0,0 +1,988 @@
+/*
+ * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ *
+ * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
+ *
+ * Copyright (C) 2006 Malcolm Noyes
+ *
+ * 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 is the AT91RM9200 MCI driver that has been tested with both MMC cards
+ and SD-cards. Boards that support write protect are now supported.
+ The CCAT91SBC001 board does not support SD cards.
+
+ The three entry points are at91_mci_request, at91_mci_set_ios
+ and at91_mci_get_ro.
+
+ SET IOS
+ This configures the device to put it into the correct mode and clock speed
+ required.
+
+ MCI REQUEST
+ MCI request processes the commands sent in the mmc_request structure. This
+ can consist of a processing command and a stop command in the case of
+ multiple block transfers.
+
+ There are three main types of request, commands, reads and writes.
+
+ Commands are straight forward. The command is submitted to the controller and
+ the request function returns. When the controller generates an interrupt to indicate
+ the command is finished, the response to the command are read and the mmc_request_done
+ function called to end the request.
+
+ Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
+ controller to manage the transfers.
+
+ A read is done from the controller directly to the scatterlist passed in from the request.
+ Due to a bug in the controller, when a read is completed, all the words are byte
+ swapped in the scatterlist buffers.
+
+ The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
+
+ A write is slightly different in that the bytes to write are read from the scatterlist
+ into a dma memory buffer (this is in case the source buffer should be read only). The
+ entire write buffer is then done from this single dma memory buffer.
+
+ The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
+
+ GET RO
+ Gets the status of the write protect pin, if available.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/mmc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mci.h>
+#include <asm/arch/at91rm9200_pdc.h>
+
+#define DRIVER_NAME "at91_mci"
+
+#undef SUPPORT_4WIRE
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(fmt...) \
+ printk(fmt)
+#else
+#define DBG(fmt...) do { } while (0)
+#endif
+
+static struct clk *mci_clk;
+
+#define FL_SENT_COMMAND (1 << 0)
+#define FL_SENT_STOP (1 << 1)
+
+
+
+/*
+ * Read from a MCI register.
+ */
+static inline unsigned long at91_mci_read(unsigned int reg)
+{
+ void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+ return __raw_readl(mci_base + reg);
+}
+
+/*
+ * Write to a MCI register.
+ */
+static inline void at91_mci_write(unsigned int reg, unsigned long value)
+{
+ void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+ __raw_writel(value, mci_base + reg);
+}
+
+/*
+ * Low level type for this driver
+ */
+struct at91mci_host
+{
+ struct mmc_host *mmc;
+ struct mmc_command *cmd;
+ struct mmc_request *request;
+
+ struct at91_mmc_data *board;
+ int present;
+
+ /*
+ * Flag indicating when the command has been sent. This is used to
+ * work out whether or not to send the stop
+ */
+ unsigned int flags;
+ /* flag for current bus settings */
+ u32 bus_mode;
+
+ /* DMA buffer used for transmitting */
+ unsigned int* buffer;
+ dma_addr_t physical_address;
+ unsigned int total_length;
+
+ /* Latest in the scatterlist that has been enabled for transfer, but not freed */
+ int in_use_index;
+
+ /* Latest in the scatterlist that has been enabled for transfer */
+ int transfer_index;
+};
+
+/*
+ * 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)
+{
+ unsigned int len, i, size;
+ unsigned *dmabuf = host->buffer;
+
+ size = host->total_length;
+ len = data->sg_len;
+
+ /*
+ * Just loop through all entries. Size might not
+ * be the entire list though so make sure that
+ * we do not transfer too much.
+ */
+ for (i = 0; i < len; i++) {
+ struct scatterlist *sg;
+ int amount;
+ int index;
+ unsigned int *sgbuffer;
+
+ sg = &data->sg[i];
+
+ sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ amount = min(size, sg->length);
+ size -= amount;
+ amount /= 4;
+
+ for (index = 0; index < amount; index++)
+ *dmabuf++ = swab32(sgbuffer[index]);
+
+ kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+
+ if (size == 0)
+ break;
+ }
+
+ /*
+ * Check that we didn't get a request to transfer
+ * more data than can fit into the SG list.
+ */
+ BUG_ON(size != 0);
+}
+
+/*
+ * Prepare a dma read
+ */
+static void at91mci_pre_dma_read(struct at91mci_host *host)
+{
+ int i;
+ struct scatterlist *sg;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ DBG("pre dma read\n");
+
+ cmd = host->cmd;
+ if (!cmd) {
+ DBG("no command\n");
+ return;
+ }
+
+ data = cmd->data;
+ if (!data) {
+ DBG("no data\n");
+ return;
+ }
+
+ for (i = 0; i < 2; i++) {
+ /* nothing left to transfer */
+ if (host->transfer_index >= data->sg_len) {
+ DBG("Nothing left to transfer (index = %d)\n", host->transfer_index);
+ break;
+ }
+
+ /* Check to see if this needs filling */
+ if (i == 0) {
+ if (at91_mci_read(AT91_PDC_RCR) != 0) {
+ DBG("Transfer active in current\n");
+ continue;
+ }
+ }
+ else {
+ if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+ DBG("Transfer active in next\n");
+ continue;
+ }
+ }
+
+ /* Setup the next transfer */
+ DBG("Using transfer index %d\n", host->transfer_index);
+
+ sg = &data->sg[host->transfer_index++];
+ DBG("sg = %p\n", sg);
+
+ sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
+
+ DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
+
+ if (i == 0) {
+ at91_mci_write(AT91_PDC_RPR, sg->dma_address);
+ at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+ }
+ else {
+ at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
+ at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+ }
+ }
+
+ DBG("pre dma read done\n");
+}
+
+/*
+ * Handle after a dma read
+ */
+static void at91mci_post_dma_read(struct at91mci_host *host)
+{
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ DBG("post dma read\n");
+
+ cmd = host->cmd;
+ if (!cmd) {
+ DBG("no command\n");
+ return;
+ }
+
+ data = cmd->data;
+ if (!data) {
+ DBG("no data\n");
+ return;
+ }
+
+ while (host->in_use_index < host->transfer_index) {
+ unsigned int *buffer;
+ int index;
+ int len;
+
+ struct scatterlist *sg;
+
+ DBG("finishing index %d\n", host->in_use_index);
+
+ sg = &data->sg[host->in_use_index++];
+
+ DBG("Unmapping page %08X\n", sg->dma_address);
+
+ 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;
+ DBG("buffer = %p, length = %d\n", buffer, sg->length);
+
+ data->bytes_xfered += sg->length;
+
+ len = sg->length / 4;
+
+ for (index = 0; index < len; index++) {
+ buffer[index] = swab32(buffer[index]);
+ }
+ 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);
+ else {
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ }
+
+ DBG("post dma read done\n");
+}
+
+/*
+ * Handle transmitted data
+ */
+static void at91_mci_handle_transmitted(struct at91mci_host *host)
+{
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ DBG("Handling the transmit\n");
+
+ /* Disable the transfer */
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+ /* Now wait for cmd ready */
+ at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
+ cmd = host->cmd;
+ if (!cmd) return;
+
+ data = cmd->data;
+ if (!data) return;
+
+ data->bytes_xfered = host->total_length;
+}
+
+/*
+ * Enable the controller
+ */
+static void at91_mci_enable(void)
+{
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+ at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
+ at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+ at91_mci_write(AT91_MCI_MR, 0x834A);
+ at91_mci_write(AT91_MCI_SDCR, 0x0);
+}
+
+/*
+ * Disable the controller
+ */
+static void at91_mci_disable(void)
+{
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+}
+
+/*
+ * Send a command
+ * return the interrupts to enable
+ */
+static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+ unsigned int cmdr, mr;
+ unsigned int block_length;
+ struct mmc_data *data = cmd->data;
+
+ unsigned int blocks;
+ unsigned int ier = 0;
+
+ host->cmd = cmd;
+
+ /* Not sure if this is needed */
+#if 0
+ if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+ DBG("Clearing timeout\n");
+ at91_mci_write(AT91_MCI_ARGR, 0);
+ at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+ while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+ /* spin */
+ DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+ }
+ }
+#endif
+ cmdr = cmd->opcode;
+
+ if (mmc_resp_type(cmd) == MMC_RSP_NONE)
+ cmdr |= AT91_MCI_RSPTYP_NONE;
+ else {
+ /* if a response is expected then allow maximum response latancy */
+ cmdr |= AT91_MCI_MAXLAT;
+ /* set 136 bit response for R2, 48 bit response otherwise */
+ if (mmc_resp_type(cmd) == MMC_RSP_R2)
+ cmdr |= AT91_MCI_RSPTYP_136;
+ else
+ cmdr |= AT91_MCI_RSPTYP_48;
+ }
+
+ if (data) {
+ block_length = 1 << data->blksz_bits;
+ blocks = data->blocks;
+
+ /* always set data start - also set direction flag for read */
+ if (data->flags & MMC_DATA_READ)
+ cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
+ else if (data->flags & MMC_DATA_WRITE)
+ cmdr |= AT91_MCI_TRCMD_START;
+
+ if (data->flags & MMC_DATA_STREAM)
+ cmdr |= AT91_MCI_TRTYP_STREAM;
+ if (data->flags & MMC_DATA_MULTI)
+ cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+ }
+ else {
+ block_length = 0;
+ blocks = 0;
+ }
+
+ if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ cmdr |= AT91_MCI_TRCMD_STOP;
+
+ if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ cmdr |= AT91_MCI_OPDCMD;
+
+ /*
+ * Set the arguments and send the command
+ */
+ DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
+ cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+
+ if (!data) {
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
+ at91_mci_write(AT91_PDC_RPR, 0);
+ at91_mci_write(AT91_PDC_RCR, 0);
+ at91_mci_write(AT91_PDC_RNPR, 0);
+ at91_mci_write(AT91_PDC_RNCR, 0);
+ at91_mci_write(AT91_PDC_TPR, 0);
+ at91_mci_write(AT91_PDC_TCR, 0);
+ at91_mci_write(AT91_PDC_TNPR, 0);
+ at91_mci_write(AT91_PDC_TNCR, 0);
+
+ at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+ at91_mci_write(AT91_MCI_CMDR, cmdr);
+ return AT91_MCI_CMDRDY;
+ }
+
+ mr = at91_mci_read(AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
+ at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+
+ /*
+ * Disable the PDC controller
+ */
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_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);
+
+ DBG("Transmitting %d bytes\n", host->total_length);
+
+ at91_mci_write(AT91_PDC_TPR, host->physical_address);
+ at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+ ier = AT91_MCI_TXBUFE;
+ }
+ }
+
+ /*
+ * Send the command and then enable the PDC - not the other way round as
+ * the data sheet says
+ */
+
+ at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+ at91_mci_write(AT91_MCI_CMDR, cmdr);
+
+ if (cmdr & AT91_MCI_TRCMD_START) {
+ if (cmdr & AT91_MCI_TRDIR)
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+ else
+ at91_mci_write(AT91_PDC_PTCR, AT91_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);
+
+ DBG("setting ier to %08X\n", ier);
+
+ /* Stop on errors or the required value */
+ at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+}
+
+/*
+ * Process the next step in the request
+ */
+static void at91mci_process_next(struct at91mci_host *host)
+{
+ if (!(host->flags & FL_SENT_COMMAND)) {
+ host->flags |= FL_SENT_COMMAND;
+ at91mci_process_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);
+ }
+ else
+ mmc_request_done(host->mmc, host->request);
+}
+
+/*
+ * Handle a command that has been completed
+ */
+static void at91mci_completed_command(struct at91mci_host *host)
+{
+ struct mmc_command *cmd = host->cmd;
+ unsigned int status;
+
+ at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+
+ cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
+ cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
+ cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
+ cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+
+ if (host->buffer) {
+ dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+ host->buffer = NULL;
+ }
+
+ status = at91_mci_read(AT91_MCI_SR);
+
+ DBG("Status = %08X [%08X %08X %08X %08X]\n",
+ status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+ 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))) {
+ cmd->error = MMC_ERR_NONE;
+ }
+ else {
+ if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
+ cmd->error = MMC_ERR_TIMEOUT;
+ else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
+ cmd->error = MMC_ERR_BADCRC;
+ else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
+ cmd->error = MMC_ERR_FIFO;
+ else
+ cmd->error = MMC_ERR_FAILED;
+
+ DBG("Error detected and set to %d (cmd = %d, retries = %d)\n",
+ cmd->error, cmd->opcode, cmd->retries);
+ }
+ }
+ else
+ cmd->error = MMC_ERR_NONE;
+
+ at91mci_process_next(host);
+}
+
+/*
+ * Handle an MMC request
+ */
+static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct at91mci_host *host = mmc_priv(mmc);
+ host->request = mrq;
+ host->flags = 0;
+
+ at91mci_process_next(host);
+}
+
+/*
+ * Set the IOS
+ */
+static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ int clkdiv;
+ struct at91mci_host *host = mmc_priv(mmc);
+ unsigned long at91_master_clock = clk_get_rate(mci_clk);
+
+ DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n",
+ ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+ if (host)
+ host->bus_mode = ios->bus_mode;
+ else
+ printk("MMC: No host for bus_mode\n");
+
+ if (ios->clock == 0) {
+ /* Disable the MCI controller */
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+ clkdiv = 0;
+ }
+ else {
+ /* Enable the MCI controller */
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+
+ if ((at91_master_clock % (ios->clock * 2)) == 0)
+ clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
+ else
+ clkdiv = (at91_master_clock / ios->clock) / 2;
+
+ DBG("clkdiv = %d. mcck = %ld\n", clkdiv,
+ at91_master_clock / (2 * (clkdiv + 1)));
+ }
+ if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
+ DBG("MMC: Setting controller bus width to 4\n");
+ at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+ }
+ else {
+ DBG("MMC: Setting controller bus width to 1\n");
+ at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+ }
+
+ /* Set the clock divider */
+ at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+
+ /* maybe switch power to the card */
+ if (host && host->board->vcc_pin) {
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ at91_set_gpio_output(host->board->vcc_pin, 0);
+ break;
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ at91_set_gpio_output(host->board->vcc_pin, 1);
+ break;
+ }
+ }
+}
+
+/*
+ * Handle an interrupt
+ */
+static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+ struct at91mci_host *host = devid;
+ int completed = 0;
+
+ unsigned int int_status;
+
+ if (host == NULL)
+ return IRQ_HANDLED;
+
+ int_status = at91_mci_read(AT91_MCI_SR);
+ DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
+ int_status & at91_mci_read(AT91_MCI_IMR));
+
+ if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+ completed = 1;
+
+ int_status &= at91_mci_read(AT91_MCI_IMR);
+
+ if (int_status & AT91_MCI_UNRE)
+ DBG("MMC: Underrun error\n");
+ if (int_status & AT91_MCI_OVRE)
+ DBG("MMC: Overrun error\n");
+ if (int_status & AT91_MCI_DTOE)
+ DBG("MMC: Data timeout\n");
+ if (int_status & AT91_MCI_DCRCE)
+ DBG("MMC: CRC error in data\n");
+ if (int_status & AT91_MCI_RTOE)
+ DBG("MMC: Response timeout\n");
+ if (int_status & AT91_MCI_RENDE)
+ DBG("MMC: Response end bit error\n");
+ if (int_status & AT91_MCI_RCRCE)
+ DBG("MMC: Response CRC error\n");
+ if (int_status & AT91_MCI_RDIRE)
+ DBG("MMC: Response direction error\n");
+ if (int_status & AT91_MCI_RINDE)
+ DBG("MMC: Response index error\n");
+
+ /* Only continue processing if no errors */
+ if (!completed) {
+ if (int_status & AT91_MCI_TXBUFE) {
+ DBG("TX buffer empty\n");
+ at91_mci_handle_transmitted(host);
+ }
+
+ if (int_status & AT91_MCI_RXBUFF) {
+ DBG("RX buffer full\n");
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+ }
+
+ if (int_status & AT91_MCI_ENDTX) {
+ DBG("Transmit has ended\n");
+ }
+
+ if (int_status & AT91_MCI_ENDRX) {
+ DBG("Receive has ended\n");
+ at91mci_post_dma_read(host);
+ }
+
+ if (int_status & AT91_MCI_NOTBUSY) {
+ DBG("Card is ready\n");
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+ }
+
+ if (int_status & AT91_MCI_DTIP) {
+ DBG("Data transfer in progress\n");
+ }
+
+ if (int_status & AT91_MCI_BLKE) {
+ DBG("Block transfer has ended\n");
+ }
+
+ if (int_status & AT91_MCI_TXRDY) {
+ DBG("Ready to transmit\n");
+ }
+
+ if (int_status & AT91_MCI_RXRDY) {
+ DBG("Ready to receive\n");
+ }
+
+ if (int_status & AT91_MCI_CMDRDY) {
+ DBG("Command ready\n");
+ completed = 1;
+ }
+ }
+ at91_mci_write(AT91_MCI_IDR, int_status);
+
+ if (completed) {
+ DBG("Completed command\n");
+ at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+ at91mci_completed_command(host);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs)
+{
+ struct at91mci_host *host = _host;
+ int present = !at91_get_gpio_value(irq);
+
+ /*
+ * we expect this irq on both insert and remove,
+ * and use a short delay to debounce.
+ */
+ if (present != host->present) {
+ host->present = present;
+ DBG("%s: card %s\n", mmc_hostname(host->mmc),
+ present ? "insert" : "remove");
+ if (!present) {
+ DBG("****** Resetting SD-card bus width ******\n");
+ at91_mci_write(AT91_MCI_SDCR, 0);
+ }
+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+ }
+ return IRQ_HANDLED;
+}
+
+int at91_mci_get_ro(struct mmc_host *mmc)
+{
+ int read_only = 0;
+ struct at91mci_host *host = mmc_priv(mmc);
+
+ if (host->board->wp_pin) {
+ read_only = at91_get_gpio_value(host->board->wp_pin);
+ printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
+ (read_only ? "read-only" : "read-write") );
+ }
+ else {
+ printk(KERN_WARNING "%s: host does not support reading read-only "
+ "switch. Assuming write-enable.\n", mmc_hostname(mmc));
+ }
+ return read_only;
+}
+
+static struct mmc_host_ops at91_mci_ops = {
+ .request = at91_mci_request,
+ .set_ios = at91_mci_set_ios,
+ .get_ro = at91_mci_get_ro,
+};
+
+/*
+ * Probe for the device
+ */
+static int at91_mci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct at91mci_host *host;
+ int ret;
+
+ DBG("Probe MCI devices\n");
+ at91_mci_disable();
+ at91_mci_enable();
+
+ mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
+ if (!mmc) {
+ DBG("Failed to allocate mmc host\n");
+ return -ENOMEM;
+ }
+
+ mmc->ops = &at91_mci_ops;
+ mmc->f_min = 375000;
+ mmc->f_max = 25000000;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->buffer = NULL;
+ 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("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+#endif
+ }
+
+ /*
+ * Get Clock
+ */
+ mci_clk = clk_get(&pdev->dev, "mci_clk");
+ if (!mci_clk) {
+ printk(KERN_ERR "AT91 MMC: no clock defined.\n");
+ return -ENODEV;
+ }
+ clk_enable(mci_clk); /* Enable the peripheral clock */
+
+ /*
+ * Allocate the MCI interrupt
+ */
+ ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host);
+ if (ret) {
+ DBG("Failed to request MCI interrupt\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, mmc);
+
+ /*
+ * Add host to MMC layer
+ */
+ if (host->board->det_pin)
+ host->present = !at91_get_gpio_value(host->board->det_pin);
+ else
+ host->present = -1;
+
+ mmc_add_host(mmc);
+
+ /*
+ * monitor card insertion/removal if we can
+ */
+ if (host->board->det_pin) {
+ ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
+ SA_SAMPLE_RANDOM, DRIVER_NAME, host);
+ if (ret)
+ DBG("couldn't allocate MMC detect irq\n");
+ }
+
+ DBG(KERN_INFO "Added MCI driver\n");
+
+ return 0;
+}
+
+/*
+ * Remove a device
+ */
+static int at91_mci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct at91mci_host *host;
+
+ if (!mmc)
+ return -1;
+
+ host = mmc_priv(mmc);
+
+ if (host->present != -1) {
+ free_irq(host->board->det_pin, host);
+ cancel_delayed_work(&host->mmc->detect);
+ }
+
+ mmc_remove_host(mmc);
+ at91_mci_disable();
+ free_irq(AT91_ID_MCI, host);
+ mmc_free_host(mmc);
+
+ clk_disable(mci_clk); /* Disable the peripheral clock */
+ clk_put(mci_clk);
+
+ platform_set_drvdata(pdev, NULL);
+
+ DBG("Removed\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_suspend_host(mmc, state);
+
+ return ret;
+}
+
+static int at91_mci_resume(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_resume_host(mmc);
+
+ return ret;
+}
+#else
+#define at91_mci_suspend NULL
+#define at91_mci_resume NULL
+#endif
+
+static struct platform_driver at91_mci_driver = {
+ .probe = at91_mci_probe,
+ .remove = at91_mci_remove,
+ .suspend = at91_mci_suspend,
+ .resume = at91_mci_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91_mci_init(void)
+{
+ return platform_driver_register(&at91_mci_driver);
+}
+
+static void __exit at91_mci_exit(void)
+{
+ platform_driver_unregister(&at91_mci_driver);
+}
+
+module_init(at91_mci_init);
+module_exit(at91_mci_exit);
+
+MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
+MODULE_AUTHOR("Nick Randell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
new file mode 100644
index 000000000000..ffb7f55d3467
--- /dev/null
+++ b/drivers/mmc/imxmmc.c
@@ -0,0 +1,1096 @@
+/*
+ * linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
+ *
+ * Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
+ * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ * derived from pxamci.c by Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Changed to conform redesigned i.MX scatter gather DMA interface
+ *
+ * 2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Updated for 2.6.14 kernel
+ *
+ * 2005-12-13 Jay Monkman <jtm@smoothsmoothie.com>
+ * Found and corrected problems in the write path
+ *
+ * 2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * The event handling rewritten right way in softirq.
+ * Added many ugly hacks and delays to overcome SDHC
+ * deficiencies
+ *
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/protocol.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/imx-dma.h>
+
+#include "imxmmc.h"
+
+#define DRIVER_NAME "imx-mmc"
+
+#define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \
+ INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \
+ INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO)
+
+struct imxmci_host {
+ struct mmc_host *mmc;
+ spinlock_t lock;
+ struct resource *res;
+ int irq;
+ imx_dmach_t dma;
+ unsigned int clkrt;
+ unsigned int cmdat;
+ volatile unsigned int imask;
+ unsigned int power_mode;
+ unsigned int present;
+ struct imxmmc_platform_data *pdata;
+
+ struct mmc_request *req;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ struct timer_list timer;
+ struct tasklet_struct tasklet;
+ unsigned int status_reg;
+ unsigned long pending_events;
+ /* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */
+ u16 *data_ptr;
+ unsigned int data_cnt;
+ atomic_t stuck_timeout;
+
+ unsigned int dma_nents;
+ unsigned int dma_size;
+ unsigned int dma_dir;
+ int dma_allocated;
+
+ unsigned char actual_bus_width;
+};
+
+#define IMXMCI_PEND_IRQ_b 0
+#define IMXMCI_PEND_DMA_END_b 1
+#define IMXMCI_PEND_DMA_ERR_b 2
+#define IMXMCI_PEND_WAIT_RESP_b 3
+#define IMXMCI_PEND_DMA_DATA_b 4
+#define IMXMCI_PEND_CPU_DATA_b 5
+#define IMXMCI_PEND_CARD_XCHG_b 6
+#define IMXMCI_PEND_SET_INIT_b 7
+
+#define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b)
+#define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b)
+#define IMXMCI_PEND_DMA_ERR_m (1 << IMXMCI_PEND_DMA_ERR_b)
+#define IMXMCI_PEND_WAIT_RESP_m (1 << IMXMCI_PEND_WAIT_RESP_b)
+#define IMXMCI_PEND_DMA_DATA_m (1 << IMXMCI_PEND_DMA_DATA_b)
+#define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b)
+#define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b)
+#define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b)
+
+static void imxmci_stop_clock(struct imxmci_host *host)
+{
+ int i = 0;
+ MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK;
+ while(i < 0x1000) {
+ if(!(i & 0x7f))
+ MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK;
+
+ if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) {
+ /* Check twice before cut */
+ if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN))
+ return;
+ }
+
+ i++;
+ }
+ dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
+}
+
+static void imxmci_start_clock(struct imxmci_host *host)
+{
+ int i = 0;
+ MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
+ while(i < 0x1000) {
+ if(!(i & 0x7f))
+ MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+ if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) {
+ /* Check twice before cut */
+ if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+ return;
+ }
+
+ i++;
+ }
+ dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+}
+
+static void imxmci_softreset(void)
+{
+ /* reset sequence */
+ MMC_STR_STP_CLK = 0x8;
+ MMC_STR_STP_CLK = 0xD;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+
+ MMC_RES_TO = 0xff;
+ MMC_BLK_LEN = 512;
+ MMC_NOB = 1;
+}
+
+static int imxmci_busy_wait_for_status(struct imxmci_host *host,
+ unsigned int *pstat, unsigned int stat_mask,
+ int timeout, const char *where)
+{
+ int loops=0;
+ while(!(*pstat & stat_mask)) {
+ loops+=2;
+ if(loops >= timeout) {
+ dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n",
+ where, *pstat, stat_mask);
+ return -1;
+ }
+ udelay(2);
+ *pstat |= MMC_STATUS;
+ }
+ if(!loops)
+ return 0;
+
+ dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
+ loops, where, *pstat, stat_mask);
+ return loops;
+}
+
+static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
+{
+ unsigned int nob = data->blocks;
+ unsigned int blksz = 1 << data->blksz_bits;
+ unsigned int datasz = nob * blksz;
+ int i;
+
+ if (data->flags & MMC_DATA_STREAM)
+ nob = 0xffff;
+
+ host->data = data;
+ data->bytes_xfered = 0;
+
+ MMC_NOB = nob;
+ MMC_BLK_LEN = blksz;
+
+ /*
+ * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise.
+ * We are in big troubles for non-512 byte transfers according to note in the paragraph
+ * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least.
+ * The situation is even more complex in reality. The SDHC in not able to handle wll
+ * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
+ * This is required for SCR read at least.
+ */
+ if (datasz < 64) {
+ host->dma_size = datasz;
+ if (data->flags & MMC_DATA_READ) {
+ host->dma_dir = DMA_FROM_DEVICE;
+
+ /* Hack to enable read SCR */
+ if(datasz < 16) {
+ MMC_NOB = 1;
+ MMC_BLK_LEN = 16;
+ }
+ } else {
+ host->dma_dir = DMA_TO_DEVICE;
+ }
+
+ /* Convert back to virtual address */
+ host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
+ host->data_cnt = 0;
+
+ clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+ set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+ return;
+ }
+
+ if (data->flags & MMC_DATA_READ) {
+ host->dma_dir = DMA_FROM_DEVICE;
+ host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+
+ imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+ host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ);
+
+ /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/
+ CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN;
+ } else {
+ host->dma_dir = DMA_TO_DEVICE;
+
+ host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+
+ imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+ host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE);
+
+ /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/
+ CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN;
+ }
+
+#if 1 /* This code is there only for consistency checking and can be disabled in future */
+ host->dma_size = 0;
+ for(i=0; i<host->dma_nents; i++)
+ host->dma_size+=data->sg[i].length;
+
+ if (datasz > host->dma_size) {
+ dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n",
+ datasz, host->dma_size);
+ }
+#endif
+
+ host->dma_size = datasz;
+
+ wmb();
+
+ if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+ BLR(host->dma) = 0; /* burst 64 byte read / 64 bytes write */
+ else
+ BLR(host->dma) = 16; /* burst 16 byte read / 16 bytes write */
+
+ RSSR(host->dma) = DMA_REQ_SDHC;
+
+ set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+ clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+ /* start DMA engine for read, write is delayed after initial response */
+ if (host->dma_dir == DMA_FROM_DEVICE) {
+ imx_dma_enable(host->dma);
+ }
+}
+
+static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+ unsigned long flags;
+ u32 imask;
+
+ WARN_ON(host->cmd != NULL);
+ host->cmd = cmd;
+
+ if (cmd->flags & MMC_RSP_BUSY)
+ cmdat |= CMD_DAT_CONT_BUSY;
+
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_R1: /* short CRC, OPCODE */
+ case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
+ break;
+ case MMC_RSP_R2: /* long 136 bit + CRC */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
+ break;
+ case MMC_RSP_R3: /* short */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
+ break;
+ case MMC_RSP_R6: /* short CRC */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6;
+ break;
+ default:
+ break;
+ }
+
+ if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
+ cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */
+
+ if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
+ cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+
+ MMC_CMD = cmd->opcode;
+ MMC_ARGH = cmd->arg >> 16;
+ MMC_ARGL = cmd->arg & 0xffff;
+ MMC_CMD_DAT_CONT = cmdat;
+
+ atomic_set(&host->stuck_timeout, 0);
+ set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);
+
+
+ imask = IMXMCI_INT_MASK_DEFAULT;
+ imask &= ~INT_MASK_END_CMD_RES;
+ if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
+ /*imask &= ~INT_MASK_BUF_READY;*/
+ imask &= ~INT_MASK_DATA_TRAN;
+ if ( cmdat & CMD_DAT_CONT_WRITE )
+ imask &= ~INT_MASK_WRITE_OP_DONE;
+ if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+ imask &= ~INT_MASK_BUF_READY;
+ }
+
+ spin_lock_irqsave(&host->lock, flags);
+ host->imask = imask;
+ MMC_INT_MASK = host->imask;
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
+ cmd->opcode, cmd->opcode, imask);
+
+ imxmci_start_clock(host);
+}
+
+static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m |
+ IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m);
+
+ host->imask = IMXMCI_INT_MASK_DEFAULT;
+ MMC_INT_MASK = host->imask;
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ host->req = NULL;
+ host->cmd = NULL;
+ host->data = NULL;
+ mmc_request_done(host->mmc, req);
+}
+
+static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+ int data_error;
+
+ if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){
+ imx_dma_disable(host->dma);
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+ host->dma_dir);
+ }
+
+ if ( stat & STATUS_ERR_MASK ) {
+ dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat);
+ if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR))
+ data->error = MMC_ERR_BADCRC;
+ else if(stat & STATUS_TIME_OUT_READ)
+ data->error = MMC_ERR_TIMEOUT;
+ else
+ data->error = MMC_ERR_FAILED;
+ } else {
+ data->bytes_xfered = host->dma_size;
+ }
+
+ data_error = data->error;
+
+ host->data = NULL;
+
+ return data_error;
+}
+
+static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat)
+{
+ struct mmc_command *cmd = host->cmd;
+ int i;
+ u32 a,b,c;
+ struct mmc_data *data = host->data;
+
+ if (!cmd)
+ return 0;
+
+ host->cmd = NULL;
+
+ if (stat & STATUS_TIME_OUT_RESP) {
+ dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
+ cmd->error = MMC_ERR_TIMEOUT;
+ } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+ dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
+ cmd->error = MMC_ERR_BADCRC;
+ }
+
+ if(cmd->flags & MMC_RSP_PRESENT) {
+ if(cmd->flags & MMC_RSP_136) {
+ for (i = 0; i < 4; i++) {
+ u32 a = MMC_RES_FIFO & 0xffff;
+ u32 b = MMC_RES_FIFO & 0xffff;
+ cmd->resp[i] = a<<16 | b;
+ }
+ } else {
+ a = MMC_RES_FIFO & 0xffff;
+ b = MMC_RES_FIFO & 0xffff;
+ c = MMC_RES_FIFO & 0xffff;
+ cmd->resp[0] = a<<24 | b<<8 | c>>8;
+ }
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n",
+ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
+
+ if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) {
+ if (host->req->data->flags & MMC_DATA_WRITE) {
+
+ /* Wait for FIFO to be empty before starting DMA write */
+
+ stat = MMC_STATUS;
+ if(imxmci_busy_wait_for_status(host, &stat,
+ STATUS_APPL_BUFF_FE,
+ 40, "imxmci_cmd_done DMA WR") < 0) {
+ cmd->error = MMC_ERR_FIFO;
+ imxmci_finish_data(host, stat);
+ if(host->req)
+ imxmci_finish_request(host, host->req);
+ dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n",
+ stat);
+ return 0;
+ }
+
+ if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+ imx_dma_enable(host->dma);
+ }
+ }
+ } else {
+ struct mmc_request *req;
+ imxmci_stop_clock(host);
+ req = host->req;
+
+ if(data)
+ imxmci_finish_data(host, stat);
+
+ if( req ) {
+ imxmci_finish_request(host, req);
+ } else {
+ dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n");
+ }
+ }
+
+ return 1;
+}
+
+static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+ int data_error;
+
+ if (!data)
+ return 0;
+
+ data_error = imxmci_finish_data(host, stat);
+
+ if (host->req->stop && (data_error == MMC_ERR_NONE)) {
+ imxmci_stop_clock(host);
+ imxmci_start_cmd(host, host->req->stop, 0);
+ } else {
+ struct mmc_request *req;
+ req = host->req;
+ if( req ) {
+ imxmci_finish_request(host, req);
+ } else {
+ dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n");
+ }
+ }
+
+ return 1;
+}
+
+static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
+{
+ int i;
+ int burst_len;
+ int flush_len;
+ int trans_done = 0;
+ unsigned int stat = *pstat;
+
+ if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+ burst_len = 16;
+ else
+ burst_len = 64;
+
+ /* This is unfortunately required */
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
+ stat);
+
+ if(host->dma_dir == DMA_FROM_DEVICE) {
+ imxmci_busy_wait_for_status(host, &stat,
+ STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
+ 20, "imxmci_cpu_driven_data read");
+
+ while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) &&
+ (host->data_cnt < host->dma_size)) {
+ if(burst_len >= host->dma_size - host->data_cnt) {
+ flush_len = burst_len;
+ burst_len = host->dma_size - host->data_cnt;
+ flush_len -= burst_len;
+ host->data_cnt = host->dma_size;
+ trans_done = 1;
+ } else {
+ flush_len = 0;
+ host->data_cnt += burst_len;
+ }
+
+ for(i = burst_len; i>=2 ; i-=2) {
+ *(host->data_ptr++) = MMC_BUFFER_ACCESS;
+ udelay(20); /* required for clocks < 8MHz*/
+ }
+
+ if(i == 1)
+ *(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS;
+
+ stat = MMC_STATUS;
+
+ /* Flush extra bytes from FIFO */
+ while(flush_len >= 2){
+ flush_len -= 2;
+ i = MMC_BUFFER_ACCESS;
+ stat = MMC_STATUS;
+ stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n",
+ burst_len, stat);
+ }
+ } else {
+ imxmci_busy_wait_for_status(host, &stat,
+ STATUS_APPL_BUFF_FE,
+ 20, "imxmci_cpu_driven_data write");
+
+ while((stat & STATUS_APPL_BUFF_FE) &&
+ (host->data_cnt < host->dma_size)) {
+ if(burst_len >= host->dma_size - host->data_cnt) {
+ burst_len = host->dma_size - host->data_cnt;
+ host->data_cnt = host->dma_size;
+ trans_done = 1;
+ } else {
+ host->data_cnt += burst_len;
+ }
+
+ for(i = burst_len; i>0 ; i-=2)
+ MMC_BUFFER_ACCESS = *(host->data_ptr++);
+
+ stat = MMC_STATUS;
+
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n",
+ burst_len, stat);
+ }
+ }
+
+ *pstat = stat;
+
+ return trans_done;
+}
+
+static void imxmci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+{
+ struct imxmci_host *host = devid;
+ uint32_t stat = MMC_STATUS;
+
+ atomic_set(&host->stuck_timeout, 0);
+ host->status_reg = stat;
+ set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+ tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+ struct imxmci_host *host = devid;
+ uint32_t stat = MMC_STATUS;
+ int handled = 1;
+
+ MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT;
+
+ atomic_set(&host->stuck_timeout, 0);
+ host->status_reg = stat;
+ set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+ tasklet_schedule(&host->tasklet);
+
+ return IRQ_RETVAL(handled);;
+}
+
+static void imxmci_tasklet_fnc(unsigned long data)
+{
+ struct imxmci_host *host = (struct imxmci_host *)data;
+ u32 stat;
+ unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */
+ int timeout = 0;
+
+ if(atomic_read(&host->stuck_timeout) > 4) {
+ char *what;
+ timeout = 1;
+ stat = MMC_STATUS;
+ host->status_reg = stat;
+ if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+ if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+ what = "RESP+DMA";
+ else
+ what = "RESP";
+ else
+ if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+ if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
+ what = "DATA";
+ else
+ what = "DMA";
+ else
+ what = "???";
+
+ dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
+ what, stat, MMC_INT_MASK);
+ dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
+ MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
+ dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n",
+ host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size);
+ }
+
+ if(!host->present || timeout)
+ host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
+ STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;
+
+ if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
+ clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+
+ stat = MMC_STATUS;
+ /*
+ * This is not required in theory, but there is chance to miss some flag
+ * which clears automatically by mask write, FreeScale original code keeps
+ * stat from IRQ time so do I
+ */
+ stat |= host->status_reg;
+
+ if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+ imxmci_busy_wait_for_status(host, &stat,
+ STATUS_END_CMD_RESP | STATUS_ERR_MASK,
+ 20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
+ }
+
+ if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
+ if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+ imxmci_cmd_done(host, stat);
+ if(host->data && (stat & STATUS_ERR_MASK))
+ imxmci_data_done(host, stat);
+ }
+
+ if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
+ stat |= MMC_STATUS;
+ if(imxmci_cpu_driven_data(host, &stat)){
+ if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+ imxmci_cmd_done(host, stat);
+ atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
+ &host->pending_events);
+ imxmci_data_done(host, stat);
+ }
+ }
+ }
+
+ if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
+ !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+
+ stat = MMC_STATUS;
+ /* Same as above */
+ stat |= host->status_reg;
+
+ if(host->dma_dir == DMA_TO_DEVICE) {
+ data_dir_mask = STATUS_WRITE_OP_DONE;
+ } else {
+ data_dir_mask = STATUS_DATA_TRANS_DONE;
+ }
+
+ imxmci_busy_wait_for_status(host, &stat,
+ data_dir_mask,
+ 50, "imxmci_tasklet_fnc data");
+
+ if(stat & data_dir_mask) {
+ clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+ imxmci_data_done(host, stat);
+ }
+ }
+
+ if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {
+
+ if(host->cmd)
+ imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);
+
+ if(host->data)
+ imxmci_data_done(host, STATUS_TIME_OUT_READ |
+ STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);
+
+ if(host->req)
+ imxmci_finish_request(host, host->req);
+
+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+
+ }
+}
+
+static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+ struct imxmci_host *host = mmc_priv(mmc);
+ unsigned int cmdat;
+
+ WARN_ON(host->req != NULL);
+
+ host->req = req;
+
+ cmdat = 0;
+
+ if (req->data) {
+ imxmci_setup_data(host, req->data);
+
+ cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+ if (req->data->flags & MMC_DATA_WRITE)
+ cmdat |= CMD_DAT_CONT_WRITE;
+
+ if (req->data->flags & MMC_DATA_STREAM) {
+ cmdat |= CMD_DAT_CONT_STREAM_BLOCK;
+ }
+ }
+
+ imxmci_start_cmd(host, req->cmd, cmdat);
+}
+
+#define CLK_RATE 19200000
+
+static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct imxmci_host *host = mmc_priv(mmc);
+ int prescaler;
+
+ dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n",
+ ios->clock, ios->power_mode, ios->vdd,
+ (ios->bus_width==MMC_BUS_WIDTH_4)?4:1);
+
+ if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
+ host->actual_bus_width = MMC_BUS_WIDTH_4;
+ imx_gpio_mode(PB11_PF_SD_DAT3);
+ }else{
+ host->actual_bus_width = MMC_BUS_WIDTH_1;
+ imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+ }
+
+ if ( host->power_mode != ios->power_mode ) {
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ break;
+ case MMC_POWER_UP:
+ set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+ break;
+ case MMC_POWER_ON:
+ break;
+ }
+ host->power_mode = ios->power_mode;
+ }
+
+ if ( ios->clock ) {
+ unsigned int clk;
+
+ /* The prescaler is 5 for PERCLK2 equal to 96MHz
+ * then 96MHz / 5 = 19.2 MHz
+ */
+ clk=imx_get_perclk2();
+ prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE;
+ switch(prescaler) {
+ case 0:
+ case 1: prescaler = 0;
+ break;
+ case 2: prescaler = 1;
+ break;
+ case 3: prescaler = 2;
+ break;
+ case 4: prescaler = 4;
+ break;
+ default:
+ case 5: prescaler = 5;
+ break;
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n",
+ clk, prescaler);
+
+ for(clk=0; clk<8; clk++) {
+ int x;
+ x = CLK_RATE / (1<<clk);
+ if( x <= ios->clock)
+ break;
+ }
+
+ MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */
+
+ imxmci_stop_clock(host);
+ MMC_CLK_RATE = (prescaler<<3) | clk;
+ imxmci_start_clock(host);
+
+ dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
+ } else {
+ imxmci_stop_clock(host);
+ }
+}
+
+static struct mmc_host_ops imxmci_ops = {
+ .request = imxmci_request,
+ .set_ios = imxmci_set_ios,
+};
+
+static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
+{
+ int i;
+
+ for (i = 0; i < dev->num_resources; i++)
+ if (dev->resource[i].flags == mask && nr-- == 0)
+ return &dev->resource[i];
+ return NULL;
+}
+
+static int platform_device_irq(struct platform_device *dev, int nr)
+{
+ int i;
+
+ for (i = 0; i < dev->num_resources; i++)
+ if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
+ return dev->resource[i].start;
+ return NO_IRQ;
+}
+
+static void imxmci_check_status(unsigned long data)
+{
+ struct imxmci_host *host = (struct imxmci_host *)data;
+
+ if( host->pdata->card_present() != host->present ) {
+ host->present ^= 1;
+ dev_info(mmc_dev(host->mmc), "card %s\n",
+ host->present ? "inserted" : "removed");
+
+ set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events);
+ tasklet_schedule(&host->tasklet);
+ }
+
+ if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) ||
+ test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+ atomic_inc(&host->stuck_timeout);
+ if(atomic_read(&host->stuck_timeout) > 4)
+ tasklet_schedule(&host->tasklet);
+ } else {
+ atomic_set(&host->stuck_timeout, 0);
+
+ }
+
+ mod_timer(&host->timer, jiffies + (HZ>>1));
+}
+
+static int imxmci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct imxmci_host *host = NULL;
+ struct resource *r;
+ int ret = 0, irq;
+
+ printk(KERN_INFO "i.MX mmc driver\n");
+
+ r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_device_irq(pdev, 0);
+ if (!r || irq == NO_IRQ)
+ return -ENXIO;
+
+ r = request_mem_region(r->start, 0x100, "IMXMCI");
+ if (!r)
+ return -EBUSY;
+
+ mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
+ if (!mmc) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ mmc->ops = &imxmci_ops;
+ mmc->f_min = 150000;
+ mmc->f_max = CLK_RATE/2;
+ mmc->ocr_avail = MMC_VDD_32_33;
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ /* MMC core transfer sizes tunable parameters */
+ mmc->max_hw_segs = 64;
+ mmc->max_phys_segs = 64;
+ mmc->max_sectors = 64; /* default 1 << (PAGE_CACHE_SHIFT - 9) */
+ mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->dma_allocated = 0;
+ host->pdata = pdev->dev.platform_data;
+
+ spin_lock_init(&host->lock);
+ host->res = r;
+ host->irq = irq;
+
+ imx_gpio_mode(PB8_PF_SD_DAT0);
+ imx_gpio_mode(PB9_PF_SD_DAT1);
+ imx_gpio_mode(PB10_PF_SD_DAT2);
+ /* Configured as GPIO with pull-up to ensure right MCC card mode */
+ /* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */
+ imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+ /* imx_gpio_mode(PB11_PF_SD_DAT3); */
+ imx_gpio_mode(PB12_PF_SD_CLK);
+ imx_gpio_mode(PB13_PF_SD_CMD);
+
+ imxmci_softreset();
+
+ if ( MMC_REV_NO != 0x390 ) {
+ dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
+ MMC_REV_NO);
+ goto out;
+ }
+
+ MMC_READ_TO = 0x2db4; /* recommended in data sheet */
+
+ host->imask = IMXMCI_INT_MASK_DEFAULT;
+ MMC_INT_MASK = host->imask;
+
+
+ if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){
+ dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
+ ret = -EBUSY;
+ goto out;
+ }
+ host->dma_allocated=1;
+ imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
+
+ tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
+ host->status_reg=0;
+ host->pending_events=0;
+
+ ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host);
+ if (ret)
+ goto out;
+
+ host->present = host->pdata->card_present();
+ init_timer(&host->timer);
+ host->timer.data = (unsigned long)host;
+ host->timer.function = imxmci_check_status;
+ add_timer(&host->timer);
+ mod_timer(&host->timer, jiffies + (HZ>>1));
+
+ platform_set_drvdata(pdev, mmc);
+
+ mmc_add_host(mmc);
+
+ return 0;
+
+out:
+ if (host) {
+ if(host->dma_allocated){
+ imx_dma_free(host->dma);
+ host->dma_allocated=0;
+ }
+ }
+ if (mmc)
+ mmc_free_host(mmc);
+ release_resource(r);
+ return ret;
+}
+
+static int imxmci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (mmc) {
+ struct imxmci_host *host = mmc_priv(mmc);
+
+ tasklet_disable(&host->tasklet);
+
+ del_timer_sync(&host->timer);
+ mmc_remove_host(mmc);
+
+ free_irq(host->irq, host);
+ if(host->dma_allocated){
+ imx_dma_free(host->dma);
+ host->dma_allocated=0;
+ }
+
+ tasklet_kill(&host->tasklet);
+
+ release_resource(host->res);
+
+ mmc_free_host(mmc);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_suspend_host(mmc, state);
+
+ return ret;
+}
+
+static int imxmci_resume(struct platform_device *dev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct imxmci_host *host;
+ int ret = 0;
+
+ if (mmc) {
+ host = mmc_priv(mmc);
+ if(host)
+ set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+ ret = mmc_resume_host(mmc);
+ }
+
+ return ret;
+}
+#else
+#define imxmci_suspend NULL
+#define imxmci_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver imxmci_driver = {
+ .probe = imxmci_probe,
+ .remove = imxmci_remove,
+ .suspend = imxmci_suspend,
+ .resume = imxmci_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ }
+};
+
+static int __init imxmci_init(void)
+{
+ return platform_driver_register(&imxmci_driver);
+}
+
+static void __exit imxmci_exit(void)
+{
+ platform_driver_unregister(&imxmci_driver);
+}
+
+module_init(imxmci_init);
+module_exit(imxmci_exit);
+
+MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/imxmmc.h
new file mode 100644
index 000000000000..e5339e334dbb
--- /dev/null
+++ b/drivers/mmc/imxmmc.h
@@ -0,0 +1,67 @@
+
+# define __REG16(x) (*((volatile u16 *)IO_ADDRESS(x)))
+
+#define MMC_STR_STP_CLK __REG16(IMX_MMC_BASE + 0x00)
+#define MMC_STATUS __REG16(IMX_MMC_BASE + 0x04)
+#define MMC_CLK_RATE __REG16(IMX_MMC_BASE + 0x08)
+#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C)
+#define MMC_RES_TO __REG16(IMX_MMC_BASE + 0x10)
+#define MMC_READ_TO __REG16(IMX_MMC_BASE + 0x14)
+#define MMC_BLK_LEN __REG16(IMX_MMC_BASE + 0x18)
+#define MMC_NOB __REG16(IMX_MMC_BASE + 0x1C)
+#define MMC_REV_NO __REG16(IMX_MMC_BASE + 0x20)
+#define MMC_INT_MASK __REG16(IMX_MMC_BASE + 0x24)
+#define MMC_CMD __REG16(IMX_MMC_BASE + 0x28)
+#define MMC_ARGH __REG16(IMX_MMC_BASE + 0x2C)
+#define MMC_ARGL __REG16(IMX_MMC_BASE + 0x30)
+#define MMC_RES_FIFO __REG16(IMX_MMC_BASE + 0x34)
+#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38)
+#define MMC_BUFFER_ACCESS_OFS 0x38
+
+
+#define STR_STP_CLK_ENDIAN (1<<5)
+#define STR_STP_CLK_RESET (1<<3)
+#define STR_STP_CLK_ENABLE (1<<2)
+#define STR_STP_CLK_START_CLK (1<<1)
+#define STR_STP_CLK_STOP_CLK (1<<0)
+#define STATUS_CARD_PRESENCE (1<<15)
+#define STATUS_SDIO_INT_ACTIVE (1<<14)
+#define STATUS_END_CMD_RESP (1<<13)
+#define STATUS_WRITE_OP_DONE (1<<12)
+#define STATUS_DATA_TRANS_DONE (1<<11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK (3<<10)
+#define STATUS_CARD_BUS_CLK_RUN (1<<8)
+#define STATUS_APPL_BUFF_FF (1<<7)
+#define STATUS_APPL_BUFF_FE (1<<6)
+#define STATUS_RESP_CRC_ERR (1<<5)
+#define STATUS_CRC_READ_ERR (1<<3)
+#define STATUS_CRC_WRITE_ERR (1<<2)
+#define STATUS_TIME_OUT_RESP (1<<1)
+#define STATUS_TIME_OUT_READ (1<<0)
+#define STATUS_ERR_MASK 0x2f
+#define CLK_RATE_PRESCALER(x) ((x) & 0x7)
+#define CLK_RATE_CLK_RATE(x) (((x) & 0x7) << 3)
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF (1<<12)
+#define CMD_DAT_CONT_STOP_READWAIT (1<<11)
+#define CMD_DAT_CONT_START_READWAIT (1<<10)
+#define CMD_DAT_CONT_BUS_WIDTH_1 (0<<8)
+#define CMD_DAT_CONT_BUS_WIDTH_4 (2<<8)
+#define CMD_DAT_CONT_INIT (1<<7)
+#define CMD_DAT_CONT_BUSY (1<<6)
+#define CMD_DAT_CONT_STREAM_BLOCK (1<<5)
+#define CMD_DAT_CONT_WRITE (1<<4)
+#define CMD_DAT_CONT_DATA_ENABLE (1<<3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6)
+#define INT_MASK_AUTO_CARD_DETECT (1<<6)
+#define INT_MASK_DAT0_EN (1<<5)
+#define INT_MASK_SDIO (1<<4)
+#define INT_MASK_BUF_READY (1<<3)
+#define INT_MASK_END_CMD_RES (1<<2)
+#define INT_MASK_WRITE_OP_DONE (1<<1)
+#define INT_MASK_DATA_TRAN (1<<0)
+#define INT_ALL (0x7f)
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index eb9a8826e9b5..eb42cb349420 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -65,11 +65,6 @@ struct pxamci_host {
unsigned int dma_dir;
};
-static inline unsigned int ns_to_clocks(unsigned int ns)
-{
- return (ns * (CLOCKRATE / 1000000) + 999) / 1000;
-}
-
static void pxamci_stop_clock(struct pxamci_host *host)
{
if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -113,6 +108,7 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
{
unsigned int nob = data->blocks;
+ unsigned long long clks;
unsigned int timeout;
u32 dcmd;
int i;
@@ -125,7 +121,9 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
writel(nob, host->base + MMC_NOB);
writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
- timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks;
+ clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
+ do_div(clks, 1000000000UL);
+ timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
writel((timeout + 255) / 256, host->base + MMC_RDTO);
if (data->flags & MMC_DATA_READ) {
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 0f6bb2e625d8..a7ec5954caf5 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -200,27 +200,6 @@ config MTD_CFI_AMDSTD
provides support for one of those command sets, used on chips
including the AMD Am29LV320.
-config MTD_CFI_AMDSTD_RETRY
- int "Retry failed commands (erase/program)"
- depends on MTD_CFI_AMDSTD
- default "0"
- help
- Some chips, when attached to a shared bus, don't properly filter
- bus traffic that is destined to other devices. This broken
- behavior causes erase and program sequences to be aborted when
- the sequences are mixed with traffic for other devices.
-
- SST49LF040 (and related) chips are know to be broken.
-
-config MTD_CFI_AMDSTD_RETRY_MAX
- int "Max retries of failed commands (erase/program)"
- depends on MTD_CFI_AMDSTD_RETRY
- default "0"
- help
- If you have an SST49LF040 (or related chip) then this value should
- be set to at least 1. This can also be adjusted at driver load
- time with the retry_cmd_max module parameter.
-
config MTD_CFI_STAA
tristate "Support for ST (Advanced Architecture) flash chips"
depends on MTD_GEN_PROBE
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index dd628cb51e31..7fac438b5c32 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -129,8 +129,8 @@ config MTDRAM_ABS_POS
allocating space from Linux's available memory. Otherwise, leave
this set to zero. Most people will want to leave this as zero.
-config MTD_BLKMTD
- tristate "MTD emulation using block device"
+config MTD_BLOCK2MTD
+ tristate "MTD using block device"
depends on MTD
help
This driver allows a block device to appear as an MTD. It would
@@ -141,15 +141,6 @@ config MTD_BLKMTD
Testing MTD users (eg JFFS2) on large media and media that might
be removed during a write (using the floppy drive).
-config MTD_BLOCK2MTD
- tristate "MTD using block device (rewrite)"
- depends on MTD && EXPERIMENTAL
- help
- This driver is basically the same at MTD_BLKMTD above, but
- experienced some interface changes plus serious speedups. In
- the long term, it should replace MTD_BLKMTD. Right now, you
- shouldn't entrust important data to it yet.
-
comment "Disk-On-Chip Device Drivers"
config MTD_DOC2000
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7c5ed2178380..b6573670316f 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_MTD_PMC551) += pmc551.o
obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
obj-$(CONFIG_MTD_LART) += lart.o
-obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
deleted file mode 100644
index 79f2e1f23ebd..000000000000
--- a/drivers/mtd/devices/blkmtd.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/*
- * $Id: blkmtd.c,v 1.27 2005/11/07 11:14:24 gleixner Exp $
- *
- * blkmtd.c - use a block device as a fake MTD
- *
- * Author: Simon Evans <spse@secret.org.uk>
- *
- * Copyright (C) 2001,2002 Simon Evans
- *
- * Licence: GPL
- *
- * How it works:
- * The driver uses raw/io to read/write the device and the page
- * cache to cache access. Writes update the page cache with the
- * new data and mark it dirty and add the page into a BIO which
- * is then written out.
- *
- * It can be loaded Read-Only to prevent erases and writes to the
- * medium.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/pagemap.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/mount.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mutex.h>
-
-#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg)
-#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg)
-
-
-/* Default erase size in K, always make it a multiple of PAGE_SIZE */
-#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
-#define VERSION "$Revision: 1.27 $"
-
-/* Info for the block device */
-struct blkmtd_dev {
- struct list_head list;
- struct block_device *blkdev;
- struct mtd_info mtd_info;
- struct mutex wrbuf_mutex;
-};
-
-
-/* Static info about the MTD, used in cleanup_module */
-static LIST_HEAD(blkmtd_device_list);
-
-
-static void blkmtd_sync(struct mtd_info *mtd);
-
-#define MAX_DEVICES 4
-
-/* Module parameters passed by insmod/modprobe */
-static char *device[MAX_DEVICES]; /* the block device to use */
-static int erasesz[MAX_DEVICES]; /* optional default erase size */
-static int ro[MAX_DEVICES]; /* optional read only flag */
-static int sync;
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
-MODULE_DESCRIPTION("Emulate an MTD using a block device");
-module_param_array(device, charp, NULL, 0);
-MODULE_PARM_DESC(device, "block device to use");
-module_param_array(erasesz, int, NULL, 0);
-MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB.");
-module_param_array(ro, bool, NULL, 0);
-MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors");
-module_param(sync, bool, 0);
-MODULE_PARM_DESC(sync, "1=Synchronous writes");
-
-
-/* completion handler for BIO reads */
-static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error)
-{
- if (bio->bi_size)
- return 1;
-
- complete((struct completion*)bio->bi_private);
- return 0;
-}
-
-
-/* completion handler for BIO writes */
-static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error)
-{
- const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-
- if (bio->bi_size)
- return 1;
-
- if(!uptodate)
- err("bi_write_complete: not uptodate\n");
-
- do {
- struct page *page = bvec->bv_page;
- DEBUG(3, "Cleaning up page %ld\n", page->index);
- if (--bvec >= bio->bi_io_vec)
- prefetchw(&bvec->bv_page->flags);
-
- if (uptodate) {
- SetPageUptodate(page);
- } else {
- ClearPageUptodate(page);
- SetPageError(page);
- }
- clear_page_dirty(page);
- unlock_page(page);
- page_cache_release(page);
- } while (bvec >= bio->bi_io_vec);
-
- complete((struct completion*)bio->bi_private);
- return 0;
-}
-
-
-/* read one page from the block device */
-static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page)
-{
- struct bio *bio;
- struct completion event;
- int err = -ENOMEM;
-
- if(PageUptodate(page)) {
- DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index);
- unlock_page(page);
- return 0;
- }
-
- ClearPageUptodate(page);
- ClearPageError(page);
-
- bio = bio_alloc(GFP_KERNEL, 1);
- if(bio) {
- init_completion(&event);
- bio->bi_bdev = dev->blkdev;
- bio->bi_sector = page->index << (PAGE_SHIFT-9);
- bio->bi_private = &event;
- bio->bi_end_io = bi_read_complete;
- if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) {
- submit_bio(READ_SYNC, bio);
- wait_for_completion(&event);
- err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
- bio_put(bio);
- }
- }
-
- if(err)
- SetPageError(page);
- else
- SetPageUptodate(page);
- flush_dcache_page(page);
- unlock_page(page);
- return err;
-}
-
-
-/* write out the current BIO and wait for it to finish */
-static int blkmtd_write_out(struct bio *bio)
-{
- struct completion event;
- int err;
-
- if(!bio->bi_vcnt) {
- bio_put(bio);
- return 0;
- }
-
- init_completion(&event);
- bio->bi_private = &event;
- bio->bi_end_io = bi_write_complete;
- submit_bio(WRITE_SYNC, bio);
- wait_for_completion(&event);
- DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt);
- err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
- bio_put(bio);
- return err;
-}
-
-
-/**
- * blkmtd_add_page - add a page to the current BIO
- * @bio: bio to add to (NULL to alloc initial bio)
- * @blkdev: block device
- * @page: page to add
- * @pagecnt: pages left to add
- *
- * Adds a page to the current bio, allocating it if necessary. If it cannot be
- * added, the current bio is written out and a new one is allocated. Returns
- * the new bio to add or NULL on error
- */
-static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev,
- struct page *page, int pagecnt)
-{
-
- retry:
- if(!bio) {
- bio = bio_alloc(GFP_KERNEL, pagecnt);
- if(!bio)
- return NULL;
- bio->bi_sector = page->index << (PAGE_SHIFT-9);
- bio->bi_bdev = blkdev;
- }
-
- if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) {
- blkmtd_write_out(bio);
- bio = NULL;
- goto retry;
- }
- return bio;
-}
-
-
-/**
- * write_pages - write block of data to device via the page cache
- * @dev: device to write to
- * @buf: data source or NULL if erase (output is set to 0xff)
- * @to: offset into output device
- * @len: amount to data to write
- * @retlen: amount of data written
- *
- * Grab pages from the page cache and fill them with the source data.
- * Non page aligned start and end result in a readin of the page and
- * part of the page being modified. Pages are added to the bio and then written
- * out.
- */
-static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
- size_t len, size_t *retlen)
-{
- int pagenr, offset;
- size_t start_len = 0, end_len;
- int pagecnt = 0;
- int err = 0;
- struct bio *bio = NULL;
- size_t thislen = 0;
-
- pagenr = to >> PAGE_SHIFT;
- offset = to & ~PAGE_MASK;
-
- DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
- buf, (long)to, len, pagenr, offset);
-
- /* see if we have to do a partial write at the start */
- if(offset) {
- start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
- len -= start_len;
- }
-
- /* calculate the length of the other two regions */
- end_len = len & ~PAGE_MASK;
- len -= end_len;
-
- if(start_len)
- pagecnt++;
-
- if(len)
- pagecnt += len >> PAGE_SHIFT;
-
- if(end_len)
- pagecnt++;
-
- mutex_lock(&dev->wrbuf_mutex);
-
- DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
- start_len, len, end_len, pagecnt);
-
- if(start_len) {
- /* do partial start region */
- struct page *page;
-
- DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
- pagenr, start_len, offset);
-
- BUG_ON(!buf);
- page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
- lock_page(page);
- if(PageDirty(page)) {
- err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
- to, start_len, len, end_len, pagenr);
- BUG();
- }
- memcpy(page_address(page)+offset, buf, start_len);
- set_page_dirty(page);
- SetPageUptodate(page);
- buf += start_len;
- thislen = start_len;
- bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
- if(!bio) {
- err = -ENOMEM;
- err("bio_add_page failed\n");
- goto write_err;
- }
- pagecnt--;
- pagenr++;
- }
-
- /* Now do the main loop to a page aligned, n page sized output */
- if(len) {
- int pagesc = len >> PAGE_SHIFT;
- DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
- pagenr, pagesc);
- while(pagesc) {
- struct page *page;
-
- /* see if page is in the page cache */
- DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr);
- page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr);
- if(PageDirty(page)) {
- BUG();
- }
- if(!page) {
- warn("write: cannot grab cache page %d", pagenr);
- err = -ENOMEM;
- goto write_err;
- }
- if(!buf) {
- memset(page_address(page), 0xff, PAGE_SIZE);
- } else {
- memcpy(page_address(page), buf, PAGE_SIZE);
- buf += PAGE_SIZE;
- }
- bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
- if(!bio) {
- err = -ENOMEM;
- err("bio_add_page failed\n");
- goto write_err;
- }
- pagenr++;
- pagecnt--;
- set_page_dirty(page);
- SetPageUptodate(page);
- pagesc--;
- thislen += PAGE_SIZE;
- }
- }
-
- if(end_len) {
- /* do the third region */
- struct page *page;
- DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
- pagenr, end_len);
- BUG_ON(!buf);
- page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
- lock_page(page);
- if(PageDirty(page)) {
- err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
- to, start_len, len, end_len, pagenr);
- BUG();
- }
- memcpy(page_address(page), buf, end_len);
- set_page_dirty(page);
- SetPageUptodate(page);
- DEBUG(3, "blkmtd: write: writing out partial end\n");
- thislen += end_len;
- bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
- if(!bio) {
- err = -ENOMEM;
- err("bio_add_page failed\n");
- goto write_err;
- }
- pagenr++;
- }
-
- DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt);
- write_err:
- if(bio)
- blkmtd_write_out(bio);
-
- DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
- mutex_unlock(&dev->wrbuf_mutex);
-
- if(retlen)
- *retlen = thislen;
- return err;
-}
-
-
-/* erase a specified part of the device */
-static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
- struct blkmtd_dev *dev = mtd->priv;
- struct mtd_erase_region_info *einfo = mtd->eraseregions;
- int numregions = mtd->numeraseregions;
- size_t from;
- u_long len;
- int err = -EIO;
- size_t retlen;
-
- instr->state = MTD_ERASING;
- from = instr->addr;
- len = instr->len;
-
- /* check erase region has valid start and length */
- DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
- mtd->name+9, from, len);
- while(numregions) {
- DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
- einfo->offset, einfo->erasesize, einfo->numblocks);
- if(from >= einfo->offset
- && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) {
- if(len == einfo->erasesize
- && ( (from - einfo->offset) % einfo->erasesize == 0))
- break;
- }
- numregions--;
- einfo++;
- }
-
- if(!numregions) {
- /* Not a valid erase block */
- err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
- instr->state = MTD_ERASE_FAILED;
- err = -EIO;
- }
-
- if(instr->state != MTD_ERASE_FAILED) {
- /* do the erase */
- DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
- err = write_pages(dev, NULL, from, len, &retlen);
- if(err || retlen != len) {
- err("erase failed err = %d", err);
- instr->state = MTD_ERASE_FAILED;
- } else {
- instr->state = MTD_ERASE_DONE;
- }
- }
-
- DEBUG(3, "blkmtd: erase: checking callback\n");
- mtd_erase_callback(instr);
- DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
- return err;
-}
-
-
-/* read a range of the data via the page cache */
-static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
-{
- struct blkmtd_dev *dev = mtd->priv;
- int err = 0;
- int offset;
- int pagenr, pages;
- size_t thislen = 0;
-
- DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
- mtd->name+9, from, len, buf);
-
- if(from > mtd->size)
- return -EINVAL;
- if(from + len > mtd->size)
- len = mtd->size - from;
-
- pagenr = from >> PAGE_SHIFT;
- offset = from - (pagenr << PAGE_SHIFT);
-
- pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT;
- DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n",
- pagenr, offset, pages);
-
- while(pages) {
- struct page *page;
- int cpylen;
-
- DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
- page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
- if(IS_ERR(page)) {
- err = -EIO;
- goto readerr;
- }
-
- cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
- if(offset+cpylen > PAGE_SIZE)
- cpylen = PAGE_SIZE-offset;
-
- memcpy(buf + thislen, page_address(page) + offset, cpylen);
- offset = 0;
- len -= cpylen;
- thislen += cpylen;
- pagenr++;
- pages--;
- if(!PageDirty(page))
- page_cache_release(page);
- }
-
- readerr:
- if(retlen)
- *retlen = thislen;
- DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err);
- return err;
-}
-
-
-/* write data to the underlying device */
-static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
-{
- struct blkmtd_dev *dev = mtd->priv;
- int err;
-
- if(!len)
- return 0;
-
- DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
- mtd->name+9, to, len, buf);
-
- if(to >= mtd->size) {
- return -ENOSPC;
- }
-
- if(to + len > mtd->size) {
- len = mtd->size - to;
- }
-
- err = write_pages(dev, buf, to, len, retlen);
- if(err > 0)
- err = 0;
- DEBUG(2, "blkmtd: write: end, err = %d\n", err);
- return err;
-}
-
-
-/* sync the device - wait until the write queue is empty */
-static void blkmtd_sync(struct mtd_info *mtd)
-{
- /* Currently all writes are synchronous */
-}
-
-
-static void free_device(struct blkmtd_dev *dev)
-{
- DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
- if(dev) {
- kfree(dev->mtd_info.eraseregions);
- kfree(dev->mtd_info.name);
- if(dev->blkdev) {
- invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
- close_bdev_excl(dev->blkdev);
- }
- kfree(dev);
- }
-}
-
-
-/* For a given size and initial erase size, calculate the number
- * and size of each erase region. Goes round the loop twice,
- * once to find out how many regions, then allocates space,
- * then round the loop again to fill it in.
- */
-static struct mtd_erase_region_info *calc_erase_regions(
- size_t erase_size, size_t total_size, int *regions)
-{
- struct mtd_erase_region_info *info = NULL;
-
- DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
- erase_size, total_size, *regions);
- /* Make any user specified erasesize be a power of 2
- and at least PAGE_SIZE */
- if(erase_size) {
- int es = erase_size;
- erase_size = 1;
- while(es != 1) {
- es >>= 1;
- erase_size <<= 1;
- }
- if(erase_size < PAGE_SIZE)
- erase_size = PAGE_SIZE;
- } else {
- erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
- }
-
- *regions = 0;
-
- do {
- int tot_size = total_size;
- int er_size = erase_size;
- int count = 0, offset = 0, regcnt = 0;
-
- while(tot_size) {
- count = tot_size / er_size;
- if(count) {
- tot_size = tot_size % er_size;
- if(info) {
- DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n",
- offset, er_size, count);
- (info+regcnt)->offset = offset;
- (info+regcnt)->erasesize = er_size;
- (info+regcnt)->numblocks = count;
- (*regions)++;
- }
- regcnt++;
- offset += (count * er_size);
- }
- while(er_size > tot_size)
- er_size >>= 1;
- }
- if(info == NULL) {
- info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
- if(!info)
- break;
- }
- } while(!(*regions));
- DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
- erase_size, total_size, *regions);
- return info;
-}
-
-
-static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
-{
- struct block_device *bdev;
- int mode;
- struct blkmtd_dev *dev;
-
- if(!devname)
- return NULL;
-
- /* Get a handle on the device */
-
-
-#ifdef MODULE
- mode = (readonly) ? O_RDONLY : O_RDWR;
- bdev = open_bdev_excl(devname, mode, NULL);
-#else
- mode = (readonly) ? FMODE_READ : FMODE_WRITE;
- bdev = open_by_devnum(name_to_dev_t(devname), mode);
-#endif
- if(IS_ERR(bdev)) {
- err("error: cannot open device %s", devname);
- DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev));
- return NULL;
- }
-
- DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
- MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
-
- if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
- err("attempting to use an MTD device as a block device");
- blkdev_put(bdev);
- return NULL;
- }
-
- dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
- if(dev == NULL) {
- blkdev_put(bdev);
- return NULL;
- }
-
- memset(dev, 0, sizeof(struct blkmtd_dev));
- dev->blkdev = bdev;
- if(!readonly) {
- mutex_init(&dev->wrbuf_mutex);
- }
-
- dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
-
- /* Setup the MTD structure */
- /* make the name contain the block device in */
- dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL);
- if(dev->mtd_info.name == NULL)
- goto devinit_err;
-
- sprintf(dev->mtd_info.name, "blkmtd: %s", devname);
- dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size,
- &dev->mtd_info.numeraseregions);
- if(dev->mtd_info.eraseregions == NULL)
- goto devinit_err;
-
- dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize;
- DEBUG(1, "blkmtd: init: found %d erase regions\n",
- dev->mtd_info.numeraseregions);
-
- if(readonly) {
- dev->mtd_info.type = MTD_ROM;
- dev->mtd_info.flags = MTD_CAP_ROM;
- } else {
- dev->mtd_info.type = MTD_RAM;
- dev->mtd_info.flags = MTD_CAP_RAM;
- dev->mtd_info.erase = blkmtd_erase;
- dev->mtd_info.write = blkmtd_write;
- dev->mtd_info.writev = default_mtd_writev;
- dev->mtd_info.sync = blkmtd_sync;
- }
- dev->mtd_info.read = blkmtd_read;
- dev->mtd_info.readv = default_mtd_readv;
- dev->mtd_info.priv = dev;
- dev->mtd_info.owner = THIS_MODULE;
-
- list_add(&dev->list, &blkmtd_device_list);
- if (add_mtd_device(&dev->mtd_info)) {
- /* Device didnt get added, so free the entry */
- list_del(&dev->list);
- goto devinit_err;
- } else {
- info("mtd%d: [%s] erase_size = %dKiB %s",
- dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "),
- dev->mtd_info.erasesize >> 10,
- readonly ? "(read-only)" : "");
- }
-
- return dev;
-
- devinit_err:
- free_device(dev);
- return NULL;
-}
-
-
-/* Cleanup and exit - sync the device and kill of the kernel thread */
-static void __devexit cleanup_blkmtd(void)
-{
- struct list_head *temp1, *temp2;
-
- /* Remove the MTD devices */
- list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
- struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
- list);
- blkmtd_sync(&dev->mtd_info);
- del_mtd_device(&dev->mtd_info);
- info("mtd%d: [%s] removed", dev->mtd_info.index,
- dev->mtd_info.name + strlen("blkmtd: "));
- list_del(&dev->list);
- free_device(dev);
- }
-}
-
-#ifndef MODULE
-
-/* Handle kernel boot params */
-
-
-static int __init param_blkmtd_device(char *str)
-{
- int i;
-
- for(i = 0; i < MAX_DEVICES; i++) {
- device[i] = str;
- DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
- strsep(&str, ",");
- }
- return 1;
-}
-
-
-static int __init param_blkmtd_erasesz(char *str)
-{
- int i;
- for(i = 0; i < MAX_DEVICES; i++) {
- char *val = strsep(&str, ",");
- if(val)
- erasesz[i] = simple_strtoul(val, NULL, 0);
- DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
- }
-
- return 1;
-}
-
-
-static int __init param_blkmtd_ro(char *str)
-{
- int i;
- for(i = 0; i < MAX_DEVICES; i++) {
- char *val = strsep(&str, ",");
- if(val)
- ro[i] = simple_strtoul(val, NULL, 0);
- DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
- }
-
- return 1;
-}
-
-
-static int __init param_blkmtd_sync(char *str)
-{
- if(str[0] == '1')
- sync = 1;
- return 1;
-}
-
-__setup("blkmtd_device=", param_blkmtd_device);
-__setup("blkmtd_erasesz=", param_blkmtd_erasesz);
-__setup("blkmtd_ro=", param_blkmtd_ro);
-__setup("blkmtd_sync=", param_blkmtd_sync);
-
-#endif
-
-
-/* Startup */
-static int __init init_blkmtd(void)
-{
- int i;
-
- info("version " VERSION);
- /* Check args - device[0] is the bare minimum*/
- if(!device[0]) {
- err("error: missing `device' name\n");
- return -EINVAL;
- }
-
- for(i = 0; i < MAX_DEVICES; i++)
- add_device(device[i], ro[i], erasesz[i] << 10);
-
- if(list_empty(&blkmtd_device_list))
- return -EINVAL;
-
- return 0;
-}
-
-module_init(init_blkmtd);
-module_exit(cleanup_blkmtd);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 8bbc751a6021..d27f4129afd3 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -54,7 +54,7 @@ static const int debug = 0;
#define MAX_PCMCIA_ADDR 0x4000000
struct pcmciamtd_dev {
- dev_link_t link; /* PCMCIA link */
+ struct pcmcia_device *p_dev;
dev_node_t node; /* device node */
caddr_t win_base; /* ioremapped address of PCMCIA window */
unsigned int win_size; /* size of window */
@@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
memreq_t mrq;
int ret;
- if(!(dev->link.state & DEV_PRESENT)) {
- DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
+ if (!pcmcia_dev_present(dev->p_dev)) {
+ DEBUG(1, "device removed");
return 0;
}
@@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
dev->offset, mrq.CardOffset);
mrq.Page = 0;
if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
- cs_error(dev->link.handle, MapMemPage, ret);
+ cs_error(dev->p_dev, MapMemPage, ret);
return NULL;
}
dev->offset = mrq.CardOffset;
@@ -238,7 +238,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
/* read/write{8,16} copy_{from,to} routines with direct access */
-#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
+#define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))
static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
{
@@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
static void pcmciamtd_set_vpp(struct map_info *map, int on)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
- dev_link_t *link = &dev->link;
+ struct pcmcia_device *link = dev->p_dev;
modconf_t mod;
int ret;
@@ -328,9 +328,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
- ret = pcmcia_modify_configuration(link->handle, &mod);
+ ret = pcmcia_modify_configuration(link, &mod);
if(ret != CS_SUCCESS) {
- cs_error(link->handle, ModifyConfiguration, ret);
+ cs_error(link, ModifyConfiguration, ret);
}
}
@@ -340,7 +340,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
* still open, this will be postponed until it is closed.
*/
-static void pcmciamtd_release(dev_link_t *link)
+static void pcmciamtd_release(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
@@ -353,12 +353,11 @@ static void pcmciamtd_release(dev_link_t *link)
}
pcmcia_release_window(link->win);
}
- pcmcia_release_configuration(link->handle);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
+static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name)
{
int rc;
tuple_t tuple;
@@ -371,16 +370,16 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
tuple.TupleOffset = 0;
tuple.DesiredTuple = RETURN_FIRST_TUPLE;
- rc = pcmcia_get_first_tuple(link->handle, &tuple);
+ rc = pcmcia_get_first_tuple(link, &tuple);
while(rc == CS_SUCCESS) {
- rc = pcmcia_get_tuple_data(link->handle, &tuple);
+ rc = pcmcia_get_tuple_data(link, &tuple);
if(rc != CS_SUCCESS) {
- cs_error(link->handle, GetTupleData, rc);
+ cs_error(link, GetTupleData, rc);
break;
}
- rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
+ rc = pcmcia_parse_tuple(link, &tuple, &parse);
if(rc != CS_SUCCESS) {
- cs_error(link->handle, ParseTuple, rc);
+ cs_error(link, ParseTuple, rc);
break;
}
@@ -451,7 +450,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
}
- rc = pcmcia_get_next_tuple(link->handle, &tuple);
+ rc = pcmcia_get_next_tuple(link, &tuple);
}
if(!dev->pcmcia_map.size)
dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
@@ -488,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void pcmciamtd_config(dev_link_t *link)
+static int pcmciamtd_config(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
struct mtd_info *mtd = NULL;
@@ -504,13 +503,10 @@ static void pcmciamtd_config(dev_link_t *link)
DEBUG(3, "link=0x%p", link);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
DEBUG(2, "Validating CIS");
- ret = pcmcia_validate_cis(link->handle, &cisinfo);
+ ret = pcmcia_validate_cis(link, &cisinfo);
if(ret != CS_SUCCESS) {
- cs_error(link->handle, GetTupleData, ret);
+ cs_error(link, GetTupleData, ret);
} else {
DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
}
@@ -538,7 +534,7 @@ static void pcmciamtd_config(dev_link_t *link)
req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
req.Base = 0;
req.AccessSpeed = mem_speed;
- link->win = (window_handle_t)link->handle;
+ link->win = (window_handle_t)link;
req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
dev->win_size = 0;
@@ -546,7 +542,7 @@ static void pcmciamtd_config(dev_link_t *link)
int ret;
DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
req.Size >> 10, req.AccessSpeed);
- ret = pcmcia_request_window(&link->handle, &req, &link->win);
+ ret = pcmcia_request_window(&link, &req, &link->win);
DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
if(ret) {
req.Size >>= 1;
@@ -562,19 +558,19 @@ static void pcmciamtd_config(dev_link_t *link)
if(!dev->win_size) {
err("Cant allocate memory window");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
/* Get write protect status */
- CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status));
+ CS_CHECK(GetStatus, pcmcia_get_status(link, &status));
DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
status.CardState, (unsigned long)link->win);
dev->win_base = ioremap(req.Base, req.Size);
if(!dev->win_base) {
err("ioremap(%lu, %u) failed", req.Base, req.Size);
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
dev, req.Base, dev->win_base, req.Size);
@@ -584,17 +580,14 @@ static void pcmciamtd_config(dev_link_t *link)
dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
DEBUG(2, "Getting configuration");
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t));
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t));
DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
dev->vpp = (vpp) ? vpp : t.Vpp1;
link->conf.Attributes = 0;
- link->conf.Vcc = t.Vcc;
if(setvpp == 2) {
- link->conf.Vpp1 = dev->vpp;
- link->conf.Vpp2 = dev->vpp;
+ link->conf.Vpp = dev->vpp;
} else {
- link->conf.Vpp1 = 0;
- link->conf.Vpp2 = 0;
+ link->conf.Vpp = 0;
}
link->conf.IntType = INT_MEMORY;
@@ -606,9 +599,10 @@ static void pcmciamtd_config(dev_link_t *link)
link->conf.ConfigIndex = 0;
link->conf.Present = t.Present;
DEBUG(2, "Setting Configuration");
- ret = pcmcia_request_configuration(link->handle, &link->conf);
+ ret = pcmcia_request_configuration(link, &link->conf);
if(ret != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, ret);
+ cs_error(link, RequestConfiguration, ret);
+ return -ENODEV;
}
if(mem_type == 1) {
@@ -629,7 +623,7 @@ static void pcmciamtd_config(dev_link_t *link)
if(!mtd) {
DEBUG(1, "Cant find an MTD");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
dev->mtd_info = mtd;
@@ -654,7 +648,6 @@ static void pcmciamtd_config(dev_link_t *link)
use the faster non-remapping read/write functions */
if(mtd->size <= dev->win_size) {
DEBUG(1, "Using non remapping memory functions");
- dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
if (dev->pcmcia_map.bankwidth == 1) {
dev->pcmcia_map.read = pcmcia_read8;
@@ -672,19 +665,18 @@ static void pcmciamtd_config(dev_link_t *link)
dev->mtd_info = NULL;
err("Couldnt register MTD device");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
info("mtd%d: %s", mtd->index, mtd->name);
- link->state &= ~DEV_CONFIG_PENDING;
- link->dev = &dev->node;
- return;
+ link->dev_node = &dev->node;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
err("CS Error, exiting");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
@@ -713,21 +705,18 @@ static int pcmciamtd_resume(struct pcmcia_device *dev)
* when the device is released.
*/
-static void pcmciamtd_detach(struct pcmcia_device *p_dev)
+static void pcmciamtd_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
+ struct pcmciamtd_dev *dev = link->priv;
DEBUG(3, "link=0x%p", link);
- if(link->state & DEV_CONFIG) {
- struct pcmciamtd_dev *dev = link->priv;
- if(dev->mtd_info) {
- del_mtd_device(dev->mtd_info);
- info("mtd%d: Removed", dev->mtd_info->index);
- }
-
- pcmciamtd_release(link);
+ if(dev->mtd_info) {
+ del_mtd_device(dev->mtd_info);
+ info("mtd%d: Removed", dev->mtd_info->index);
}
+
+ pcmciamtd_release(link);
}
@@ -736,10 +725,9 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev)
* with Card Services.
*/
-static int pcmciamtd_attach(struct pcmcia_device *p_dev)
+static int pcmciamtd_probe(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev;
- dev_link_t *link;
/* Create new memory card device */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
@@ -747,20 +735,13 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev)
DEBUG(1, "dev=0x%p", dev);
memset(dev, 0, sizeof(*dev));
- link = &dev->link;
+ dev->p_dev = link;
link->priv = dev;
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY;
- link->next = NULL;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- pcmciamtd_config(link);
-
- return 0;
+ return pcmciamtd_config(link);
}
static struct pcmcia_device_id pcmciamtd_ids[] = {
@@ -794,7 +775,7 @@ static struct pcmcia_driver pcmciamtd_driver = {
.drv = {
.name = "pcmciamtd"
},
- .probe = pcmciamtd_attach,
+ .probe = pcmciamtd_probe,
.remove = pcmciamtd_detach,
.owner = THIS_MODULE,
.id_table = pcmciamtd_ids,
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ce99845d8266..066e22b01a94 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -539,8 +539,7 @@ rx_status_loop:
unsigned buflen;
skb = cp->rx_skb[rx_tail].skb;
- if (!skb)
- BUG();
+ BUG_ON(!skb);
desc = &cp->rx_ring[rx_tail];
status = le32_to_cpu(desc->opts1);
@@ -723,8 +722,7 @@ static void cp_tx (struct cp_private *cp)
break;
skb = cp->tx_skb[tx_tail].skb;
- if (!skb)
- BUG();
+ BUG_ON(!skb);
pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
@@ -1550,8 +1548,7 @@ static void cp_get_ethtool_stats (struct net_device *dev,
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
- if (i != CP_NUM_STATS)
- BUG();
+ BUG_ON(i != CP_NUM_STATS);
pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}
@@ -1856,8 +1853,7 @@ static void cp_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct cp_private *cp = netdev_priv(dev);
- if (!dev)
- BUG();
+ BUG_ON(!dev);
unregister_netdev(dev);
iounmap(cp->regs);
if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 64e2caf3083d..fabc0607b0f1 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -765,8 +765,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
BUGMSG(D_DURING, "in arcnet_interrupt\n");
lp = dev->priv;
- if (!lp)
- BUG();
+ BUG_ON(!lp);
spin_lock(&lp->lock);
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index 43150b2bd13f..0d45553ff75c 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -125,11 +125,11 @@ static void __init com90xx_probe(void)
if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
return;
- shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long),
+ shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long),
GFP_KERNEL);
if (!shmems)
return;
- iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *),
+ iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *),
GFP_KERNEL);
if (!iomem) {
kfree(shmems);
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 15032f2c7817..3d306681919e 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
* Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
+ * Copyright (C) 2006 Broadcom Corporation.
*
* Distribute under GPL.
*/
@@ -28,8 +29,8 @@
#define DRV_MODULE_NAME "b44"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "0.97"
-#define DRV_MODULE_RELDATE "Nov 30, 2005"
+#define DRV_MODULE_VERSION "1.00"
+#define DRV_MODULE_RELDATE "Apr 7, 2006"
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
@@ -136,7 +137,7 @@ static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
return readl(bp->regs + reg);
}
-static inline void bw32(const struct b44 *bp,
+static inline void bw32(const struct b44 *bp,
unsigned long reg, unsigned long val)
{
writel(val, bp->regs + reg);
@@ -286,13 +287,13 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
val |= ((u32) data[4]) << 8;
val |= ((u32) data[5]) << 0;
bw32(bp, B44_CAM_DATA_LO, val);
- val = (CAM_DATA_HI_VALID |
+ val = (CAM_DATA_HI_VALID |
(((u32) data[0]) << 8) |
(((u32) data[1]) << 0));
bw32(bp, B44_CAM_DATA_HI, val);
bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
(index << CAM_CTRL_INDEX_SHIFT)));
- b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
+ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
}
static inline void __b44_disable_ints(struct b44 *bp)
@@ -410,25 +411,18 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
{
- u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE |
- B44_FLAG_RX_PAUSE);
+ u32 pause_enab = 0;
- if (local & ADVERTISE_PAUSE_CAP) {
- if (local & ADVERTISE_PAUSE_ASYM) {
- if (remote & LPA_PAUSE_CAP)
- pause_enab |= (B44_FLAG_TX_PAUSE |
- B44_FLAG_RX_PAUSE);
- else if (remote & LPA_PAUSE_ASYM)
- pause_enab |= B44_FLAG_RX_PAUSE;
- } else {
- if (remote & LPA_PAUSE_CAP)
- pause_enab |= (B44_FLAG_TX_PAUSE |
- B44_FLAG_RX_PAUSE);
- }
- } else if (local & ADVERTISE_PAUSE_ASYM) {
- if ((remote & LPA_PAUSE_CAP) &&
- (remote & LPA_PAUSE_ASYM))
- pause_enab |= B44_FLAG_TX_PAUSE;
+ /* The driver supports only rx pause by default because
+ the b44 mac tx pause mechanism generates excessive
+ pause frames.
+ Use ethtool to turn on b44 tx pause if necessary.
+ */
+ if ((local & ADVERTISE_PAUSE_CAP) &&
+ (local & ADVERTISE_PAUSE_ASYM)){
+ if ((remote & LPA_PAUSE_ASYM) &&
+ !(remote & LPA_PAUSE_CAP))
+ pause_enab |= B44_FLAG_RX_PAUSE;
}
__b44_set_flow_ctrl(bp, pause_enab);
@@ -608,8 +602,7 @@ static void b44_tx(struct b44 *bp)
struct ring_info *rp = &bp->tx_buffers[cons];
struct sk_buff *skb = rp->skb;
- if (unlikely(skb == NULL))
- BUG();
+ BUG_ON(skb == NULL);
pci_unmap_single(bp->pdev,
pci_unmap_addr(rp, mapping),
@@ -1064,7 +1057,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
-
+
return 0;
}
@@ -1382,7 +1375,7 @@ static void b44_init_hw(struct b44 *bp)
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
- bp->rx_prod = bp->rx_pending;
+ bp->rx_prod = bp->rx_pending;
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
@@ -1554,9 +1547,9 @@ static void __b44_set_rx_mode(struct net_device *dev)
val |= RXCONFIG_ALLMULTI;
else
i = __b44_load_mcast(bp, dev);
-
+
for (; i < 64; i++) {
- __b44_cam_write(bp, zero, i);
+ __b44_cam_write(bp, zero, i);
}
bw32(bp, B44_RXCONFIG, val);
val = br32(bp, B44_CAM_CTRL);
@@ -1738,7 +1731,7 @@ static int b44_set_ringparam(struct net_device *dev,
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
-
+
return 0;
}
@@ -1783,7 +1776,7 @@ static int b44_set_pauseparam(struct net_device *dev,
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
-
+
return 0;
}
@@ -1899,7 +1892,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->core_unit = ssb_core_unit(bp);
bp->dma_offset = SB_PCI_DMA;
- /* XXX - really required?
+ /* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
*/
out:
@@ -1947,7 +1940,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
"aborting.\n");
goto err_out_free_res;
}
-
+
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
@@ -2042,9 +2035,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
pci_save_state(bp->pdev);
- /* Chip reset provides power to the b44 MAC & PCI cores, which
+ /* Chip reset provides power to the b44 MAC & PCI cores, which
* is necessary for MAC register access.
- */
+ */
b44_chip_reset(bp);
printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
@@ -2092,10 +2085,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
del_timer_sync(&bp->timer);
- spin_lock_irq(&bp->lock);
+ spin_lock_irq(&bp->lock);
b44_halt(bp);
- netif_carrier_off(bp->dev);
+ netif_carrier_off(bp->dev);
netif_device_detach(bp->dev);
b44_free_rings(bp);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 2671da20a496..5ca99e26660a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -63,7 +63,7 @@
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (5*HZ)
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile
index 91e927827c43..54c78d94f48b 100644
--- a/drivers/net/chelsio/Makefile
+++ b/drivers/net/chelsio/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_CHELSIO_T1) += cxgb.o
-EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS)
+EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS)
cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 30ff8ea1a402..4391bf4bf573 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1093,8 +1093,7 @@ static int process_responses(struct adapter *adapter, int budget)
if (likely(e->DataValid)) {
struct freelQ *fl = &sge->freelQ[e->FreelistQid];
- if (unlikely(!e->Sop || !e->Eop))
- BUG();
+ BUG_ON(!e->Sop || !e->Eop);
if (unlikely(e->Offload))
unexpected_offload(adapter, fl);
else
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 49cd096a3c3d..c99e87838f92 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3308,8 +3308,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
while (poll_dev != &adapter->polling_netdev[i]) {
i++;
- if (unlikely(i == adapter->num_rx_queues))
- BUG();
+ BUG_ON(i == adapter->num_rx_queues);
}
if (likely(adapter->num_tx_queues == 1)) {
@@ -3769,6 +3768,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
ps_page->ps_page[j] = NULL;
skb->len += length;
skb->data_len += length;
+ skb->truesize += length;
}
copydone:
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index aa1569182fd6..815436c6170f 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -203,8 +203,7 @@ static int eql_open(struct net_device *dev)
printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
"your slave devices.\n", dev->name);
- if (!list_empty(&eql->queue.all_slaves))
- BUG();
+ BUG_ON(!list_empty(&eql->queue.all_slaves));
eql->min_slaves = 1;
eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 7627a75f4f7c..9788b1ef2e7d 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -105,6 +105,7 @@
* 0.50: 20 Jan 2006: Add 8021pq tagging support.
* 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
* 0.52: 20 Jan 2006: Add MSI/MSIX support.
+ * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -116,7 +117,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.52"
+#define FORCEDETH_VERSION "0.53"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -160,6 +161,7 @@
#define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */
#define DEV_HAS_MSI 0x0040 /* device supports MSI */
#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */
+#define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */
enum {
NvRegIrqStatus = 0x000,
@@ -203,6 +205,8 @@ enum {
#define NVREG_MISC1_HD 0x02
#define NVREG_MISC1_FORCE 0x3b0f3c
+ NvRegMacReset = 0x3c,
+#define NVREG_MAC_RESET_ASSERT 0x0F3
NvRegTransmitterControl = 0x084,
#define NVREG_XMITCTL_START 0x01
NvRegTransmitterStatus = 0x088,
@@ -326,6 +330,10 @@ enum {
NvRegMSIXMap0 = 0x3e0,
NvRegMSIXMap1 = 0x3e4,
NvRegMSIXIrqStatus = 0x3f0,
+
+ NvRegPowerState2 = 0x600,
+#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11
+#define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001
};
/* Big endian: should work, but is untested */
@@ -414,7 +422,8 @@ typedef union _ring_type {
#define NV_RX3_VLAN_TAG_MASK (0x0000FFFF)
/* Miscelaneous hardware related defines: */
-#define NV_PCI_REGSZ 0x270
+#define NV_PCI_REGSZ_VER1 0x270
+#define NV_PCI_REGSZ_VER2 0x604
/* various timeout delays: all in usec */
#define NV_TXRX_RESET_DELAY 4
@@ -431,6 +440,7 @@ typedef union _ring_type {
#define NV_MIIBUSY_DELAY 50
#define NV_MIIPHY_DELAY 10
#define NV_MIIPHY_DELAYMAX 10000
+#define NV_MAC_RESET_DELAY 64
#define NV_WAKEUPPATTERNS 5
#define NV_WAKEUPMASKENTRIES 4
@@ -552,6 +562,8 @@ struct fe_priv {
u32 desc_ver;
u32 txrxctl_bits;
u32 vlanctl_bits;
+ u32 driver_data;
+ u32 register_size;
void __iomem *base;
@@ -919,6 +931,24 @@ static void nv_txrx_reset(struct net_device *dev)
pci_push(base);
}
+static void nv_mac_reset(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+ dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name);
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
+ pci_push(base);
+ writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset);
+ pci_push(base);
+ udelay(NV_MAC_RESET_DELAY);
+ writel(0, base + NvRegMacReset);
+ pci_push(base);
+ udelay(NV_MAC_RESET_DELAY);
+ writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
+ pci_push(base);
+}
+
/*
* nv_get_stats: dev->get_stats function
* Get latest stats value from the nic.
@@ -1331,7 +1361,7 @@ static void nv_tx_timeout(struct net_device *dev)
dev->name, (unsigned long)np->ring_addr,
np->next_tx, np->nic_tx);
printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
- for (i=0;i<0x400;i+= 32) {
+ for (i=0;i<=np->register_size;i+= 32) {
printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
i,
readl(base + i + 0), readl(base + i + 4),
@@ -2488,11 +2518,11 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
}
#define FORCEDETH_REGS_VER 1
-#define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */
static int nv_get_regs_len(struct net_device *dev)
{
- return FORCEDETH_REGS_SIZE;
+ struct fe_priv *np = netdev_priv(dev);
+ return np->register_size;
}
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
@@ -2504,7 +2534,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void
regs->version = FORCEDETH_REGS_VER;
spin_lock_irq(&np->lock);
- for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++)
+ for (i = 0;i <= np->register_size/sizeof(u32); i++)
rbuf[i] = readl(base + i*sizeof(u32));
spin_unlock_irq(&np->lock);
}
@@ -2608,6 +2638,8 @@ static int nv_open(struct net_device *dev)
dprintk(KERN_DEBUG "nv_open: begin\n");
/* 1) erase previous misconfiguration */
+ if (np->driver_data & DEV_HAS_POWER_CNTRL)
+ nv_mac_reset(dev);
/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
writel(0, base + NvRegMulticastAddrB);
@@ -2878,6 +2910,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
unsigned long addr;
u8 __iomem *base;
int err, i;
+ u32 powerstate;
dev = alloc_etherdev(sizeof(struct fe_priv));
err = -ENOMEM;
@@ -2910,6 +2943,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (err < 0)
goto out_disable;
+ if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL))
+ np->register_size = NV_PCI_REGSZ_VER2;
+ else
+ np->register_size = NV_PCI_REGSZ_VER1;
+
err = -EINVAL;
addr = 0;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
@@ -2918,7 +2956,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
pci_resource_len(pci_dev, i),
pci_resource_flags(pci_dev, i));
if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM &&
- pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) {
+ pci_resource_len(pci_dev, i) >= np->register_size) {
addr = pci_resource_start(pci_dev, i);
break;
}
@@ -2929,6 +2967,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
goto out_relreg;
}
+ /* copy of driver data */
+ np->driver_data = id->driver_data;
+
/* handle different descriptor versions */
if (id->driver_data & DEV_HAS_HIGH_DMA) {
/* packet format 3: supports 40-bit addressing */
@@ -2986,7 +3027,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
}
err = -ENOMEM;
- np->base = ioremap(addr, NV_PCI_REGSZ);
+ np->base = ioremap(addr, np->register_size);
if (!np->base)
goto out_relreg;
dev->base_addr = (unsigned long)np->base;
@@ -3062,6 +3103,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
writel(0, base + NvRegWakeUpFlags);
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)
+ powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
+ writel(powerstate, base + NvRegPowerState2);
+ }
+
if (np->desc_ver == DESC_VER_1) {
np->tx_flags = NV_TX_VALID;
} else {
@@ -3223,19 +3278,19 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP51 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL,
},
{ /* MCP51 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL,
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
},
{0,},
};
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 771e25d8c417..218d31764c52 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -210,7 +210,8 @@ static int gfar_probe(struct platform_device *pdev)
goto regs_fail;
}
- spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->txlock);
+ spin_lock_init(&priv->rxlock);
platform_set_drvdata(pdev, dev);
@@ -515,11 +516,13 @@ void stop_gfar(struct net_device *dev)
phy_stop(priv->phydev);
/* Lock it down */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
gfar_halt(dev);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
/* Free the IRQs */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
@@ -605,14 +608,15 @@ void gfar_start(struct net_device *dev)
tempval |= DMACTRL_INIT_SETTINGS;
gfar_write(&priv->regs->dmactrl, tempval);
- /* Clear THLT, so that the DMA starts polling now */
- gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
-
/* Make sure we aren't stopped */
tempval = gfar_read(&priv->regs->dmactrl);
tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&priv->regs->dmactrl, tempval);
+ /* Clear THLT/RHLT, so that the DMA starts polling now */
+ gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
+ gfar_write(&regs->rstat, RSTAT_CLEAR_RHALT);
+
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
}
@@ -928,12 +932,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct txfcb *fcb = NULL;
struct txbd8 *txbdp;
u16 status;
+ unsigned long flags;
/* Update transmit stats */
priv->stats.tx_bytes += skb->len;
/* Lock priv now */
- spin_lock_irq(&priv->lock);
+ spin_lock_irqsave(&priv->txlock, flags);
/* Point at the first free tx descriptor */
txbdp = priv->cur_tx;
@@ -1004,7 +1009,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
/* Unlock priv */
- spin_unlock_irq(&priv->lock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return 0;
}
@@ -1049,7 +1054,7 @@ static void gfar_vlan_rx_register(struct net_device *dev,
unsigned long flags;
u32 tempval;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
priv->vlgrp = grp;
@@ -1076,7 +1081,7 @@ static void gfar_vlan_rx_register(struct net_device *dev,
gfar_write(&priv->regs->rctrl, tempval);
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
}
@@ -1085,12 +1090,12 @@ 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->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
if (priv->vlgrp)
priv->vlgrp->vlan_devices[vid] = NULL;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
}
@@ -1179,7 +1184,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
/* Lock priv */
- spin_lock(&priv->lock);
+ spin_lock(&priv->txlock);
bdp = priv->dirty_tx;
while ((bdp->status & TXBD_READY) == 0) {
/* If dirty_tx and cur_tx are the same, then either the */
@@ -1224,7 +1229,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
else
gfar_write(&priv->regs->txic, 0);
- spin_unlock(&priv->lock);
+ spin_unlock(&priv->txlock);
return IRQ_HANDLED;
}
@@ -1305,9 +1310,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
struct gfar_private *priv = netdev_priv(dev);
-
#ifdef CONFIG_GFAR_NAPI
u32 tempval;
+#else
+ unsigned long flags;
#endif
/* Clear IEVENT, so rx interrupt isn't called again
@@ -1330,7 +1336,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
}
#else
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->rxlock, flags);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
/* If we are coalescing interrupts, update the timer */
@@ -1341,7 +1347,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
else
gfar_write(&priv->regs->rxic, 0);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
#endif
return IRQ_HANDLED;
@@ -1490,13 +1496,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
/* Update the current rxbd pointer to be the next one */
priv->cur_rx = bdp;
- /* If no packets have arrived since the
- * last one we processed, clear the IEVENT RX and
- * BSY bits so that another interrupt won't be
- * generated when we set IMASK */
- if (bdp->status & RXBD_EMPTY)
- gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
-
return howmany;
}
@@ -1516,7 +1515,7 @@ static int gfar_poll(struct net_device *dev, int *budget)
rx_work_limit -= howmany;
*budget -= howmany;
- if (rx_work_limit >= 0) {
+ if (rx_work_limit > 0) {
netif_rx_complete(dev);
/* Clear the halt bit in RSTAT */
@@ -1533,7 +1532,8 @@ static int gfar_poll(struct net_device *dev, int *budget)
gfar_write(&priv->regs->rxic, 0);
}
- return (rx_work_limit < 0) ? 1 : 0;
+ /* Return 1 if there's more work to do */
+ return (rx_work_limit > 0) ? 0 : 1;
}
#endif
@@ -1629,7 +1629,7 @@ static void adjust_link(struct net_device *dev)
struct phy_device *phydev = priv->phydev;
int new_state = 0;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
if (phydev->link) {
u32 tempval = gfar_read(&regs->maccfg2);
u32 ecntrl = gfar_read(&regs->ecntrl);
@@ -1694,7 +1694,7 @@ static void adjust_link(struct net_device *dev)
if (new_state && netif_msg_link(priv))
phy_print_status(phydev);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
}
/* Update the hash table based on the current list of multicast
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index d37d5401be6e..127c98cf3336 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -656,43 +656,62 @@ struct gfar {
* the buffer descriptor determines the actual condition.
*/
struct gfar_private {
- /* pointers to arrays of skbuffs for tx and rx */
+ /* Fields controlled by TX lock */
+ spinlock_t txlock;
+
+ /* Pointer to the array of skbuffs */
struct sk_buff ** tx_skbuff;
- struct sk_buff ** rx_skbuff;
- /* indices pointing to the next free sbk in skb arrays */
+ /* next free skb in the array */
u16 skb_curtx;
- u16 skb_currx;
- /* index of the first skb which hasn't been transmitted
- * yet. */
+ /* First skb in line to be transmitted */
u16 skb_dirtytx;
/* Configuration info for the coalescing features */
unsigned char txcoalescing;
unsigned short txcount;
unsigned short txtime;
+
+ /* Buffer descriptor pointers */
+ struct txbd8 *tx_bd_base; /* First tx buffer descriptor */
+ struct txbd8 *cur_tx; /* Next free ring entry */
+ struct txbd8 *dirty_tx; /* First buffer in line
+ to be transmitted */
+ unsigned int tx_ring_size;
+
+ /* RX Locked fields */
+ spinlock_t rxlock;
+
+ /* skb array and index */
+ struct sk_buff ** rx_skbuff;
+ u16 skb_currx;
+
+ /* RX Coalescing values */
unsigned char rxcoalescing;
unsigned short rxcount;
unsigned short rxtime;
- /* GFAR addresses */
- struct rxbd8 *rx_bd_base; /* Base addresses of Rx and Tx Buffers */
- struct txbd8 *tx_bd_base;
+ struct rxbd8 *rx_bd_base; /* First Rx buffers */
struct rxbd8 *cur_rx; /* Next free rx ring entry */
- struct txbd8 *cur_tx; /* Next free ring entry */
- struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
- struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */
- u32 __iomem *hash_regs[16];
- int hash_width;
- struct net_device_stats stats; /* linux network statistics */
- struct gfar_extra_stats extra_stats;
- spinlock_t lock;
+
+ /* RX parameters */
+ unsigned int rx_ring_size;
unsigned int rx_buffer_size;
unsigned int rx_stash_size;
unsigned int rx_stash_index;
- unsigned int tx_ring_size;
- unsigned int rx_ring_size;
+
+ struct vlan_group *vlgrp;
+
+ /* Unprotected fields */
+ /* Pointer to the GFAR memory mapped Registers */
+ struct gfar __iomem *regs;
+
+ /* Hash registers and their width */
+ u32 __iomem *hash_regs[16];
+ int hash_width;
+
+ /* global parameters */
unsigned int fifo_threshold;
unsigned int fifo_starve;
unsigned int fifo_starve_off;
@@ -702,13 +721,15 @@ struct gfar_private {
extended_hash:1,
bd_stash_en:1;
unsigned short padding;
- struct vlan_group *vlgrp;
- /* Info structure initialized by board setup code */
+
unsigned int interruptTransmit;
unsigned int interruptReceive;
unsigned int interruptError;
+
+ /* info structure initialized by platform code */
struct gianfar_platform_data *einfo;
+ /* PHY stuff */
struct phy_device *phydev;
struct mii_bus *mii_bus;
int oldspeed;
@@ -716,6 +737,10 @@ struct gfar_private {
int oldlink;
uint32_t msg_enable;
+
+ /* Network Statistics */
+ struct net_device_stats stats;
+ struct gfar_extra_stats extra_stats;
};
static inline u32 gfar_read(volatile unsigned __iomem *addr)
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 5de7b2e259dc..d69698c695ef 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -455,10 +455,14 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
/* Halt TX and RX, and process the frames which
* have already been received */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
gfar_halt(dev);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
@@ -488,10 +492,14 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
/* Halt TX and RX, and process the frames which
* have already been received */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
gfar_halt(dev);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
@@ -523,7 +531,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
gfar_halt(dev);
if (data)
@@ -532,7 +540,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
dev->features &= ~NETIF_F_IP_CSUM;
gfar_start(dev);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return 0;
}
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 51ef181b1368..a6d5c43199cb 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
else
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
/* Set the new stashing value */
priv->bd_stash_en = new_setting;
@@ -96,7 +96,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
gfar_write(&priv->regs->attr, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
u32 temp;
unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
if (length > priv->rx_buffer_size)
return count;
@@ -142,7 +142,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
gfar_write(&priv->regs->attr, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
u32 temp;
unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
if (index > priv->rx_stash_size)
return count;
@@ -180,7 +180,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
temp |= ATTRELI_EI(index);
gfar_write(&priv->regs->attreli, flags);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -205,7 +205,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
if (length > GFAR_MAX_FIFO_THRESHOLD)
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
priv->fifo_threshold = length;
@@ -214,7 +214,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
temp |= length;
gfar_write(&priv->regs->fifo_tx_thr, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return count;
}
@@ -240,7 +240,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
if (num > GFAR_MAX_FIFO_STARVE)
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
priv->fifo_starve = num;
@@ -249,7 +249,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
temp |= num;
gfar_write(&priv->regs->fifo_tx_starve, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return count;
}
@@ -274,7 +274,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
if (num > GFAR_MAX_FIFO_STARVE_OFF)
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
priv->fifo_starve_off = num;
@@ -283,7 +283,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
temp |= num;
gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return count;
}
diff --git a/drivers/net/hydra.h b/drivers/net/hydra.h
deleted file mode 100644
index 37414146258d..000000000000
--- a/drivers/net/hydra.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* $Linux: hydra.h,v 1.0 1994/10/26 02:03:47 cgd Exp $ */
-
-/*
- * Copyright (c) 1994 Timo Rossi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Timo Rossi
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- */
-
-/*
- * The Hydra Systems card uses the National Semiconductor
- * 8390 NIC (Network Interface Controller) chip, located
- * at card base address + 0xffe1. NIC registers are accessible
- * only at odd byte addresses, so the register offsets must
- * be multiplied by two.
- *
- * Card address PROM is located at card base + 0xffc0 (even byte addresses)
- *
- * RAM starts at the card base address, and is 16K or 64K.
- * The current Amiga NetBSD hydra driver is hardwired for 16K.
- * It seems that the RAM should be accessed as words or longwords only.
- *
- */
-
-/* adapted for Linux by Topi Kanerva 03/29/95
- with original author's permission */
-
-#define HYDRA_NIC_BASE 0xffe1
-
-/* Page0 registers */
-
-#define NIC_CR 0 /* Command register */
-#define NIC_PSTART (1*2) /* Page start (write) */
-#define NIC_PSTOP (2*2) /* Page stop (write) */
-#define NIC_BNDRY (3*2) /* Boundary pointer */
-#define NIC_TSR (4*2) /* Transmit status (read) */
-#define NIC_TPSR (4*2) /* Transmit page start (write) */
-#define NIC_NCR (5*2) /* Number of collisions, read */
-#define NIC_TBCR0 (5*2) /* Transmit byte count low (write) */
-#define NIC_FIFO (6*2) /* FIFO reg. (read) */
-#define NIC_TBCR1 (6*2) /* Transmit byte count high (write) */
-#define NIC_ISR (7*2) /* Interrupt status register */
-#define NIC_RBCR0 (0xa*2) /* Remote byte count low (write) */
-#define NIC_RBCR1 (0xb*2) /* Remote byte count high (write) */
-#define NIC_RSR (0xc*2) /* Receive status (read) */
-#define NIC_RCR (0xc*2) /* Receive config (write) */
-#define NIC_CNTR0 (0xd*2) /* Frame alignment error count (read) */
-#define NIC_TCR (0xd*2) /* Transmit config (write) */
-#define NIC_CNTR1 (0xe*2) /* CRC error counter (read) */
-#define NIC_DCR (0xe*2) /* Data config (write) */
-#define NIC_CNTR2 (0xf*2) /* missed packet counter (read) */
-#define NIC_IMR (0xf*2) /* Interrupt mask reg. (write) */
-
-/* Page1 registers */
-
-#define NIC_PAR0 (1*2) /* Physical address */
-#define NIC_PAR1 (2*2)
-#define NIC_PAR2 (3*2)
-#define NIC_PAR3 (4*2)
-#define NIC_PAR4 (5*2)
-#define NIC_PAR5 (6*2)
-#define NIC_CURR (7*2) /* Current RX ring-buffer page */
-#define NIC_MAR0 (8*2) /* Multicast address */
-#define NIC_MAR1 (9*2)
-#define NIC_MAR2 (0xa*2)
-#define NIC_MAR3 (0xb*2)
-#define NIC_MAR4 (0xc*2)
-#define NIC_MAR5 (0xd*2)
-#define NIC_MAR6 (0xe*2)
-#define NIC_MAR7 (0xf*2)
-
-/* Command register definitions */
-
-#define CR_STOP 0x01 /* Stop -- software reset command */
-#define CR_START 0x02 /* Start */
-#define CR_TXP 0x04 /* Transmit packet */
-
-#define CR_RD0 0x08 /* Remote DMA cmd */
-#define CR_RD1 0x10
-#define CR_RD2 0x20
-
-#define CR_NODMA CR_RD2
-
-#define CR_PS0 0x40 /* Page select */
-#define CR_PS1 0x80
-
-#define CR_PAGE0 0
-#define CR_PAGE1 CR_PS0
-#define CR_PAGE2 CR_PS1
-
-/* Interrupt status reg. definitions */
-
-#define ISR_PRX 0x01 /* Packet received without errors */
-#define ISR_PTX 0x02 /* Packet transmitted without errors */
-#define ISR_RXE 0x04 /* Receive error */
-#define ISR_TXE 0x08 /* Transmit error */
-#define ISR_OVW 0x10 /* Ring buffer overrun */
-#define ISR_CNT 0x20 /* Counter overflow */
-#define ISR_RDC 0x40 /* Remote DMA compile */
-#define ISR_RST 0x80 /* Reset status */
-
-/* Data config reg. definitions */
-
-#define DCR_WTS 0x01 /* Word transfer select */
-#define DCR_BOS 0x02 /* Byte order select */
-#define DCR_LAS 0x04 /* Long address select */
-#define DCR_LS 0x08 /* Loopback select */
-#define DCR_AR 0x10 /* Auto-init remote */
-#define DCR_FT0 0x20 /* FIFO threshold select */
-#define DCR_FT1 0x40
-
-/* Transmit config reg. definitions */
-
-#define TCR_CRC 0x01 /* Inhibit CRC */
-#define TCR_LB0 0x02 /* Loopback control */
-#define TCR_LB1 0x04
-#define TCR_ATD 0x08 /* Auto transmit disable */
-#define TCR_OFST 0x10 /* Collision offset enable */
-
-/* Transmit status reg. definitions */
-
-#define TSR_PTX 0x01 /* Packet transmitted */
-#define TSR_COL 0x04 /* Transmit collided */
-#define TSR_ABT 0x08 /* Transmit aborted */
-#define TSR_CRS 0x10 /* Carrier sense lost */
-#define TSR_FU 0x20 /* FIFO underrun */
-#define TSR_CDH 0x40 /* CD Heartbeat */
-#define TSR_OWC 0x80 /* Out of Window Collision */
-
-/* Receiver config register definitions */
-
-#define RCR_SEP 0x01 /* Save errored packets */
-#define RCR_AR 0x02 /* Accept runt packets */
-#define RCR_AB 0x04 /* Accept broadcast */
-#define RCR_AM 0x08 /* Accept multicast */
-#define RCR_PRO 0x10 /* Promiscuous mode */
-#define RCR_MON 0x20 /* Monitor mode */
-
-/* Receiver status register definitions */
-
-#define RSR_PRX 0x01 /* Packet received without error */
-#define RSR_CRC 0x02 /* CRC error */
-#define RSR_FAE 0x04 /* Frame alignment error */
-#define RSR_FO 0x08 /* FIFO overrun */
-#define RSR_MPA 0x10 /* Missed packet */
-#define RSR_PHY 0x20 /* Physical address */
-#define RSR_DIS 0x40 /* Received disabled */
-#define RSR_DFR 0x80 /* Deferring (jabber) */
-
-/* Hydra System card address PROM offset */
-
-#define HYDRA_ADDRPROM 0xffc0
-
-
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index ceb98fd398af..52d01027d9e7 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -235,7 +235,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
pool->free_map[free_index] = index;
pool->skbuff[index] = NULL;
pool->consumer_index--;
@@ -373,7 +373,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
}
@@ -511,7 +511,7 @@ static int ibmveth_open(struct net_device *netdev)
adapter->filter_list_dma,
mac_address);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
adapter->buffer_list_dma,
@@ -527,7 +527,7 @@ static int ibmveth_open(struct net_device *netdev)
ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
do {
rc = h_free_logical_lan(adapter->vdev->unit_address);
- } while (H_isLongBusy(rc) || (rc == H_Busy));
+ } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
ibmveth_cleanup(adapter);
return rc;
@@ -556,9 +556,9 @@ static int ibmveth_close(struct net_device *netdev)
do {
lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
- } while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
+ } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
- if(lpar_rc != H_Success)
+ if(lpar_rc != H_SUCCESS)
{
ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
lpar_rc);
@@ -693,9 +693,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
desc[4].desc,
desc[5].desc,
correlator);
- } while ((lpar_rc == H_Busy) && (retry_count--));
+ } while ((lpar_rc == H_BUSY) && (retry_count--));
- if(lpar_rc != H_Success && lpar_rc != H_Dropped) {
+ if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
int i;
ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
for(i = 0; i < 6; i++) {
@@ -786,14 +786,14 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
/* we think we are done - reenable interrupts, then check once more to make sure we are done */
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE);
- ibmveth_assert(lpar_rc == H_Success);
+ ibmveth_assert(lpar_rc == H_SUCCESS);
netif_rx_complete(netdev);
if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed))
{
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
- ibmveth_assert(lpar_rc == H_Success);
+ ibmveth_assert(lpar_rc == H_SUCCESS);
more_work = 1;
goto restart_poll;
}
@@ -813,7 +813,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs
if(netif_rx_schedule_prep(netdev)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
- ibmveth_assert(lpar_rc == H_Success);
+ ibmveth_assert(lpar_rc == H_SUCCESS);
__netif_rx_schedule(netdev);
}
return IRQ_HANDLED;
@@ -835,7 +835,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
IbmVethMcastEnableRecv |
IbmVethMcastDisableFiltering,
0);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
}
} else {
@@ -847,7 +847,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
IbmVethMcastDisableFiltering |
IbmVethMcastClearFilterTable,
0);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
}
/* add the addresses to the filter table */
@@ -858,7 +858,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastAddFilter,
mcast_addr);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
}
}
@@ -867,7 +867,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastEnableFiltering,
0);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
}
}
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6e2ec56cde0b..96bdb73c2283 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1,7 +1,7 @@
/*****************************************************************************
*
* Filename: irda-usb.c
- * Version: 0.9b
+ * Version: 0.10
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
+ * Copyright (C) 2005, Milan Beno <beno@pobox.sk>
+ * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -61,6 +64,7 @@
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/usb.h>
+#include <linux/firmware.h>
#include "irda-usb.h"
@@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = {
{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
/* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
{ USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
+ /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
+ { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+ { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+ { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
- USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.bInterfaceClass = USB_CLASS_APP_SPEC,
.bInterfaceSubClass = USB_CLASS_IRDA,
.driver_info = IUC_DEFAULT, },
@@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles);
/*------------------------------------------------------------------*/
+static void irda_usb_init_qos(struct irda_usb_cb *self) ;
static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf);
static void irda_usb_disconnect(struct usb_interface *intf);
static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
@@ -141,7 +150,24 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
__u8 *header,
int force)
{
- /* Set the negotiated link speed */
+ /* Here we check if we have an STIR421x chip,
+ * and if either speed or xbofs (or both) needs
+ * to be changed.
+ */
+ if (self->capability & IUC_STIR_4210 &&
+ ((self->new_speed != -1) || (self->new_xbofs != -1))) {
+
+ /* With STIR421x, speed and xBOFs must be set at the same
+ * time, even if only one of them changes.
+ */
+ if (self->new_speed == -1)
+ self->new_speed = self->speed ;
+
+ if (self->new_xbofs == -1)
+ self->new_xbofs = self->xbofs ;
+ }
+
+ /* Set the link speed */
if (self->new_speed != -1) {
/* Hum... Ugly hack :-(
* Some device are not compliant with the spec and change
@@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
*header = SPEED_4000000;
self->new_xbofs = 0;
break;
- }
+ case 16000000:
+ *header = SPEED_16000000;
+ self->new_xbofs = 0;
+ break;
+ }
} else
/* No change */
*header = 0;
@@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
}
}
+/*
+* calculate turnaround time for SigmaTel header
+*/
+static __u8 get_turnaround_time(struct sk_buff *skb)
+{
+ int turnaround_time = irda_get_mtt(skb);
+
+ if ( turnaround_time == 0 )
+ return 0;
+ else if ( turnaround_time <= 10 )
+ return 1;
+ else if ( turnaround_time <= 50 )
+ return 2;
+ else if ( turnaround_time <= 100 )
+ return 3;
+ else if ( turnaround_time <= 500 )
+ return 4;
+ else if ( turnaround_time <= 1000 )
+ return 5;
+ else if ( turnaround_time <= 5000 )
+ return 6;
+ else
+ return 7;
+}
+
+
/*------------------------------------------------------------------*/
/*
* Send a command to change the speed of the dongle
@@ -262,12 +318,18 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/* Set the new speed and xbofs in this fake frame */
irda_usb_build_header(self, frame, 1);
+ if ( self->capability & IUC_STIR_4210 ) {
+ if (frame[0] == 0) return ; // do nothing if no change
+ frame[1] = 0; // other parameters don't change here
+ frame[2] = 0;
+ }
+
/* Submit the 0 length IrDA frame to trigger new speed settings */
usb_fill_bulk_urb(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
- urb->transfer_buffer_length = USB_IRDA_HEADER;
+ urb->transfer_buffer_length = self->header_length;
urb->transfer_flags = 0;
/* Irq disabled -> GFP_ATOMIC */
@@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* allocation will be done lower in skb_push().
* Also, we don't use directly skb_cow(), because it require
* headroom >= 16, which force unnecessary copies - Jean II */
- if (skb_headroom(skb) < USB_IRDA_HEADER) {
+ if (skb_headroom(skb) < self->header_length) {
IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
- if (skb_cow(skb, USB_IRDA_HEADER)) {
+ if (skb_cow(skb, self->header_length)) {
IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
goto drop;
}
}
/* Change setting for next frame */
- irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0);
+
+ if ( self->capability & IUC_STIR_4210 ) {
+ __u8 turnaround_time;
+ __u8* frame;
+ turnaround_time = get_turnaround_time( skb );
+ frame= skb_push(skb, self->header_length);
+ irda_usb_build_header(self, frame, 0);
+ frame[2] = turnaround_time;
+ if ((skb->len != 0) &&
+ ((skb->len % 128) == 0) &&
+ ((skb->len % 512) != 0)) {
+ /* add extra byte for special SigmaTel feature */
+ frame[1] = 1;
+ skb_put(skb, 1);
+ } else {
+ frame[1] = 0;
+ }
+ } else {
+ irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
+ }
/* FIXME: Make macro out of this one */
((struct irda_skb_cb *)skb->cb)->context = self;
@@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
}
/* Check for empty frames */
- if (urb->actual_length <= USB_IRDA_HEADER) {
+ if (urb->actual_length <= self->header_length) {
IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
goto done;
}
@@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
/* Allocate a new skb */
- newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+ if ( self->capability & IUC_STIR_4210 )
+ newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
+ else
+ newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+
if (!newskb) {
self->stats.rx_dropped++;
/* We could deliver the current skb, but this would stall
@@ -845,7 +930,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
/* Set proper length on skb & remove USB-IrDA header */
skb_put(dataskb, urb->actual_length);
- skb_pull(dataskb, USB_IRDA_HEADER);
+ skb_pull(dataskb, self->header_length);
/* Ask the networking layer to queue the packet for the IrDA stack */
dataskb->dev = self->netdev;
@@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
return 0; /* For now */
}
+
+#define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: "
+#define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: "
+#define STIR421X_PATCH_DATA_TAG_STR "STMP"
+#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */
+#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */
+#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */
+
+/*
+ * Known firmware patches for STIR421x dongles
+ */
+static char * stir421x_patches[] = {
+ "42101001.sb",
+ "42101002.sb",
+};
+
+static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
+{
+ unsigned int version_offset;
+ unsigned long version_major, version_minor, version_build;
+ unsigned char * version_start;
+ int version_found = 0;
+
+ for (version_offset = 0;
+ version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
+ version_offset++) {
+ if (!memcmp(patch + version_offset,
+ STIR421X_PATCH_PRODUCT_VERSION_STR,
+ sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
+ version_found = 1;
+ version_start = patch +
+ version_offset +
+ sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
+ break;
+ }
+ }
+
+ /* We couldn't find a product version on this patch */
+ if (!version_found)
+ return -EINVAL;
+
+ /* Let's check if the product version is dotted */
+ if (version_start[3] != '.' ||
+ version_start[7] != '.')
+ return -EINVAL;
+
+ version_major = simple_strtoul(version_start, NULL, 10);
+ version_minor = simple_strtoul(version_start + 4, NULL, 10);
+ version_build = simple_strtoul(version_start + 8, NULL, 10);
+
+ IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
+ __FUNCTION__,
+ version_major, version_minor, version_build);
+
+ return (((version_major) << 12) +
+ ((version_minor) << 8) +
+ ((version_build / 10) << 4) +
+ (version_build % 10));
+
+}
+
+
+static int stir421x_upload_patch (struct irda_usb_cb *self,
+ unsigned char * patch,
+ const unsigned int patch_len)
+{
+ int retval = 0;
+ int actual_len;
+ unsigned int i = 0, download_amount = 0;
+ unsigned char * patch_chunk;
+
+ IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
+
+ patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
+ if (patch_chunk == NULL)
+ return -ENOMEM;
+
+ /* break up patch into 1023-byte sections */
+ for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
+ download_amount = patch_len - i;
+ if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
+ download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
+
+ /* download the patch section */
+ memcpy(patch_chunk, patch + i, download_amount);
+
+ retval = usb_bulk_msg (self->usbdev,
+ usb_sndbulkpipe (self->usbdev,
+ self->bulk_out_ep),
+ patch_chunk, download_amount,
+ &actual_len, msecs_to_jiffies (500));
+ IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
+ actual_len);
+ if (retval == 0)
+ mdelay(10);
+ }
+
+ kfree(patch_chunk);
+
+ if (i != patch_len) {
+ IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
+ __FUNCTION__, i, patch_len);
+ retval = -EIO;
+ }
+
+ if (retval < 0)
+ /* todo - mark device as not ready */
+ IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
+ __FUNCTION__, retval);
+
+ return retval;
+}
+
+
+static int stir421x_patch_device(struct irda_usb_cb *self)
+{
+ unsigned int i, patch_found = 0, data_found = 0, data_offset;
+ int patch_version, ret = 0;
+ const struct firmware *fw_entry;
+
+ for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
+ if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
+ IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
+ continue;
+ }
+
+ /* We found a patch from userspace */
+ patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
+
+ if (patch_version < 0) {
+ /* Couldn't fetch a version, let's move on to the next file */
+ IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
+ ret = patch_version;
+ release_firmware(fw_entry);
+ continue;
+ }
+
+ if (patch_version != self->usbdev->descriptor.bcdDevice) {
+ /* Patch version and device don't match */
+ IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
+ __FUNCTION__,
+ patch_version, self->usbdev->descriptor.bcdDevice);
+ ret = -EINVAL;
+ release_firmware(fw_entry);
+ continue;
+ }
+
+ /* If we're here, we've found a correct patch */
+ patch_found = 1;
+ break;
+
+ }
+
+ /* We couldn't find a valid firmware, let's leave */
+ if (!patch_found)
+ return ret;
+
+ /* The actual image starts after the "STMP" keyword */
+ for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
+ if (!memcmp(fw_entry->data + data_offset,
+ STIR421X_PATCH_DATA_TAG_STR,
+ sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
+ IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
+ __FUNCTION__, data_offset);
+ data_found = 1;
+ break;
+ }
+ }
+
+ /* We couldn't find "STMP" from the header */
+ if (!data_found)
+ return -EINVAL;
+
+ /* Let's upload the patch to the target */
+ ret = stir421x_upload_patch(self,
+ &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
+ fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
+
+ release_firmware(fw_entry);
+
+ return ret;
+
+}
+
+
/********************** IRDA DEVICE CALLBACKS **********************/
/*
* Main calls from the IrDA/Network subsystem.
@@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev)
return -1;
}
+ if(self->needspatch) {
+ IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
+ return -EIO ;
+ }
+
/* Initialise default speed and xbofs value
* (IrLAP will change that soon) */
self->speed = -1;
@@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev)
del_timer(&self->rx_defer_timer);
/* Deallocate all the Rx path buffers (URBs and skb) */
- for (i = 0; i < IU_MAX_RX_URBS; i++) {
+ for (i = 0; i < self->max_rx_urb; i++) {
struct urb *urb = self->rx_urb[i];
struct sk_buff *skb = (struct sk_buff *) urb->context;
/* Cancel the receive command */
@@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf,
spin_lock_init(&self->lock);
init_timer(&self->rx_defer_timer);
+ self->capability = id->driver_info;
+ self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
+
/* Create all of the needed urbs */
- for (i = 0; i < IU_MAX_RX_URBS; i++) {
+ if (self->capability & IUC_STIR_4210) {
+ self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
+ self->header_length = USB_IRDA_SIGMATEL_HEADER;
+ } else {
+ self->max_rx_urb = IU_MAX_RX_URBS;
+ self->header_length = USB_IRDA_HEADER;
+ }
+
+ self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *),
+ GFP_KERNEL);
+
+ for (i = 0; i < self->max_rx_urb; i++) {
self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!self->rx_urb[i]) {
goto err_out_1;
@@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf,
goto err_out_3;
}
+ self->usbdev = dev;
+
/* Find IrDA class descriptor */
irda_desc = irda_usb_find_class_desc(intf);
ret = -ENODEV;
if (irda_desc == NULL)
goto err_out_3;
+ if (self->needspatch) {
+ ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
+ 0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500));
+ if (ret < 0) {
+ IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
+ goto err_out_3;
+ } else {
+ mdelay(10);
+ }
+ }
+
self->irda_desc = irda_desc;
self->present = 1;
self->netopen = 0;
- self->capability = id->driver_info;
- self->usbdev = dev;
self->usbintf = intf;
/* Allocate the buffer for speed changes */
@@ -1508,8 +1808,32 @@ static int irda_usb_probe(struct usb_interface *intf,
IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self);
+
+ if (self->needspatch) {
+ /* Now we fetch and upload the firmware patch */
+ ret = stir421x_patch_device(self);
+ self->needspatch = (ret < 0);
+ if (ret < 0) {
+ printk("patch_device failed\n");
+ goto err_out_5;
+ }
+
+ /* replace IrDA class descriptor with what patched device is now reporting */
+ irda_desc = irda_usb_find_class_desc (self->usbintf);
+ if (irda_desc == NULL) {
+ ret = -ENODEV;
+ goto err_out_5;
+ }
+ if (self->irda_desc)
+ kfree (self->irda_desc);
+ self->irda_desc = irda_desc;
+ irda_usb_init_qos(self);
+ }
+
return 0;
+err_out_5:
+ unregister_netdev(self->netdev);
err_out_4:
kfree(self->speed_buff);
err_out_3:
@@ -1518,7 +1842,7 @@ err_out_3:
err_out_2:
usb_free_urb(self->tx_urb);
err_out_1:
- for (i = 0; i < IU_MAX_RX_URBS; i++) {
+ for (i = 0; i < self->max_rx_urb; i++) {
if (self->rx_urb[i])
usb_free_urb(self->rx_urb[i]);
}
@@ -1571,7 +1895,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
/*netif_device_detach(self->netdev);*/
netif_stop_queue(self->netdev);
/* Stop all the receive URBs. Must be synchronous. */
- for (i = 0; i < IU_MAX_RX_URBS; i++)
+ for (i = 0; i < self->max_rx_urb; i++)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
* Make sure it's synchronous to avoid races. */
@@ -1586,8 +1910,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
self->usbintf = NULL;
/* Clean up our urbs */
- for (i = 0; i < IU_MAX_RX_URBS; i++)
+ for (i = 0; i < self->max_rx_urb; i++)
usb_free_urb(self->rx_urb[i]);
+ kfree(self->rx_urb);
/* Clean up Tx and speed URB */
usb_free_urb(self->tx_urb);
usb_free_urb(self->speed_urb);
@@ -1648,6 +1973,6 @@ module_exit(usb_irda_cleanup);
*/
module_param(qos_mtt_bits, int, 0);
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
-MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>");
-MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
+MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index 4026af42dd47..d833db52cebf 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -1,7 +1,7 @@
/*****************************************************************************
*
* Filename: irda-usb.h
- * Version: 0.9b
+ * Version: 0.10
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
* Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2000, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
+ * Copyright (C) 2005, Milan Beno <beno@pobox.sk>
+ * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,6 +34,9 @@
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> /* struct irlap_cb */
+#define PATCH_FILE_SIZE_MAX 65536
+#define PATCH_FILE_SIZE_MIN 80
+
#define RX_COPY_THRESHOLD 200
#define IRDA_USB_MAX_MTU 2051
#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
@@ -79,15 +85,16 @@
/* Inbound header */
#define MEDIA_BUSY 0x80
-#define SPEED_2400 0x01
-#define SPEED_9600 0x02
-#define SPEED_19200 0x03
-#define SPEED_38400 0x04
-#define SPEED_57600 0x05
-#define SPEED_115200 0x06
-#define SPEED_576000 0x07
-#define SPEED_1152000 0x08
-#define SPEED_4000000 0x09
+#define SPEED_2400 0x01
+#define SPEED_9600 0x02
+#define SPEED_19200 0x03
+#define SPEED_38400 0x04
+#define SPEED_57600 0x05
+#define SPEED_115200 0x06
+#define SPEED_576000 0x07
+#define SPEED_1152000 0x08
+#define SPEED_4000000 0x09
+#define SPEED_16000000 0x0a
/* Basic capabilities */
#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */
@@ -100,11 +107,14 @@
#define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */
#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
+#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */
/* USB class definitions */
-#define USB_IRDA_HEADER 0x01
-#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
-#define USB_DT_IRDA 0x21
+#define USB_IRDA_HEADER 0x01
+#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
+#define USB_DT_IRDA 0x21
+#define USB_IRDA_SIGMATEL_HEADER 0x03
+#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
struct irda_class_desc {
__u8 bLength;
@@ -123,6 +133,7 @@ struct irda_class_desc {
* (6.2.5, USB-IrDA class spec 1.0) */
#define IU_REQ_GET_CLASS_DESC 0x06
+#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023
struct irda_usb_cb {
struct irda_class_desc *irda_desc;
@@ -136,7 +147,8 @@ struct irda_usb_cb {
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
- struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
+ __u8 max_rx_urb;
+ struct urb **rx_urb; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
struct urb *speed_urb; /* URB used to send speed commands */
@@ -157,6 +169,9 @@ struct irda_usb_cb {
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
+ __u8 header_length; /* USB-IrDA frame header size */
+ int needspatch; /* device needs firmware patch */
+
struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
};
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 63d38fbbd04e..f530686bd09f 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -695,8 +695,7 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/*
* We must not be transmitting...
*/
- if (si->txskb)
- BUG();
+ BUG_ON(si->txskb);
netif_stop_queue(dev);
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index ec94ecdb103d..58f76cefbc83 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -11,6 +11,7 @@
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
* Copyright (c) 2002 Jean Tourrilhes
+ * Copyright (c) 2006 Linus Walleij
*
*
* Based on smc-ircc.c:
@@ -61,6 +62,9 @@
#include <linux/spinlock.h>
#include <linux/pm.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
@@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
/* Types */
+#ifdef CONFIG_PCI
+struct smsc_ircc_subsystem_configuration {
+ unsigned short vendor; /* PCI vendor ID */
+ unsigned short device; /* PCI vendor ID */
+ unsigned short subvendor; /* PCI subsystem vendor ID */
+ unsigned short subdevice; /* PCI sybsystem device ID */
+ unsigned short sir_io; /* I/O port for SIR */
+ unsigned short fir_io; /* I/O port for FIR */
+ unsigned char fir_irq; /* FIR IRQ */
+ unsigned char fir_dma; /* FIR DMA */
+ unsigned short cfg_base; /* I/O port for chip configuration */
+ int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */
+ const char *name; /* name shown as info */
+};
+#endif
+
struct smsc_transceiver {
char *name;
void (*set_for_speed)(int fir_base, u32 speed);
@@ -202,6 +222,18 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor
static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
static int __init smsc_superio_fdc(unsigned short cfg_base);
static int __init smsc_superio_lpc(unsigned short cfg_base);
+#ifdef CONFIG_PCI
+static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
+static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
+static void __init preconfigure_ali_port(struct pci_dev *dev,
+ unsigned short port);
+static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
+static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
+ unsigned short ircc_fir,
+ unsigned short ircc_sir,
+ unsigned char ircc_dma,
+ unsigned char ircc_irq);
+#endif
/* Transceivers specific functions */
@@ -353,6 +385,13 @@ 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 (ircc_fir > 0 && ircc_sir > 0) {
@@ -2285,6 +2324,490 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
return ret;
}
+/*
+ * Look for some specific subsystem setups that need
+ * pre-configuration not properly done by the BIOS (especially laptops)
+ * This code is based in part on smcinit.c, tosh1800-smcinit.c
+ * and tosh2450-smcinit.c. The table lists the device entries
+ * for ISA bridges with an LPC (Low Pin Count) controller which
+ * handles the communication with the SMSC device. After the LPC
+ * controller is initialized through PCI, the SMSC device is initialized
+ * through a dedicated port in the ISA port-mapped I/O area, this latter
+ * area is used to configure the SMSC device with default
+ * SIR and FIR I/O ports, DMA and IRQ. Different vendors have
+ * used different sets of parameters and different control port
+ * addresses making a subsystem device table necessary.
+ */
+#ifdef CONFIG_PCI
+#define PCIID_VENDOR_INTEL 0x8086
+#define PCIID_VENDOR_ALI 0x10b9
+static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
+ {
+ .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .device = 0x24cc,
+ .subvendor = 0x103c,
+ .subdevice = 0x088c,
+ /* Quite certain these are the same for nc8000 as for nc6000 */
+ .sir_io = 0x02f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x05,
+ .fir_dma = 0x03,
+ .cfg_base = 0x004e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "HP nc8000",
+ },
+ {
+ .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .device = 0x24cc,
+ .subvendor = 0x103c,
+ .subdevice = 0x0890,
+ .sir_io = 0x02f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x05,
+ .fir_dma = 0x03,
+ .cfg_base = 0x004e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "HP nc6000",
+ },
+ {
+ /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
+ .vendor = PCIID_VENDOR_INTEL,
+ .device = 0x24c0,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x03f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x07,
+ .fir_dma = 0x01,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
+ },
+ {
+ .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
+ .device = 0x248c,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x03f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x03,
+ .fir_dma = 0x03,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "Toshiba laptop with Intel 82801CAM ISA bridge",
+ },
+ {
+ /* 82801DBM (ICH4-M) LPC Interface Bridge */
+ .vendor = PCIID_VENDOR_INTEL,
+ .device = 0x24cc,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x03f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x03,
+ .fir_dma = 0x03,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "Toshiba laptop with Intel 8281DBM LPC bridge",
+ },
+ {
+ /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
+ .vendor = PCIID_VENDOR_ALI,
+ .device = 0x1533,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x02e8,
+ .fir_io = 0x02f8,
+ .fir_irq = 0x07,
+ .fir_dma = 0x03,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_ali,
+ .name = "Toshiba laptop with ALi ISA bridge",
+ },
+ { } // Terminator
+};
+
+
+/*
+ * This sets up the basic SMSC parameters
+ * (FIR port, SIR port, FIR DMA, FIR IRQ)
+ * through the chip configuration port.
+ */
+static int __init preconfigure_smsc_chip(struct
+ smsc_ircc_subsystem_configuration
+ *conf)
+{
+ unsigned short iobase = conf->cfg_base;
+ unsigned char tmpbyte;
+
+ outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
+ outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
+ tmpbyte = inb(iobase +1); // Read device ID
+ IRDA_DEBUG(0,
+ "Detected Chip id: 0x%02x, setting up registers...\n",
+ tmpbyte);
+
+ /* Disable UART1 and set up SIR I/O port */
+ outb(0x24, iobase); // select CR24 - UART1 base addr
+ outb(0x00, iobase + 1); // disable UART1
+ outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr
+ outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8
+ tmpbyte = inb(iobase + 1);
+ if (tmpbyte != (conf->sir_io >> 2) ) {
+ IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
+ IRDA_WARNING("Try to supply ircc_cfg argument.\n");
+ return -ENXIO;
+ }
+
+ /* Set up FIR IRQ channel for UART2 */
+ outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select
+ tmpbyte = inb(iobase + 1);
+ tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion
+ tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK);
+ outb(tmpbyte, iobase + 1);
+ tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+ if (tmpbyte != conf->fir_irq) {
+ IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n");
+ return -ENXIO;
+ }
+
+ /* Set up FIR I/O port */
+ outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr
+ outb((conf->fir_io >> 3), iobase + 1);
+ tmpbyte = inb(iobase + 1);
+ if (tmpbyte != (conf->fir_io >> 3) ) {
+ IRDA_WARNING("ERROR: could not configure FIR I/O port.\n");
+ return -ENXIO;
+ }
+
+ /* Set up FIR DMA channel */
+ outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select
+ outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA
+ tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK;
+ if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) {
+ IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n");
+ return -ENXIO;
+ }
+
+ outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
+ tmpbyte = inb(iobase + 1);
+ tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK |
+ SMSCSIOFLAT_UART2MODE_VAL_IRDA;
+ outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
+
+ outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down
+
+ /* This one was not part of tosh1800 */
+ outb(0x0a, iobase); // CR0a - ecp fifo / ir mux
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port
+
+ outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down
+
+ outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done
+
+ outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration
+
+ return 0;
+}
+
+/* 82801CAM generic registers */
+#define VID 0x00
+#define DID 0x02
+#define PIRQ_A_D_ROUT 0x60
+#define SIRQ_CNTL 0x64
+#define PIRQ_E_H_ROUT 0x68
+#define PCI_DMA_C 0x90
+/* LPC-specific registers */
+#define COM_DEC 0xe0
+#define GEN1_DEC 0xe4
+#define LPC_EN 0xe6
+#define GEN2_DEC 0xec
+/*
+ * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge
+ * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge.
+ * They all work the same way!
+ */
+static int __init preconfigure_through_82801(struct pci_dev *dev,
+ struct
+ smsc_ircc_subsystem_configuration
+ *conf)
+{
+ unsigned short tmpword;
+ unsigned char tmpbyte;
+
+ IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n");
+ /*
+ * Select the range for the COMA COM port (SIR)
+ * Register COM_DEC:
+ * Bit 7: reserved
+ * Bit 6-4, COMB decode range
+ * Bit 3: reserved
+ * Bit 2-0, COMA decode range
+ *
+ * Decode ranges:
+ * 000 = 0x3f8-0x3ff (COM1)
+ * 001 = 0x2f8-0x2ff (COM2)
+ * 010 = 0x220-0x227
+ * 011 = 0x228-0x22f
+ * 100 = 0x238-0x23f
+ * 101 = 0x2e8-0x2ef (COM4)
+ * 110 = 0x338-0x33f
+ * 111 = 0x3e8-0x3ef (COM3)
+ */
+ pci_read_config_byte(dev, COM_DEC, &tmpbyte);
+ tmpbyte &= 0xf8; /* mask COMA bits */
+ switch(conf->sir_io) {
+ case 0x3f8:
+ tmpbyte |= 0x00;
+ break;
+ case 0x2f8:
+ tmpbyte |= 0x01;
+ break;
+ case 0x220:
+ tmpbyte |= 0x02;
+ break;
+ case 0x228:
+ tmpbyte |= 0x03;
+ break;
+ case 0x238:
+ tmpbyte |= 0x04;
+ break;
+ case 0x2e8:
+ tmpbyte |= 0x05;
+ break;
+ case 0x338:
+ tmpbyte |= 0x06;
+ break;
+ case 0x3e8:
+ tmpbyte |= 0x07;
+ break;
+ default:
+ tmpbyte |= 0x01; /* COM2 default */
+ }
+ IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte);
+ pci_write_config_byte(dev, COM_DEC, tmpbyte);
+
+ /* Enable Low Pin Count interface */
+ pci_read_config_word(dev, LPC_EN, &tmpword);
+ /* These seem to be set up at all times,
+ * just make sure it is properly set.
+ */
+ switch(conf->cfg_base) {
+ case 0x04e:
+ tmpword |= 0x2000;
+ break;
+ case 0x02e:
+ tmpword |= 0x1000;
+ break;
+ case 0x062:
+ tmpword |= 0x0800;
+ break;
+ case 0x060:
+ tmpword |= 0x0400;
+ break;
+ default:
+ IRDA_WARNING("Uncommon I/O base address: 0x%04x\n",
+ conf->cfg_base);
+ break;
+ }
+ tmpword &= 0xfffd; /* disable LPC COMB */
+ tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */
+ IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword);
+ pci_write_config_word(dev, LPC_EN, tmpword);
+
+ /*
+ * Configure LPC DMA channel
+ * PCI_DMA_C bits:
+ * Bit 15-14: DMA channel 7 select
+ * Bit 13-12: DMA channel 6 select
+ * Bit 11-10: DMA channel 5 select
+ * Bit 9-8: Reserved
+ * Bit 7-6: DMA channel 3 select
+ * Bit 5-4: DMA channel 2 select
+ * Bit 3-2: DMA channel 1 select
+ * Bit 1-0: DMA channel 0 select
+ * 00 = Reserved value
+ * 01 = PC/PCI DMA
+ * 10 = Reserved value
+ * 11 = LPC I/F DMA
+ */
+ pci_read_config_word(dev, PCI_DMA_C, &tmpword);
+ switch(conf->fir_dma) {
+ case 0x07:
+ tmpword |= 0xc000;
+ break;
+ case 0x06:
+ tmpword |= 0x3000;
+ break;
+ case 0x05:
+ tmpword |= 0x0c00;
+ break;
+ case 0x03:
+ tmpword |= 0x00c0;
+ break;
+ case 0x02:
+ tmpword |= 0x0030;
+ break;
+ case 0x01:
+ tmpword |= 0x000c;
+ break;
+ case 0x00:
+ tmpword |= 0x0003;
+ break;
+ default:
+ break; /* do not change settings */
+ }
+ IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword);
+ pci_write_config_word(dev, PCI_DMA_C, tmpword);
+
+ /*
+ * GEN2_DEC bits:
+ * Bit 15-4: Generic I/O range
+ * Bit 3-1: reserved (read as 0)
+ * Bit 0: enable GEN2 range on LPC I/F
+ */
+ tmpword = conf->fir_io & 0xfff8;
+ tmpword |= 0x0001;
+ IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword);
+ pci_write_config_word(dev, GEN2_DEC, tmpword);
+
+ /* Pre-configure chip */
+ return preconfigure_smsc_chip(conf);
+}
+
+/*
+ * Pre-configure a certain port on the ALi 1533 bridge.
+ * This is based on reverse-engineering since ALi does not
+ * provide any data sheet for the 1533 chip.
+ */
+static void __init preconfigure_ali_port(struct pci_dev *dev,
+ unsigned short port)
+{
+ unsigned char reg;
+ /* These bits obviously control the different ports */
+ unsigned char mask;
+ unsigned char tmpbyte;
+
+ switch(port) {
+ case 0x0130:
+ case 0x0178:
+ reg = 0xb0;
+ mask = 0x80;
+ break;
+ case 0x03f8:
+ reg = 0xb4;
+ mask = 0x80;
+ break;
+ case 0x02f8:
+ reg = 0xb4;
+ mask = 0x30;
+ break;
+ case 0x02e8:
+ reg = 0xb4;
+ mask = 0x08;
+ break;
+ default:
+ IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port);
+ return;
+ }
+
+ pci_read_config_byte(dev, reg, &tmpbyte);
+ /* Turn on the right bits */
+ tmpbyte |= mask;
+ pci_write_config_byte(dev, reg, tmpbyte);
+ IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port);
+ return;
+}
+
+static int __init preconfigure_through_ali(struct pci_dev *dev,
+ struct
+ smsc_ircc_subsystem_configuration
+ *conf)
+{
+ /* Configure the two ports on the ALi 1533 */
+ preconfigure_ali_port(dev, conf->sir_io);
+ preconfigure_ali_port(dev, conf->fir_io);
+
+ /* Pre-configure chip */
+ return preconfigure_smsc_chip(conf);
+}
+
+static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
+ unsigned short ircc_fir,
+ unsigned short ircc_sir,
+ unsigned char ircc_dma,
+ unsigned char ircc_irq)
+{
+ struct pci_dev *dev = NULL;
+ unsigned short ss_vendor = 0x0000;
+ unsigned short ss_device = 0x0000;
+ int ret = 0;
+
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+
+ while (dev != NULL) {
+ struct smsc_ircc_subsystem_configuration *conf;
+
+ /*
+ * Cache the subsystem vendor/device:
+ * some manufacturers fail to set this for all components,
+ * so we save it in case there is just 0x0000 0x0000 on the
+ * device we want to check.
+ */
+ if (dev->subsystem_vendor != 0x0000U) {
+ ss_vendor = dev->subsystem_vendor;
+ ss_device = dev->subsystem_device;
+ }
+ conf = subsystem_configurations;
+ for( ; conf->subvendor; conf++) {
+ if(conf->vendor == dev->vendor &&
+ conf->device == dev->device &&
+ conf->subvendor == ss_vendor &&
+ /* Sometimes these are cached values */
+ (conf->subdevice == ss_device ||
+ conf->subdevice == 0xffff)) {
+ struct smsc_ircc_subsystem_configuration
+ tmpconf;
+
+ memcpy(&tmpconf, conf,
+ sizeof(struct smsc_ircc_subsystem_configuration));
+
+ /*
+ * Override the default values with anything
+ * passed in as parameter
+ */
+ if (ircc_cfg != 0)
+ tmpconf.cfg_base = ircc_cfg;
+ if (ircc_fir != 0)
+ tmpconf.fir_io = ircc_fir;
+ if (ircc_sir != 0)
+ tmpconf.sir_io = ircc_sir;
+ if (ircc_dma != 0xff)
+ tmpconf.fir_dma = ircc_dma;
+ if (ircc_irq != 0xff)
+ tmpconf.fir_irq = ircc_irq;
+
+ IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
+ if (conf->preconfigure)
+ ret = conf->preconfigure(dev, &tmpconf);
+ else
+ ret = -ENODEV;
+ }
+ }
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+ }
+
+ return ret;
+}
+#endif // CONFIG_PCI
+
/************************************************
*
* Transceivers specific functions
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index f9f77e4f5965..cfd67d812f0d 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -357,18 +357,20 @@ ixgb_probe(struct pci_dev *pdev,
if((err = pci_enable_device(pdev)))
return err;
- if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
+ !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
+ (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
IXGB_ERR("No usable DMA configuration, aborting\n");
- return err;
+ goto err_dma_mask;
}
pci_using_dac = 0;
}
if((err = pci_request_regions(pdev, ixgb_driver_name)))
- return err;
+ goto err_request_regions;
pci_set_master(pdev);
@@ -502,6 +504,9 @@ err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
pci_release_regions(pdev);
+err_request_regions:
+err_dma_mask:
+ pci_disable_device(pdev);
return err;
}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 9f2661355a4a..ea62a3e7d586 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -281,10 +281,16 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
- netif_device_detach(dev);
+ if (!netif_running(dev))
+ return;
+
+ netif_stop_queue(dev);
+
eth_port_reset(mp->port_num);
eth_port_start(dev);
- netif_device_attach(dev);
+
+ if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+ netif_wake_queue(dev);
}
/**
@@ -552,9 +558,9 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
#else
if (eth_int_cause & ETH_INT_CAUSE_RX)
mv643xx_eth_receive_queue(dev, INT_MAX);
+#endif
if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
mv643xx_eth_free_completed_tx_descs(dev);
-#endif
/*
* If no real interrupt occured, exit.
@@ -1186,7 +1192,12 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
BUG_ON(netif_queue_stopped(dev));
BUG_ON(skb == NULL);
- BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
+
+ if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+ printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+ netif_stop_queue(dev);
+ return 1;
+ }
if (has_tiny_unaligned_frags(skb)) {
if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 7826afbb9db9..90627756d6fa 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -238,7 +238,7 @@ static int full_duplex[MAX_UNITS];
#define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */
/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
KERN_INFO DRV_NAME " dp8381x driver, version "
DRV_VERSION ", " DRV_RELDATE "\n"
KERN_INFO " originally by Donald Becker <becker@scyld.com>\n"
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 08b218c5bfbc..93c494bcd18d 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -226,7 +226,7 @@ struct net_device * __init ne_probe(int unit)
netdev_boot_setup_check(dev);
#ifdef CONFIG_TOSHIBA_RBTX4938
- dev->base_addr = 0x07f20280;
+ dev->base_addr = RBTX4938_RTL_8019_BASE;
dev->irq = RBTX4938_RTL_8019_IRQ;
#endif
err = do_ne_probe(dev);
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index d11821dd86ed..ced9fdb8335c 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -645,9 +645,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (!dev)
- BUG();
-
+ BUG_ON(!dev);
unregister_netdev(dev);
release_region(dev->base_addr, NE_IO_EXTENT);
free_netdev(dev);
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 75b35ad760de..66e74f740261 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
}
static struct console netconsole = {
+ .name = "netcon",
.flags = CON_ENABLED | CON_PRINTBUFFER,
.write = write_msg
};
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 8e9b1a537dee..706aed7d717f 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -568,8 +568,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb)
#endif
sg = dev->rx_info.descs + (next_empty * DESC_SIZE);
- if (unlikely(NULL != dev->rx_info.skbs[next_empty]))
- BUG();
+ BUG_ON(NULL != dev->rx_info.skbs[next_empty]);
dev->rx_info.skbs[next_empty] = skb;
dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC;
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index ce90becb8bdf..fab93360f017 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -204,7 +204,7 @@ enum Window4 { /* Window 4: Xcvr/media bits. */
#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
struct el3_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
u16 advertising, partner; /* NWay media advertisement */
@@ -225,8 +225,8 @@ static char mii_preamble_required = 0;
/* Index of functions. */
-static void tc574_config(dev_link_t *link);
-static void tc574_release(dev_link_t *link);
+static int tc574_config(struct pcmcia_device *link);
+static void tc574_release(struct pcmcia_device *link);
static void mdio_sync(kio_addr_t ioaddr, int bits);
static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
@@ -256,10 +256,9 @@ static void tc574_detach(struct pcmcia_device *p_dev);
with Card Services.
*/
-static int tc574_attach(struct pcmcia_device *p_dev)
+static int tc574_probe(struct pcmcia_device *link)
{
struct el3_private *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "3c574_attach()\n");
@@ -269,8 +268,8 @@ static int tc574_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
link->priv = dev;
+ lp->p_dev = link;
spin_lock_init(&lp->window_lock);
link->io.NumPorts1 = 32;
@@ -280,7 +279,6 @@ static int tc574_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -298,13 +296,7 @@ static int tc574_attach(struct pcmcia_device *p_dev)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- tc574_config(link);
-
- return 0;
+ return tc574_config(link);
} /* tc574_attach */
/*
@@ -316,18 +308,16 @@ static int tc574_attach(struct pcmcia_device *p_dev)
*/
-static void tc574_detach(struct pcmcia_device *p_dev)
+static void tc574_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "3c574_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- tc574_release(link);
+ tc574_release(link);
free_netdev(dev);
} /* tc574_detach */
@@ -343,9 +333,8 @@ static void tc574_detach(struct pcmcia_device *p_dev)
static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
-static void tc574_config(dev_link_t *link)
+static int tc574_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct el3_private *lp = netdev_priv(dev);
tuple_t tuple;
@@ -363,30 +352,27 @@ static void tc574_config(dev_link_t *link)
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
link->io.IOAddrLines = 16;
for (i = j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -397,8 +383,8 @@ static void tc574_config(dev_link_t *link)
the hardware address. The future products may include a modem chip
and put the address in the CIS. */
tuple.DesiredTuple = 0x88;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
- pcmcia_get_tuple_data(handle, &tuple);
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ pcmcia_get_tuple_data(link, &tuple);
for (i = 0; i < 3; i++)
phys_addr[i] = htons(buf[i]);
} else {
@@ -412,9 +398,9 @@ static void tc574_config(dev_link_t *link)
}
}
tuple.DesiredTuple = CISTPL_VERS_1;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS &&
- pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS &&
- pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS &&
+ pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS &&
+ pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) {
cardname = parse.version_1.str + parse.version_1.ofs[1];
} else
cardname = "3Com 3c574";
@@ -473,13 +459,12 @@ static void tc574_config(dev_link_t *link)
}
}
- link->state &= ~DEV_CONFIG_PENDING;
- link->dev = &lp->node;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -493,13 +478,13 @@ static void tc574_config(dev_link_t *link)
8 << config.u.ram_size, ram_split[config.u.ram_split],
config.u.autoselect ? "autoselect " : "");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
tc574_release(link);
- return;
+ return -ENODEV;
} /* tc574_config */
@@ -509,44 +494,28 @@ failed:
still open, this will be postponed until it is closed.
*/
-static void tc574_release(dev_link_t *link)
+static void tc574_release(struct pcmcia_device *link)
{
- DEBUG(0, "3c574_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int tc574_suspend(struct pcmcia_device *p_dev)
+static int tc574_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int tc574_resume(struct pcmcia_device *p_dev)
+static int tc574_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- tc574_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ tc574_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -757,9 +726,9 @@ static void tc574_reset(struct net_device *dev)
static int el3_open(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1203,11 +1172,11 @@ static int el3_close(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
unsigned long flags;
/* Turn off statistics ASAP. We update lp->stats below. */
@@ -1246,7 +1215,7 @@ static struct pcmcia_driver tc574_driver = {
.drv = {
.name = "3c574_cs",
},
- .probe = tc574_attach,
+ .probe = tc574_probe,
.remove = tc574_detach,
.id_table = tc574_ids,
.suspend = tc574_suspend,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 3dba50849da7..875a0fe251e7 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -105,7 +105,7 @@ enum RxFilter {
#define TX_TIMEOUT ((400*HZ)/1000)
struct el3_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
/* For transceiver monitoring */
@@ -142,8 +142,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
/*====================================================================*/
-static void tc589_config(dev_link_t *link);
-static void tc589_release(dev_link_t *link);
+static int tc589_config(struct pcmcia_device *link);
+static void tc589_release(struct pcmcia_device *link);
static u16 read_eeprom(kio_addr_t ioaddr, int index);
static void tc589_reset(struct net_device *dev);
@@ -170,10 +170,9 @@ static void tc589_detach(struct pcmcia_device *p_dev);
======================================================================*/
-static int tc589_attach(struct pcmcia_device *p_dev)
+static int tc589_probe(struct pcmcia_device *link)
{
struct el3_private *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "3c589_attach()\n");
@@ -183,8 +182,8 @@ static int tc589_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
link->priv = dev;
+ lp->p_dev = link;
spin_lock_init(&lp->lock);
link->io.NumPorts1 = 16;
@@ -194,7 +193,6 @@ static int tc589_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -213,13 +211,7 @@ static int tc589_attach(struct pcmcia_device *p_dev)
#endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- tc589_config(link);
-
- return 0;
+ return tc589_config(link);
} /* tc589_attach */
/*======================================================================
@@ -231,18 +223,16 @@ static int tc589_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void tc589_detach(struct pcmcia_device *p_dev)
+static void tc589_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "3c589_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- tc589_release(link);
+ tc589_release(link);
free_netdev(dev);
} /* tc589_detach */
@@ -258,9 +248,8 @@ static void tc589_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void tc589_config(dev_link_t *link)
+static int tc589_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct el3_private *lp = netdev_priv(dev);
tuple_t tuple;
@@ -275,43 +264,40 @@ static void tc589_config(dev_link_t *link)
phys_addr = (u16 *)dev->dev_addr;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Is this a 3c562? */
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
if (le16_to_cpu(buf[0]) != MANFID_3COM)
printk(KERN_INFO "3c589_cs: hmmm, is this really a "
"3Com card??\n");
multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562);
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
/* For the 3c562, the base address must be xx00-xx7f */
link->io.IOAddrLines = 16;
for (i = j = 0; j < 0x400; j += 0x10) {
if (multi && (j & 0x80)) continue;
link->io.BasePort1 = j ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -321,8 +307,8 @@ static void tc589_config(dev_link_t *link)
/* The 3c589 has an extra EEPROM for configuration info, including
the hardware address. The 3c562 puts the address in the CIS. */
tuple.DesiredTuple = 0x88;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
- pcmcia_get_tuple_data(handle, &tuple);
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ pcmcia_get_tuple_data(link, &tuple);
for (i = 0; i < 3; i++)
phys_addr[i] = htons(buf[i]);
} else {
@@ -346,13 +332,12 @@ static void tc589_config(dev_link_t *link)
else
printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -366,14 +351,13 @@ static void tc589_config(dev_link_t *link)
printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n",
(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
if_names[dev->if_port]);
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
tc589_release(link);
- return;
-
+ return -ENODEV;
} /* tc589_config */
/*======================================================================
@@ -384,44 +368,28 @@ failed:
======================================================================*/
-static void tc589_release(dev_link_t *link)
+static void tc589_release(struct pcmcia_device *link)
{
- DEBUG(0, "3c589_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int tc589_suspend(struct pcmcia_device *p_dev)
+static int tc589_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int tc589_resume(struct pcmcia_device *p_dev)
+static int tc589_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- tc589_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ tc589_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -587,9 +555,9 @@ static int el3_config(struct net_device *dev, struct ifmap *map)
static int el3_open(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -848,9 +816,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
unsigned long flags;
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
spin_lock_irqsave(&lp->lock, flags);
update_stats(dev);
spin_unlock_irqrestore(&lp->lock, flags);
@@ -950,11 +918,11 @@ static int el3_rx(struct net_device *dev)
static void set_multicast_list(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
kio_addr_t ioaddr = dev->base_addr;
u16 opts = SetRxFilter | RxStation | RxBroadcast;
- if (!(DEV_OK(link))) return;
+ if (!pcmcia_dev_present(link)) return;
if (dev->flags & IFF_PROMISC)
opts |= RxMulticast | RxProm;
else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -965,12 +933,12 @@ static void set_multicast_list(struct net_device *dev)
static int el3_close(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
kio_addr_t ioaddr = dev->base_addr;
DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
/* Turn off statistics ASAP. We update lp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1020,7 +988,7 @@ static struct pcmcia_driver tc589_driver = {
.drv = {
.name = "3c589_cs",
},
- .probe = tc589_attach,
+ .probe = tc589_probe,
.remove = tc589_detach,
.id_table = tc589_ids,
.suspend = tc589_suspend,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 1cc94b2d76c1..448a09488529 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -86,8 +86,8 @@ static char *version =
/*====================================================================*/
-static void axnet_config(dev_link_t *link);
-static void axnet_release(dev_link_t *link);
+static int axnet_config(struct pcmcia_device *link);
+static void axnet_release(struct pcmcia_device *link);
static int axnet_open(struct net_device *dev);
static int axnet_close(struct net_device *dev);
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -117,7 +117,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*====================================================================*/
typedef struct axnet_dev_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
caddr_t base;
struct timer_list watchdog;
@@ -142,10 +142,9 @@ static inline axnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/
-static int axnet_attach(struct pcmcia_device *p_dev)
+static int axnet_probe(struct pcmcia_device *link)
{
axnet_dev_t *info;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "axnet_attach()\n");
@@ -157,7 +156,7 @@ static int axnet_attach(struct pcmcia_device *p_dev)
return -ENOMEM;
info = PRIV(dev);
- link = &info->link;
+ info->p_dev = link;
link->priv = dev;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -169,13 +168,7 @@ static int axnet_attach(struct pcmcia_device *p_dev)
dev->do_ioctl = &axnet_ioctl;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- axnet_config(link);
-
- return 0;
+ return axnet_config(link);
} /* axnet_attach */
/*======================================================================
@@ -187,18 +180,16 @@ static int axnet_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void axnet_detach(struct pcmcia_device *p_dev)
+static void axnet_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "axnet_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- axnet_release(link);
+ axnet_release(link);
free_netdev(dev);
} /* axnet_detach */
@@ -209,7 +200,7 @@ static void axnet_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static int get_prom(dev_link_t *link)
+static int get_prom(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -263,7 +254,7 @@ static int get_prom(dev_link_t *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
{
int j, ret;
if (link->io.NumPorts1 == 32) {
@@ -284,25 +275,23 @@ static int try_io_port(dev_link_t *link)
for (j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
} else {
- return pcmcia_request_io(link->handle, &link->io);
+ return pcmcia_request_io(link, &link->io);
}
}
-static void axnet_config(dev_link_t *link)
+static int axnet_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
axnet_dev_t *info = PRIV(dev);
tuple_t tuple;
cisparse_t parse;
int i, j, last_ret, last_fn;
u_short buf[64];
- config_info_t conf;
DEBUG(0, "axnet_config(0x%p)\n", link);
@@ -311,29 +300,22 @@ static void axnet_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
/* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (last_ret == CS_SUCCESS) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_io_t *io = &(parse.cftable_entry.io);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
cfg->index == 0 || cfg->io.nwin == 0)
goto next_entry;
@@ -355,21 +337,21 @@ static void axnet_config(dev_link_t *link)
if (last_ret == CS_SUCCESS) break;
}
next_entry:
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
}
if (last_ret != CS_SUCCESS) {
- cs_error(handle, RequestIO, last_ret);
+ cs_error(link, RequestIO, last_ret);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
if (link->io.NumPorts2 == 8) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -406,7 +388,7 @@ static void axnet_config(dev_link_t *link)
Bit 2 of CCSR is active low. */
if (i == 32) {
conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
for (i = 0; i < 32; i++) {
j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
if ((j != 0) && (j != 0xffff)) break;
@@ -414,13 +396,12 @@ static void axnet_config(dev_link_t *link)
}
info->phy_id = (i < 32) ? i : -1;
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -436,14 +417,13 @@ static void axnet_config(dev_link_t *link)
} else {
printk(KERN_NOTICE " No MII transceivers found!\n");
}
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
axnet_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
} /* axnet_config */
/*======================================================================
@@ -454,45 +434,29 @@ failed:
======================================================================*/
-static void axnet_release(dev_link_t *link)
+static void axnet_release(struct pcmcia_device *link)
{
- DEBUG(0, "axnet_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int axnet_suspend(struct pcmcia_device *p_dev)
+static int axnet_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int axnet_resume(struct pcmcia_device *p_dev)
+static int axnet_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- axnet_reset_8390(dev);
- AX88190_init(dev, 1);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ axnet_reset_8390(dev);
+ AX88190_init(dev, 1);
+ netif_device_attach(dev);
}
return 0;
@@ -562,11 +526,11 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
axnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
+ struct pcmcia_device *link = info->p_dev;
DEBUG(2, "axnet_open('%s')\n", dev->name);
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -588,7 +552,7 @@ static int axnet_open(struct net_device *dev)
static int axnet_close(struct net_device *dev)
{
axnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
+ struct pcmcia_device *link = info->p_dev;
DEBUG(2, "axnet_close('%s')\n", dev->name);
@@ -833,7 +797,7 @@ static struct pcmcia_driver axnet_cs_driver = {
.drv = {
.name = "axnet_cs",
},
- .probe = axnet_attach,
+ .probe = axnet_probe,
.remove = axnet_detach,
.id_table = axnet_ids,
.suspend = axnet_suspend,
@@ -1596,7 +1560,7 @@ static void ei_receive(struct net_device *dev)
static void ei_rx_overrun(struct net_device *dev)
{
- axnet_dev_t *info = (axnet_dev_t *)dev;
+ axnet_dev_t *info = PRIV(dev);
long e8390_base = dev->base_addr;
unsigned char was_txing, must_resend = 0;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 2827a48ea37c..441de824ab6b 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -118,8 +118,8 @@ MODULE_LICENSE("GPL");
/*====================================================================*/
-static void com20020_config(dev_link_t *link);
-static void com20020_release(dev_link_t *link);
+static int com20020_config(struct pcmcia_device *link);
+static void com20020_release(struct pcmcia_device *link);
static void com20020_detach(struct pcmcia_device *p_dev);
@@ -138,9 +138,8 @@ typedef struct com20020_dev_t {
======================================================================*/
-static int com20020_attach(struct pcmcia_device *p_dev)
+static int com20020_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
com20020_dev_t *info;
struct net_device *dev;
struct arcnet_local *lp;
@@ -148,10 +147,6 @@ static int com20020_attach(struct pcmcia_device *p_dev)
DEBUG(0, "com20020_attach()\n");
/* Create new network device */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
-
info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
if (!info)
goto fail_alloc_info;
@@ -161,7 +156,6 @@ static int com20020_attach(struct pcmcia_device *p_dev)
goto fail_alloc_dev;
memset(info, 0, sizeof(struct com20020_dev_t));
- memset(link, 0, sizeof(struct dev_link_t));
lp = dev->priv;
lp->timeout = timeout;
lp->backplane = backplane;
@@ -172,28 +166,23 @@ static int com20020_attach(struct pcmcia_device *p_dev)
/* fill in our module parameters as defaults */
dev->dev_addr[0] = node;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts1 = 16;
- link->io.IOAddrLines = 16;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
-
- link->irq.Instance = info->dev = dev;
- link->priv = info;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.IOAddrLines = 16;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.Present = PRESENT_OPTION;
- link->state |= DEV_PRESENT;
- com20020_config(link);
+ p_dev->irq.Instance = info->dev = dev;
+ p_dev->priv = info;
- return 0;
+ return com20020_config(p_dev);
fail_alloc_dev:
kfree(info);
fail_alloc_info:
- kfree(link);
return -ENOMEM;
} /* com20020_attach */
@@ -206,9 +195,8 @@ fail_alloc_info:
======================================================================*/
-static void com20020_detach(struct pcmcia_device *p_dev)
+static void com20020_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
@@ -216,7 +204,7 @@ static void com20020_detach(struct pcmcia_device *p_dev)
DEBUG(0, "com20020_detach(0x%p)\n", link);
- if (link->dev) {
+ if (link->dev_node) {
DEBUG(1,"unregister...\n");
unregister_netdev(dev);
@@ -229,8 +217,7 @@ static void com20020_detach(struct pcmcia_device *p_dev)
free_irq(dev->irq, dev);
}
- if (link->state & DEV_CONFIG)
- com20020_release(link);
+ com20020_release(link);
/* Unlink device structure, free bits */
DEBUG(1,"unlinking...\n");
@@ -245,8 +232,6 @@ static void com20020_detach(struct pcmcia_device *p_dev)
DEBUG(1,"kfree2...\n");
kfree(info);
}
- DEBUG(1,"kfree3...\n");
- kfree(link);
} /* com20020_detach */
@@ -261,10 +246,9 @@ static void com20020_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void com20020_config(dev_link_t *link)
+static int com20020_config(struct pcmcia_device *link)
{
struct arcnet_local *lp;
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
com20020_dev_t *info;
@@ -273,7 +257,6 @@ static void com20020_config(dev_link_t *link)
u_char buf[64];
int ioaddr;
- handle = link->handle;
info = link->priv;
dev = info->dev;
@@ -286,14 +269,11 @@ static void com20020_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
i = !CS_SUCCESS;
if (!link->io.BasePort1)
@@ -301,13 +281,13 @@ static void com20020_config(dev_link_t *link)
for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
{
link->io.BasePort1 = ioaddr;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
}
else
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i != CS_SUCCESS)
{
@@ -321,7 +301,7 @@ static void com20020_config(dev_link_t *link)
DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
link->irq.AssignedIRQ,
link->irq.IRQInfo1, link->irq.IRQInfo2);
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS)
{
DEBUG(1,"arcnet: requestIRQ failed totally!\n");
@@ -330,7 +310,7 @@ static void com20020_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (com20020_check(dev))
{
@@ -342,15 +322,14 @@ static void com20020_config(dev_link_t *link)
lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) {
DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -358,13 +337,14 @@ static void com20020_config(dev_link_t *link)
DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
dev->name, dev->base_addr, dev->irq);
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
DEBUG(1,"com20020_config failed...\n");
com20020_release(link);
+ return -ENODEV;
} /* com20020_config */
/*======================================================================
@@ -375,52 +355,33 @@ failed:
======================================================================*/
-static void com20020_release(dev_link_t *link)
+static void com20020_release(struct pcmcia_device *link)
{
-
- DEBUG(1,"release...\n");
-
- DEBUG(0, "com20020_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ DEBUG(0, "com20020_release(0x%p)\n", link);
+ pcmcia_disable_device(link);
}
-static int com20020_suspend(struct pcmcia_device *p_dev)
+static int com20020_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- }
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int com20020_resume(struct pcmcia_device *p_dev)
+static int com20020_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- int ioaddr = dev->base_addr;
- struct arcnet_local *lp = dev->priv;
- ARCRESET;
- }
- }
+ if (link->open) {
+ int ioaddr = dev->base_addr;
+ struct arcnet_local *lp = dev->priv;
+ ARCRESET;
+ }
return 0;
}
@@ -436,7 +397,7 @@ static struct pcmcia_driver com20020_cs_driver = {
.drv = {
.name = "com20020_cs",
},
- .probe = com20020_attach,
+ .probe = com20020_probe,
.remove = com20020_detach,
.id_table = com20020_ids,
.suspend = com20020_suspend,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index b7ac14ba8877..09b11761cdfa 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -84,10 +84,10 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23";
/*
PCMCIA event handlers
*/
-static void fmvj18x_config(dev_link_t *link);
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
-static int fmvj18x_setup_mfc(dev_link_t *link);
-static void fmvj18x_release(dev_link_t *link);
+static int fmvj18x_config(struct pcmcia_device *link);
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
+static int fmvj18x_setup_mfc(struct pcmcia_device *link);
+static void fmvj18x_release(struct pcmcia_device *link);
static void fmvj18x_detach(struct pcmcia_device *p_dev);
/*
@@ -116,7 +116,7 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
driver specific data structure
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
long open_time;
@@ -228,10 +228,9 @@ typedef struct local_info_t {
#define BANK_1U 0x24 /* bank 1 (CONFIG_1) */
#define BANK_2U 0x28 /* bank 2 (CONFIG_1) */
-static int fmvj18x_attach(struct pcmcia_device *p_dev)
+static int fmvj18x_probe(struct pcmcia_device *link)
{
local_info_t *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "fmvj18x_attach()\n");
@@ -241,8 +240,8 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
link->priv = dev;
+ lp->p_dev = link;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 32;
@@ -257,7 +256,6 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
/* The FMVJ18x specific entries in the device structure. */
@@ -274,29 +272,21 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
#endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- fmvj18x_config(link);
-
- return 0;
+ return fmvj18x_config(link);
} /* fmvj18x_attach */
/*====================================================================*/
-static void fmvj18x_detach(struct pcmcia_device *p_dev)
+static void fmvj18x_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- fmvj18x_release(link);
+ fmvj18x_release(link);
free_netdev(dev);
} /* fmvj18x_detach */
@@ -306,7 +296,7 @@ static void fmvj18x_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int mfc_try_io_port(dev_link_t *link)
+static int mfc_try_io_port(struct pcmcia_device *link)
{
int i, ret;
static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
@@ -318,13 +308,13 @@ static int mfc_try_io_port(dev_link_t *link)
link->io.NumPorts2 = 0;
printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
}
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
}
-static int ungermann_try_io_port(dev_link_t *link)
+static int ungermann_try_io_port(struct pcmcia_device *link)
{
int ret;
kio_addr_t ioaddr;
@@ -334,7 +324,7 @@ static int ungermann_try_io_port(dev_link_t *link)
*/
for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
link->io.BasePort1 = ioaddr;
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) {
/* calculate ConfigIndex value */
link->conf.ConfigIndex =
@@ -345,9 +335,8 @@ static int ungermann_try_io_port(dev_link_t *link)
return ret; /* RequestIO failed */
}
-static void fmvj18x_config(dev_link_t *link)
+static int fmvj18x_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
local_info_t *lp = netdev_priv(dev);
tuple_t tuple;
@@ -366,42 +355,34 @@ static void fmvj18x_config(dev_link_t *link)
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (u_char *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
-
- /* Configure card */
- link->state |= DEV_CONFIG;
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigIndex = parse.cftable_entry.index;
tuple.DesiredTuple = CISTPL_MANFID;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
else
buf[0] = 0xffff;
switch (le16_to_cpu(buf[0])) {
case MANFID_TDK:
cardtype = TDK;
- if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) {
- cs_status_t status;
- pcmcia_get_status(handle, &status);
- if (status.CardState & CS_EVENT_3VCARD)
- link->conf.Vcc = 33; /* inserted in 3.3V slot */
- } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
+ if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
|| le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
|| le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
/* MultiFunction Card */
@@ -429,8 +410,8 @@ static void fmvj18x_config(dev_link_t *link)
} else {
/* old type card */
tuple.DesiredTuple = CISTPL_MANFID;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
else
buf[0] = 0xffff;
switch (le16_to_cpu(buf[0])) {
@@ -461,10 +442,10 @@ static void fmvj18x_config(dev_link_t *link)
ret = ungermann_try_io_port(link);
if (ret != CS_SUCCESS) goto cs_failed;
} else {
- CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -493,17 +474,17 @@ static void fmvj18x_config(dev_link_t *link)
case CONTEC:
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
if (cardtype == MBH10304) {
/* MBH10304's CIS_FUNCE is corrupted */
node_id = &(tuple.TupleData[5]);
card_name = "FMV-J182";
} else {
while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
}
node_id = &(tuple.TupleData[2]);
if( cardtype == TDK ) {
@@ -545,13 +526,12 @@ static void fmvj18x_config(dev_link_t *link)
}
lp->cardtype = cardtype;
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -564,19 +544,18 @@ static void fmvj18x_config(dev_link_t *link)
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
/* All Card Services errors end up here */
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
fmvj18x_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
-
+ return -ENODEV;
} /* fmvj18x_config */
/*====================================================================*/
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
{
win_req_t req;
memreq_t mem;
@@ -587,9 +566,9 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
return -1;
}
@@ -623,13 +602,13 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
iounmap(base);
j = pcmcia_release_window(link->win);
if (j != CS_SUCCESS)
- cs_error(link->handle, ReleaseWindow, j);
+ cs_error(link, ReleaseWindow, j);
return (i != 0x200) ? 0 : -1;
} /* fmvj18x_get_hwinfo */
/*====================================================================*/
-static int fmvj18x_setup_mfc(dev_link_t *link)
+static int fmvj18x_setup_mfc(struct pcmcia_device *link)
{
win_req_t req;
memreq_t mem;
@@ -642,9 +621,9 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
return -1;
}
@@ -666,54 +645,35 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
iounmap(base);
j = pcmcia_release_window(link->win);
if (j != CS_SUCCESS)
- cs_error(link->handle, ReleaseWindow, j);
+ cs_error(link, ReleaseWindow, j);
return 0;
}
/*====================================================================*/
-static void fmvj18x_release(dev_link_t *link)
+static void fmvj18x_release(struct pcmcia_device *link)
{
-
- DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+ pcmcia_disable_device(link);
}
-static int fmvj18x_suspend(struct pcmcia_device *p_dev)
+static int fmvj18x_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
-
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int fmvj18x_resume(struct pcmcia_device *p_dev)
+static int fmvj18x_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- fjn_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ fjn_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -751,7 +711,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
.drv = {
.name = "fmvj18x_cs",
},
- .probe = fmvj18x_attach,
+ .probe = fmvj18x_probe,
.remove = fmvj18x_detach,
.id_table = fmvj18x_ids,
.suspend = fmvj18x_suspend,
@@ -1148,11 +1108,11 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){
static int fjn_open(struct net_device *dev)
{
struct local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(4, "fjn_open('%s').\n", dev->name);
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1173,7 +1133,7 @@ static int fjn_open(struct net_device *dev)
static int fjn_close(struct net_device *dev)
{
struct local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
kio_addr_t ioaddr = dev->base_addr;
DEBUG(4, "fjn_close('%s').\n", dev->name);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b9c7e39576f5..b8fe70b85641 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -105,15 +105,15 @@ MODULE_LICENSE("GPL");
/*====================================================================*/
-static void ibmtr_config(dev_link_t *link);
+static int ibmtr_config(struct pcmcia_device *link);
static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
-static void ibmtr_release(dev_link_t *link);
+static void ibmtr_release(struct pcmcia_device *link);
static void ibmtr_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
typedef struct ibmtr_dev_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
struct net_device *dev;
dev_node_t node;
window_handle_t sram_win_handle;
@@ -138,12 +138,11 @@ static struct ethtool_ops netdev_ethtool_ops = {
======================================================================*/
-static int ibmtr_attach(struct pcmcia_device *p_dev)
+static int ibmtr_attach(struct pcmcia_device *link)
{
ibmtr_dev_t *info;
- dev_link_t *link;
struct net_device *dev;
-
+
DEBUG(0, "ibmtr_attach()\n");
/* Create new token-ring device */
@@ -156,7 +155,7 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
return -ENOMEM;
}
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
info->ti = netdev_priv(dev);
@@ -167,21 +166,14 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &tok_interrupt;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
link->irq.Instance = info->dev = dev;
-
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
- link->handle = p_dev;
- p_dev->instance = link;
- link->state |= DEV_PRESENT;
- ibmtr_config(link);
+ SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- return 0;
+ return ibmtr_config(link);
} /* ibmtr_attach */
/*======================================================================
@@ -193,23 +185,22 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void ibmtr_detach(struct pcmcia_device *p_dev)
+static void ibmtr_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
DEBUG(0, "ibmtr_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
{
struct tok_info *ti = netdev_priv(dev);
del_timer_sync(&(ti->tr_timer));
}
- if (link->state & DEV_CONFIG)
- ibmtr_release(link);
+
+ ibmtr_release(link);
free_netdev(dev);
kfree(info);
@@ -226,9 +217,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void ibmtr_config(dev_link_t *link)
+static int ibmtr_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
struct tok_info *ti = netdev_priv(dev);
@@ -246,29 +236,25 @@ static void ibmtr_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
link->conf.ConfigIndex = 0x61;
/* Determine if this is PRIMARY or ALTERNATE. */
/* Try PRIMARY card at 0xA20-0xA23 */
link->io.BasePort1 = 0xA20;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i != CS_SUCCESS) {
/* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
link->io.BasePort1 = 0xA24;
- CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
dev->base_addr = link->io.BasePort1;
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
dev->irq = link->irq.AssignedIRQ;
ti->irq = link->irq.AssignedIRQ;
ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
@@ -279,7 +265,7 @@ static void ibmtr_config(dev_link_t *link)
req.Base = 0;
req.Size = 0x2000;
req.AccessSpeed = 250;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = mmiobase;
mem.Page = 0;
@@ -292,7 +278,7 @@ static void ibmtr_config(dev_link_t *link)
req.Base = 0;
req.Size = sramsize * 1024;
req.AccessSpeed = 250;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle));
mem.CardOffset = srambase;
mem.Page = 0;
@@ -302,21 +288,20 @@ static void ibmtr_config(dev_link_t *link)
ti->sram_virt = ioremap(req.Base, req.Size);
ti->sram_phys = req.Base;
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/* Set up the Token-Ring Controller Configuration Register and
turn on the card. Check the "Local Area Network Credit Card
Adapters Technical Reference" SC30-3585 for this info. */
ibmtr_hw_setup(dev, mmiobase);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = ibmtr_probe_card(dev);
if (i != 0) {
printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -330,12 +315,13 @@ static void ibmtr_config(dev_link_t *link)
for (i = 0; i < TR_ALEN; i++)
printk("%02X", dev->dev_addr[i]);
printk("\n");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
ibmtr_release(link);
+ return -ENODEV;
} /* ibmtr_config */
/*======================================================================
@@ -346,56 +332,41 @@ failed:
======================================================================*/
-static void ibmtr_release(dev_link_t *link)
+static void ibmtr_release(struct pcmcia_device *link)
{
- ibmtr_dev_t *info = link->priv;
- struct net_device *dev = info->dev;
-
- DEBUG(0, "ibmtr_release(0x%p)\n", link);
+ ibmtr_dev_t *info = link->priv;
+ struct net_device *dev = info->dev;
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- if (link->win) {
- struct tok_info *ti = netdev_priv(dev);
- iounmap(ti->mmio);
- pcmcia_release_window(link->win);
- pcmcia_release_window(info->sram_win_handle);
- }
+ DEBUG(0, "ibmtr_release(0x%p)\n", link);
- link->state &= ~DEV_CONFIG;
+ if (link->win) {
+ struct tok_info *ti = netdev_priv(dev);
+ iounmap(ti->mmio);
+ pcmcia_release_window(info->sram_win_handle);
+ }
+ pcmcia_disable_device(link);
}
-static int ibmtr_suspend(struct pcmcia_device *p_dev)
+static int ibmtr_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int ibmtr_resume(struct pcmcia_device *p_dev)
+static int ibmtr_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- ibmtr_probe(dev); /* really? */
- netif_device_attach(dev);
- }
- }
+ if (link->open) {
+ ibmtr_probe(dev); /* really? */
+ netif_device_attach(dev);
+ }
return 0;
}
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 787176c57fd9..4260c2128f47 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -362,7 +362,7 @@ typedef struct _mace_statistics {
} mace_statistics;
typedef struct _mace_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats linux_stats; /* Linux statistics counters */
mace_statistics mace_stats; /* MACE chip statistics counters */
@@ -417,8 +417,8 @@ INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
Function Prototypes
---------------------------------------------------------------------------- */
-static void nmclan_config(dev_link_t *link);
-static void nmclan_release(dev_link_t *link);
+static int nmclan_config(struct pcmcia_device *link);
+static void nmclan_release(struct pcmcia_device *link);
static void nmclan_reset(struct net_device *dev);
static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -443,10 +443,9 @@ nmclan_attach
Services.
---------------------------------------------------------------------------- */
-static int nmclan_attach(struct pcmcia_device *p_dev)
+static int nmclan_probe(struct pcmcia_device *link)
{
mace_private *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "nmclan_attach()\n");
@@ -457,7 +456,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
+ lp->p_dev = link;
link->priv = dev;
spin_lock_init(&lp->bank_lock);
@@ -469,7 +468,6 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &mace_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -489,13 +487,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- nmclan_config(link);
-
- return 0;
+ return nmclan_config(link);
} /* nmclan_attach */
/* ----------------------------------------------------------------------------
@@ -506,18 +498,16 @@ nmclan_detach
when the device is released.
---------------------------------------------------------------------------- */
-static void nmclan_detach(struct pcmcia_device *p_dev)
+static void nmclan_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "nmclan_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- nmclan_release(link);
+ nmclan_release(link);
free_netdev(dev);
} /* nmclan_detach */
@@ -661,9 +651,8 @@ nmclan_config
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void nmclan_config(dev_link_t *link)
+static int nmclan_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
mace_private *lp = netdev_priv(dev);
tuple_t tuple;
@@ -679,17 +668,14 @@ static void nmclan_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -700,8 +686,8 @@ static void nmclan_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);
/* Verify configuration by reading the MACE ID. */
@@ -716,8 +702,7 @@ static void nmclan_config(dev_link_t *link)
} else {
printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
" be 0x40 0x?9\n", sig[0], sig[1]);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
}
}
@@ -730,14 +715,13 @@ static void nmclan_config(dev_link_t *link)
else
printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = register_netdev(dev);
if (i != 0) {
printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -747,14 +731,13 @@ static void nmclan_config(dev_link_t *link)
dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
- nmclan_release(link);
- return;
-
+ nmclan_release(link);
+ return -ENODEV;
} /* nmclan_config */
/* ----------------------------------------------------------------------------
@@ -763,46 +746,29 @@ nmclan_release
net device, and release the PCMCIA configuration. If the device
is still open, this will be postponed until it is closed.
---------------------------------------------------------------------------- */
-static void nmclan_release(dev_link_t *link)
+static void nmclan_release(struct pcmcia_device *link)
{
-
- DEBUG(0, "nmclan_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ DEBUG(0, "nmclan_release(0x%p)\n", link);
+ pcmcia_disable_device(link);
}
-static int nmclan_suspend(struct pcmcia_device *p_dev)
+static int nmclan_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
-
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int nmclan_resume(struct pcmcia_device *p_dev)
+static int nmclan_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- nmclan_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ nmclan_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -818,7 +784,7 @@ static void nmclan_reset(struct net_device *dev)
mace_private *lp = netdev_priv(dev);
#if RESET_XILINX
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = &lp->link;
conf_reg_t reg;
u_long OrigCorValue;
@@ -827,7 +793,7 @@ static void nmclan_reset(struct net_device *dev)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
reg.Value = 0;
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
OrigCorValue = reg.Value;
/* Reset Xilinx */
@@ -836,12 +802,12 @@ static void nmclan_reset(struct net_device *dev)
DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",
OrigCorValue);
reg.Value = COR_SOFT_RESET;
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
/* Need to wait for 20 ms for PCMCIA to finish reset. */
/* Restore original COR configuration index */
reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
/* Xilinx is now completely reset along with the MACE chip. */
lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
@@ -885,9 +851,9 @@ static int mace_open(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
mace_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -908,7 +874,7 @@ static int mace_close(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
mace_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
@@ -963,12 +929,12 @@ mace_start_xmit
static void mace_tx_timeout(struct net_device *dev)
{
mace_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
#if RESET_ON_TIMEOUT
printk("resetting card\n");
- pcmcia_reset_card(link->handle, NULL);
+ pcmcia_reset_card(link, NULL);
#else /* #if RESET_ON_TIMEOUT */
printk("NOT resetting card\n");
#endif /* #if RESET_ON_TIMEOUT */
@@ -1635,7 +1601,7 @@ static struct pcmcia_driver nmclan_cs_driver = {
.drv = {
.name = "nmclan_cs",
},
- .probe = nmclan_attach,
+ .probe = nmclan_probe,
.remove = nmclan_detach,
.id_table = nmclan_ids,
.suspend = nmclan_suspend,
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b46e5f703efa..d090df413049 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -103,8 +103,8 @@ module_param_array(hw_addr, int, NULL, 0);
/*====================================================================*/
static void mii_phy_probe(struct net_device *dev);
-static void pcnet_config(dev_link_t *link);
-static void pcnet_release(dev_link_t *link);
+static int pcnet_config(struct pcmcia_device *link);
+static void pcnet_release(struct pcmcia_device *link);
static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev);
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -113,9 +113,9 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
static void ei_watchdog(u_long arg);
static void pcnet_reset_8390(struct net_device *dev);
static int set_config(struct net_device *dev, struct ifmap *map);
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
int stop_pg, int cm_offset);
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
int stop_pg);
static void pcnet_detach(struct pcmcia_device *p_dev);
@@ -214,7 +214,7 @@ static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
typedef struct pcnet_dev_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
u_int flags;
void __iomem *base;
@@ -240,10 +240,9 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/
-static int pcnet_probe(struct pcmcia_device *p_dev)
+static int pcnet_probe(struct pcmcia_device *link)
{
pcnet_dev_t *info;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "pcnet_attach()\n");
@@ -252,7 +251,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
if (!dev) return -ENOMEM;
info = PRIV(dev);
- link = &info->link;
+ info->p_dev = link;
link->priv = dev;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -265,13 +264,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
dev->stop = &pcnet_close;
dev->set_config = &set_config;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- pcnet_config(link);
-
- return 0;
+ return pcnet_config(link);
} /* pcnet_attach */
/*======================================================================
@@ -283,18 +276,16 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
======================================================================*/
-static void pcnet_detach(struct pcmcia_device *p_dev)
+static void pcnet_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "pcnet_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- pcnet_release(link);
+ pcnet_release(link);
free_netdev(dev);
} /* pcnet_detach */
@@ -306,7 +297,7 @@ static void pcnet_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static hw_info_t *get_hwinfo(dev_link_t *link)
+static hw_info_t *get_hwinfo(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
win_req_t req;
@@ -318,9 +309,9 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
return NULL;
}
@@ -343,7 +334,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
iounmap(virt);
j = pcmcia_release_window(link->win);
if (j != CS_SUCCESS)
- cs_error(link->handle, ReleaseWindow, j);
+ cs_error(link, ReleaseWindow, j);
return (i < NR_INFO) ? hw_info+i : NULL;
} /* get_hwinfo */
@@ -355,7 +346,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_prom(dev_link_t *link)
+static hw_info_t *get_prom(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -409,7 +400,7 @@ static hw_info_t *get_prom(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_dl10019(dev_link_t *link)
+static hw_info_t *get_dl10019(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -431,7 +422,7 @@ static hw_info_t *get_dl10019(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_ax88190(dev_link_t *link)
+static hw_info_t *get_ax88190(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -464,7 +455,7 @@ static hw_info_t *get_ax88190(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_hwired(dev_link_t *link)
+static hw_info_t *get_hwired(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -491,7 +482,7 @@ static hw_info_t *get_hwired(dev_link_t *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
{
int j, ret;
if (link->io.NumPorts1 == 32) {
@@ -512,18 +503,17 @@ static int try_io_port(dev_link_t *link)
for (j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
} else {
- return pcmcia_request_io(link->handle, &link->io);
+ return pcmcia_request_io(link, &link->io);
}
}
-static void pcnet_config(dev_link_t *link)
+static int pcnet_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
pcnet_dev_t *info = PRIV(dev);
tuple_t tuple;
@@ -531,7 +521,6 @@ static void pcnet_config(dev_link_t *link)
int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
int manfid = 0, prodid = 0, has_shmem = 0;
u_short buf[64];
- config_info_t conf;
hw_info_t *hw_info;
DEBUG(0, "pcnet_config(0x%p)\n", link);
@@ -541,36 +530,29 @@ static void pcnet_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
-
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
manfid = le16_to_cpu(buf[0]);
prodid = le16_to_cpu(buf[1]);
}
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (last_ret == CS_SUCCESS) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_io_t *io = &(parse.cftable_entry.io);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
cfg->index == 0 || cfg->io.nwin == 0)
goto next_entry;
@@ -594,14 +576,14 @@ static void pcnet_config(dev_link_t *link)
if (last_ret == CS_SUCCESS) break;
}
next_entry:
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
}
if (last_ret != CS_SUCCESS) {
- cs_error(handle, RequestIO, last_ret);
+ cs_error(link, RequestIO, last_ret);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
if (link->io.NumPorts2 == 8) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -611,7 +593,7 @@ static void pcnet_config(dev_link_t *link)
(prodid == PRODID_IBM_HOME_AND_AWAY))
link->conf.ConfigIndex |= 0x10;
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
if (info->flags & HAS_MISC_REG) {
@@ -679,9 +661,8 @@ static void pcnet_config(dev_link_t *link)
info->eth_phy = 0;
}
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ei_poll;
@@ -689,7 +670,7 @@ static void pcnet_config(dev_link_t *link)
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -712,14 +693,13 @@ static void pcnet_config(dev_link_t *link)
printk(" hw_addr ");
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
pcnet_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
} /* pcnet_config */
/*======================================================================
@@ -730,21 +710,16 @@ failed:
======================================================================*/
-static void pcnet_release(dev_link_t *link)
+static void pcnet_release(struct pcmcia_device *link)
{
- pcnet_dev_t *info = PRIV(link->priv);
+ pcnet_dev_t *info = PRIV(link->priv);
- DEBUG(0, "pcnet_release(0x%p)\n", link);
+ DEBUG(0, "pcnet_release(0x%p)\n", link);
- if (info->flags & USE_SHMEM) {
- iounmap(info->base);
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ if (info->flags & USE_SHMEM)
+ iounmap(info->base);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
/*======================================================================
@@ -756,34 +731,24 @@ static void pcnet_release(dev_link_t *link)
======================================================================*/
-static int pcnet_suspend(struct pcmcia_device *p_dev)
+static int pcnet_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int pcnet_resume(struct pcmcia_device *p_dev)
+static int pcnet_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- pcnet_reset_8390(dev);
- NS8390_init(dev, 1);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ pcnet_reset_8390(dev);
+ NS8390_init(dev, 1);
+ netif_device_attach(dev);
}
return 0;
@@ -1023,11 +988,11 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
pcnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
-
+ struct pcmcia_device *link = info->p_dev;
+
DEBUG(2, "pcnet_open('%s')\n", dev->name);
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1051,7 +1016,7 @@ static int pcnet_open(struct net_device *dev)
static int pcnet_close(struct net_device *dev)
{
pcnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
+ struct pcmcia_device *link = info->p_dev;
DEBUG(2, "pcnet_close('%s')\n", dev->name);
@@ -1429,7 +1394,7 @@ static void dma_block_output(struct net_device *dev, int count,
/*====================================================================*/
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
int stop_pg)
{
struct net_device *dev = link->priv;
@@ -1532,7 +1497,7 @@ static void shmem_block_output(struct net_device *dev, int count,
/*====================================================================*/
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
int stop_pg, int cm_offset)
{
struct net_device *dev = link->priv;
@@ -1554,7 +1519,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
req.Attributes |= WIN_USE_WAIT;
req.Base = 0; req.Size = window_size;
req.AccessSpeed = mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = (start_pg << 8) + cm_offset;
offset = mem.CardOffset % window_size;
@@ -1595,7 +1560,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
return 1;
}
@@ -1674,6 +1639,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 8839c4faafd6..e74bf5014ef6 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -49,6 +49,7 @@
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
+#include <pcmcia/ss.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -103,7 +104,7 @@ static const char *version =
#define MEMORY_WAIT_TIME 8
struct smc_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
spinlock_t lock;
u_short manfid;
u_short cardid;
@@ -278,8 +279,8 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
/*====================================================================*/
static void smc91c92_detach(struct pcmcia_device *p_dev);
-static void smc91c92_config(dev_link_t *link);
-static void smc91c92_release(dev_link_t *link);
+static int smc91c92_config(struct pcmcia_device *link);
+static void smc91c92_release(struct pcmcia_device *link);
static int smc_open(struct net_device *dev);
static int smc_close(struct net_device *dev);
@@ -308,10 +309,9 @@ static struct ethtool_ops ethtool_ops;
======================================================================*/
-static int smc91c92_attach(struct pcmcia_device *p_dev)
+static int smc91c92_probe(struct pcmcia_device *link)
{
struct smc_private *smc;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "smc91c92_attach()\n");
@@ -321,7 +321,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
smc = netdev_priv(dev);
- link = &smc->link;
+ smc->p_dev = link;
link->priv = dev;
spin_lock_init(&smc->lock);
@@ -333,7 +333,6 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &smc_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
/* The SMC91c92-specific entries in the device structure. */
@@ -357,13 +356,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
smc->mii_if.phy_id_mask = 0x1f;
smc->mii_if.reg_num_mask = 0x1f;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- smc91c92_config(link);
-
- return 0;
+ return smc91c92_config(link);
} /* smc91c92_attach */
/*======================================================================
@@ -375,18 +368,16 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void smc91c92_detach(struct pcmcia_device *p_dev)
+static void smc91c92_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "smc91c92_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- smc91c92_release(link);
+ smc91c92_release(link);
free_netdev(dev);
} /* smc91c92_detach */
@@ -414,7 +405,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s)
/*====================================================================*/
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i;
@@ -425,7 +416,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i;
@@ -447,7 +438,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
======================================================================*/
-static int mhz_3288_power(dev_link_t *link)
+static int mhz_3288_power(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
@@ -469,7 +460,7 @@ static int mhz_3288_power(dev_link_t *link)
return 0;
}
-static int mhz_mfc_config(dev_link_t *link)
+static int mhz_mfc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
@@ -504,7 +495,7 @@ static int mhz_mfc_config(dev_link_t *link)
tuple->TupleDataMax = 255;
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(link->handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
/* The Megahertz combo cards have modem-like CIS entries, so
we have to explicitly try a bunch of port combinations. */
while (i == CS_SUCCESS) {
@@ -513,11 +504,11 @@ static int mhz_mfc_config(dev_link_t *link)
for (k = 0; k < 0x400; k += 0x10) {
if (k & 0x80) continue;
link->io.BasePort1 = k ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i == CS_SUCCESS) break;
- i = next_tuple(link->handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
if (i != CS_SUCCESS)
goto free_cfg_mem;
@@ -527,7 +518,7 @@ static int mhz_mfc_config(dev_link_t *link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS)
goto free_cfg_mem;
smc->base = ioremap(req.Base, req.Size);
@@ -546,9 +537,8 @@ free_cfg_mem:
return i;
}
-static int mhz_setup(dev_link_t *link)
+static int mhz_setup(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -571,13 +561,13 @@ static int mhz_setup(dev_link_t *link)
/* Read the station address from the CIS. It is stored as the last
(fourth) string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
- if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
/* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
- if (next_tuple(handle, tuple, parse) != CS_SUCCESS)
- first_tuple(handle, tuple, parse);
+ if (next_tuple(link, tuple, parse) != CS_SUCCESS)
+ first_tuple(link, tuple, parse);
if (parse->version_1.ns > 3) {
station_addr = parse->version_1.str + parse->version_1.ofs[3];
if (cvt_ascii_address(dev, station_addr) == 0) {
@@ -588,11 +578,11 @@ static int mhz_setup(dev_link_t *link)
/* Another possibility: for the EM3288, in a special tuple */
tuple->DesiredTuple = 0x81;
- if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
- if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) {
+ if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
@@ -616,7 +606,7 @@ free_cfg_mem:
======================================================================*/
-static void mot_config(dev_link_t *link)
+static void mot_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
@@ -637,7 +627,7 @@ static void mot_config(dev_link_t *link)
mdelay(100);
}
-static int mot_setup(dev_link_t *link)
+static int mot_setup(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -671,7 +661,7 @@ static int mot_setup(dev_link_t *link)
/*====================================================================*/
-static int smc_config(dev_link_t *link)
+static int smc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
@@ -696,16 +686,16 @@ static int smc_config(dev_link_t *link)
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
link->io.NumPorts1 = 16;
- i = first_tuple(link->handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if (i == CS_SUCCESS) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
- i = next_tuple(link->handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
if (i == CS_SUCCESS)
dev->base_addr = link->io.BasePort1;
@@ -714,9 +704,8 @@ static int smc_config(dev_link_t *link)
return i;
}
-static int smc_setup(dev_link_t *link)
+static int smc_setup(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -739,11 +728,11 @@ static int smc_setup(dev_link_t *link)
/* Check for a LAN function extension tuple */
tuple->DesiredTuple = CISTPL_FUNCE;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i == CS_SUCCESS) {
if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
break;
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
if (i == CS_SUCCESS) {
node_id = (cistpl_lan_node_id_t *)parse->funce.data;
@@ -756,7 +745,7 @@ static int smc_setup(dev_link_t *link)
}
/* Try the third string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
- if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
@@ -774,7 +763,7 @@ free_cfg_mem:
/*====================================================================*/
-static int osi_config(dev_link_t *link)
+static int osi_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
@@ -794,22 +783,21 @@ static int osi_config(dev_link_t *link)
for (i = j = 0; j < 4; j++) {
link->io.BasePort2 = com[j];
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
/* Fallback: turn off hard decode */
link->conf.ConfigIndex = 0x03;
link->io.NumPorts2 = 0;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
}
dev->base_addr = link->io.BasePort1 + 0x10;
return i;
}
-static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
+static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -830,12 +818,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
/* Read the station address from tuple 0x90, subtuple 0x04 */
tuple->DesiredTuple = 0x90;
- i = pcmcia_get_first_tuple(handle, tuple);
+ i = pcmcia_get_first_tuple(link, tuple);
while (i == CS_SUCCESS) {
- i = pcmcia_get_tuple_data(handle, tuple);
+ i = pcmcia_get_tuple_data(link, tuple);
if ((i != CS_SUCCESS) || (buf[0] == 0x04))
break;
- i = pcmcia_get_next_tuple(handle, tuple);
+ i = pcmcia_get_next_tuple(link, tuple);
}
if (i != CS_SUCCESS) {
rc = -1;
@@ -868,57 +856,47 @@ free_cfg_mem:
return rc;
}
-static int smc91c92_suspend(struct pcmcia_device *p_dev)
+static int smc91c92_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int smc91c92_resume(struct pcmcia_device *p_dev)
+static int smc91c92_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
int i;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if ((smc->manfid == MANFID_MEGAHERTZ) &&
- (smc->cardid == PRODID_MEGAHERTZ_EM3288))
- mhz_3288_power(link);
- pcmcia_request_configuration(link->handle, &link->conf);
- if (smc->manfid == MANFID_MOTOROLA)
- mot_config(link);
- if ((smc->manfid == MANFID_OSITECH) &&
- (smc->cardid != PRODID_OSITECH_SEVEN)) {
- /* Power up the card and enable interrupts */
- set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
- set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
- }
- if (((smc->manfid == MANFID_OSITECH) &&
- (smc->cardid == PRODID_OSITECH_SEVEN)) ||
- ((smc->manfid == MANFID_PSION) &&
- (smc->cardid == PRODID_PSION_NET100))) {
- /* Download the Seven of Diamonds firmware */
- for (i = 0; i < sizeof(__Xilinx7OD); i++) {
- outb(__Xilinx7OD[i], link->io.BasePort1+2);
- udelay(50);
- }
- }
- if (link->open) {
- smc_reset(dev);
- netif_device_attach(dev);
+ if ((smc->manfid == MANFID_MEGAHERTZ) &&
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288))
+ mhz_3288_power(link);
+ if (smc->manfid == MANFID_MOTOROLA)
+ mot_config(link);
+ if ((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid != PRODID_OSITECH_SEVEN)) {
+ /* Power up the card and enable interrupts */
+ set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
+ set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+ }
+ if (((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+ ((smc->manfid == MANFID_PSION) &&
+ (smc->cardid == PRODID_PSION_NET100))) {
+ /* Download the Seven of Diamonds firmware */
+ for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+ outb(__Xilinx7OD[i], link->io.BasePort1+2);
+ udelay(50);
}
}
+ if (link->open) {
+ smc_reset(dev);
+ netif_device_attach(dev);
+ }
return 0;
}
@@ -931,7 +909,7 @@ static int smc91c92_resume(struct pcmcia_device *p_dev)
======================================================================*/
-static int check_sig(dev_link_t *link)
+static int check_sig(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -964,13 +942,15 @@ static int check_sig(dev_link_t *link)
}
if (width) {
- printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
- smc91c92_suspend(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- pcmcia_request_io(link->handle, &link->io);
- smc91c92_resume(link->handle);
- return check_sig(link);
+ modconf_t mod = {
+ .Attributes = CONF_IO_CHANGE_WIDTH,
+ };
+ printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
+
+ smc91c92_suspend(link);
+ pcmcia_modify_configuration(link, &mod);
+ smc91c92_resume(link);
+ return check_sig(link);
}
return -ENODEV;
}
@@ -984,11 +964,10 @@ static int check_sig(dev_link_t *link)
======================================================================*/
#define CS_EXIT_TEST(ret, svc, label) \
-if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; }
+if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; }
-static void smc91c92_config(dev_link_t *link)
+static int smc91c92_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
struct smc_cfg_mem *cfg_mem;
@@ -1015,21 +994,18 @@ static void smc91c92_config(dev_link_t *link)
tuple->TupleDataMax = 64;
tuple->DesiredTuple = CISTPL_CONFIG;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
CS_EXIT_TEST(i, ParseTuple, config_failed);
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
tuple->DesiredTuple = CISTPL_MANFID;
tuple->Attributes = TUPLE_RETURN_COMMON;
- if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
smc->manfid = parse->manfid.manf;
smc->cardid = parse->manfid.card;
}
- /* Configure card */
- link->state |= DEV_CONFIG;
-
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) {
i = osi_config(link);
@@ -1043,9 +1019,9 @@ static void smc91c92_config(dev_link_t *link)
}
CS_EXIT_TEST(i, RequestIO, config_failed);
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
CS_EXIT_TEST(i, RequestIRQ, config_failed);
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
CS_EXIT_TEST(i, RequestConfiguration, config_failed);
if (smc->manfid == MANFID_MOTOROLA)
@@ -1124,13 +1100,12 @@ static void smc91c92_config(dev_link_t *link)
SMC_SELECT_BANK(0);
}
- link->dev = &smc->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &smc->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto config_undo;
}
@@ -1160,15 +1135,14 @@ static void smc91c92_config(dev_link_t *link)
}
}
kfree(cfg_mem);
- return;
+ return 0;
config_undo:
unregister_netdev(dev);
config_failed: /* CS_EXIT_TEST() calls jump to here... */
smc91c92_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
kfree(cfg_mem);
-
+ return -ENODEV;
} /* smc91c92_config */
/*======================================================================
@@ -1179,22 +1153,15 @@ config_failed: /* CS_EXIT_TEST() calls jump to here... */
======================================================================*/
-static void smc91c92_release(dev_link_t *link)
+static void smc91c92_release(struct pcmcia_device *link)
{
-
- DEBUG(0, "smc91c92_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- if (link->win) {
- struct net_device *dev = link->priv;
- struct smc_private *smc = netdev_priv(dev);
- iounmap(smc->base);
- pcmcia_release_window(link->win);
- }
-
- link->state &= ~DEV_CONFIG;
+ DEBUG(0, "smc91c92_release(0x%p)\n", link);
+ if (link->win) {
+ struct net_device *dev = link->priv;
+ struct smc_private *smc = netdev_priv(dev);
+ iounmap(smc->base);
+ }
+ pcmcia_disable_device(link);
}
/*======================================================================
@@ -1283,7 +1250,7 @@ static void smc_dump(struct net_device *dev)
static int smc_open(struct net_device *dev)
{
struct smc_private *smc = netdev_priv(dev);
- dev_link_t *link = &smc->link;
+ struct pcmcia_device *link = smc->p_dev;
#ifdef PCMCIA_DEBUG
DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
@@ -1292,7 +1259,7 @@ static int smc_open(struct net_device *dev)
#endif
/* Check that the PCMCIA card is still here. */
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
/* Physical device present signature. */
if (check_sig(link) < 0) {
@@ -1320,7 +1287,7 @@ static int smc_open(struct net_device *dev)
static int smc_close(struct net_device *dev)
{
struct smc_private *smc = netdev_priv(dev);
- dev_link_t *link = &smc->link;
+ struct pcmcia_device *link = smc->p_dev;
kio_addr_t ioaddr = dev->base_addr;
DEBUG(0, "%s: smc_close(), status %4.4x.\n",
@@ -2311,7 +2278,7 @@ static struct pcmcia_driver smc91c92_cs_driver = {
.drv = {
.name = "smc91c92_cs",
},
- .probe = smc91c92_attach,
+ .probe = smc91c92_probe,
.remove = smc91c92_detach,
.id_table = smc91c92_ids,
.suspend = smc91c92_suspend,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index e8f849e12976..71f45056a70c 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -289,9 +289,9 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
* and ejection events. They are invoked from the event handler.
*/
-static int has_ce2_string(dev_link_t * link);
-static void xirc2ps_config(dev_link_t * link);
-static void xirc2ps_release(dev_link_t * link);
+static int has_ce2_string(struct pcmcia_device * link);
+static int xirc2ps_config(struct pcmcia_device * link);
+static void xirc2ps_release(struct pcmcia_device * link);
/****************
* The attach() and detach() entry points are used to create and destroy
@@ -313,10 +313,10 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs
/****************
* A linked list of "instances" of the device. Each actual
* PCMCIA card corresponds to one device instance, and is described
- * by one dev_link_t structure (defined in ds.h).
+ * by one struct pcmcia_device structure (defined in ds.h).
*
* You may not want to use a linked list for this -- for example, the
- * memory card driver uses an array of dev_link_t pointers, where minor
+ * memory card driver uses an array of struct pcmcia_device pointers, where minor
* device numbers are used to derive the corresponding array index.
*/
@@ -326,13 +326,13 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs
* example, ethernet cards, modems). In other cases, there may be
* many actual or logical devices (SCSI adapters, memory cards with
* multiple partitions). The dev_node_t structures need to be kept
- * in a linked list starting at the 'dev' field of a dev_link_t
+ * in a linked list starting at the 'dev' field of a struct pcmcia_device
* structure. We allocate them in the card's private data structure,
* because they generally can't be allocated dynamically.
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
int card_type;
@@ -355,7 +355,7 @@ static void do_tx_timeout(struct net_device *dev);
static struct net_device_stats *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
-static int set_card_type(dev_link_t *link, const void *s);
+static int set_card_type(struct pcmcia_device *link, const void *s);
static int do_config(struct net_device *dev, struct ifmap *map);
static int do_open(struct net_device *dev);
static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -368,7 +368,7 @@ static int do_stop(struct net_device *dev);
/*=============== Helper functions =========================*/
static int
-first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int err;
@@ -379,7 +379,7 @@ first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
}
static int
-next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int err;
@@ -553,9 +553,8 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
*/
static int
-xirc2ps_attach(struct pcmcia_device *p_dev)
+xirc2ps_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
struct net_device *dev;
local_info_t *local;
@@ -566,12 +565,11 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
local = netdev_priv(dev);
- link = &local->link;
+ local->p_dev = link;
link->priv = dev;
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -593,13 +591,7 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- xirc2ps_config(link);
-
- return 0;
+ return xirc2ps_config(link);
} /* xirc2ps_attach */
/****************
@@ -610,18 +602,16 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
*/
static void
-xirc2ps_detach(struct pcmcia_device *p_dev)
+xirc2ps_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- xirc2ps_release(link);
+ xirc2ps_release(link);
free_netdev(dev);
} /* xirc2ps_detach */
@@ -645,7 +635,7 @@ xirc2ps_detach(struct pcmcia_device *p_dev)
*
*/
static int
-set_card_type(dev_link_t *link, const void *s)
+set_card_type(struct pcmcia_device *link, const void *s)
{
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
@@ -714,9 +704,8 @@ set_card_type(dev_link_t *link, const void *s)
* Returns: true if this is a CE2
*/
static int
-has_ce2_string(dev_link_t * link)
+has_ce2_string(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
tuple_t tuple;
cisparse_t parse;
u_char buf[256];
@@ -726,7 +715,7 @@ has_ce2_string(dev_link_t * link)
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
- if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) {
+ if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) {
if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2"))
return 1;
}
@@ -738,10 +727,9 @@ has_ce2_string(dev_link_t * link)
* is received, to configure the PCMCIA socket, and to make the
* ethernet device available to the system.
*/
-static void
-xirc2ps_config(dev_link_t * link)
+static int
+xirc2ps_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
tuple_t tuple;
@@ -767,7 +755,7 @@ xirc2ps_config(dev_link_t * link)
/* Is this a valid card */
tuple.DesiredTuple = CISTPL_MANFID;
- if ((err=first_tuple(handle, &tuple, &parse))) {
+ if ((err=first_tuple(link, &tuple, &parse))) {
printk(KNOT_XIRC "manfid not found in CIS\n");
goto failure;
}
@@ -803,15 +791,15 @@ xirc2ps_config(dev_link_t * link)
/* get configuration stuff */
tuple.DesiredTuple = CISTPL_CONFIG;
- if ((err=first_tuple(handle, &tuple, &parse)))
+ if ((err=first_tuple(link, &tuple, &parse)))
goto cis_error;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* get the ethernet address from the CIS */
tuple.DesiredTuple = CISTPL_FUNCE;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)) {
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)) {
/* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries:
* the first one with a length of zero the second correct -
* so I skip all entries with length 0 */
@@ -821,8 +809,8 @@ xirc2ps_config(dev_link_t * link)
}
if (err) { /* not found: try to get the node-id from tuple 0x89 */
tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */
- if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 &&
- (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) {
+ if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 &&
+ (err = pcmcia_get_tuple_data(link, &tuple)) == 0) {
if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID)
memcpy(&parse, buf, 8);
else
@@ -831,8 +819,8 @@ xirc2ps_config(dev_link_t * link)
}
if (err) { /* another try (James Lehmer's CE2 version 4.1)*/
tuple.DesiredTuple = CISTPL_FUNCE;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)) {
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)) {
if (parse.funce.type == 0x02 && parse.funce.data[0] == 1
&& parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) {
buf[1] = 4;
@@ -853,9 +841,6 @@ xirc2ps_config(dev_link_t * link)
for (i=0; i < 6; i++)
dev->dev_addr[i] = node_id->id[i];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
link->io.IOAddrLines =10;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
link->irq.Attributes = IRQ_HANDLE_PRESENT;
@@ -875,14 +860,14 @@ xirc2ps_config(dev_link_t * link)
* Ethernet port */
link->io.NumPorts1 = 16; /* no Mako stuff anymore */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)) {
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)) {
if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->conf.ConfigIndex = cf->index ;
link->io.BasePort2 = cf->io.win[0].base;
link->io.BasePort1 = ioaddr;
- if (!(err=pcmcia_request_io(link->handle, &link->io)))
+ if (!(err=pcmcia_request_io(link, &link->io)))
goto port_found;
}
}
@@ -896,15 +881,15 @@ xirc2ps_config(dev_link_t * link)
*/
for (pass=0; pass < 2; pass++) {
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)){
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)){
if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){
link->conf.ConfigIndex = cf->index ;
link->io.BasePort2 = cf->io.win[0].base;
link->io.BasePort1 = link->io.BasePort2
+ (pass ? (cf->index & 0x20 ? -24:8)
: (cf->index & 0x20 ? 8:-24));
- if (!(err=pcmcia_request_io(link->handle, &link->io)))
+ if (!(err=pcmcia_request_io(link, &link->io)))
goto port_found;
}
}
@@ -919,12 +904,12 @@ xirc2ps_config(dev_link_t * link)
link->io.NumPorts1 = 16;
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->io.BasePort1 = ioaddr;
- if (!(err=pcmcia_request_io(link->handle, &link->io)))
+ if (!(err=pcmcia_request_io(link, &link->io)))
goto port_found;
}
link->io.BasePort1 = 0; /* let CS decide */
- if ((err=pcmcia_request_io(link->handle, &link->io))) {
- cs_error(link->handle, RequestIO, err);
+ if ((err=pcmcia_request_io(link, &link->io))) {
+ cs_error(link, RequestIO, err);
goto config_error;
}
}
@@ -936,8 +921,8 @@ xirc2ps_config(dev_link_t * link)
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
- if ((err=pcmcia_request_irq(link->handle, &link->irq))) {
- cs_error(link->handle, RequestIRQ, err);
+ if ((err=pcmcia_request_irq(link, &link->irq))) {
+ cs_error(link, RequestIRQ, err);
goto config_error;
}
@@ -945,8 +930,8 @@ xirc2ps_config(dev_link_t * link)
* This actually configures the PCMCIA socket -- setting up
* the I/O windows and the interrupt mapping.
*/
- if ((err=pcmcia_request_configuration(link->handle, &link->conf))) {
- cs_error(link->handle, RequestConfiguration, err);
+ if ((err=pcmcia_request_configuration(link, &link->conf))) {
+ cs_error(link, RequestConfiguration, err);
goto config_error;
}
@@ -963,15 +948,15 @@ xirc2ps_config(dev_link_t * link)
reg.Action = CS_WRITE;
reg.Offset = CISREG_IOBASE_0;
reg.Value = link->io.BasePort2 & 0xff;
- if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
- cs_error(link->handle, AccessConfigurationRegister, err);
+ if ((err = pcmcia_access_configuration_register(link, &reg))) {
+ cs_error(link, AccessConfigurationRegister, err);
goto config_error;
}
reg.Action = CS_WRITE;
reg.Offset = CISREG_IOBASE_1;
reg.Value = (link->io.BasePort2 >> 8) & 0xff;
- if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
- cs_error(link->handle, AccessConfigurationRegister, err);
+ if ((err = pcmcia_access_configuration_register(link, &reg))) {
+ cs_error(link, AccessConfigurationRegister, err);
goto config_error;
}
@@ -982,15 +967,15 @@ xirc2ps_config(dev_link_t * link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
req.AccessSpeed = 0;
- if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) {
- cs_error(link->handle, RequestWindow, err);
+ if ((err = pcmcia_request_window(&link, &req, &link->win))) {
+ cs_error(link, RequestWindow, err);
goto config_error;
}
local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
mem.CardOffset = 0x0;
mem.Page = 0;
if ((err = pcmcia_map_mem_page(link->win, &mem))) {
- cs_error(link->handle, MapMemPage, err);
+ cs_error(link, MapMemPage, err);
goto config_error;
}
@@ -1050,13 +1035,12 @@ xirc2ps_config(dev_link_t * link)
if (local->dingo)
do_reset(dev, 1); /* a kludge to make the cem56 work */
- link->dev = &local->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &local->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto config_error;
}
@@ -1069,17 +1053,16 @@ xirc2ps_config(dev_link_t * link)
printk("%c%02X", i?':':' ', dev->dev_addr[i]);
printk("\n");
- return;
+ return 0;
config_error:
- link->state &= ~DEV_CONFIG_PENDING;
xirc2ps_release(link);
- return;
+ return -ENODEV;
cis_error:
printk(KNOT_XIRC "unable to parse CIS\n");
failure:
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
} /* xirc2ps_config */
/****************
@@ -1088,57 +1071,41 @@ xirc2ps_config(dev_link_t * link)
* still open, this will be postponed until it is closed.
*/
static void
-xirc2ps_release(dev_link_t *link)
+xirc2ps_release(struct pcmcia_device *link)
{
+ DEBUG(0, "release(0x%p)\n", link);
- DEBUG(0, "release(0x%p)\n", link);
-
- if (link->win) {
- struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
- if (local->dingo)
- iounmap(local->dingo_ccr - 0x0800);
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
-
+ if (link->win) {
+ struct net_device *dev = link->priv;
+ local_info_t *local = netdev_priv(dev);
+ if (local->dingo)
+ iounmap(local->dingo_ccr - 0x0800);
+ }
+ pcmcia_disable_device(link);
} /* xirc2ps_release */
/*====================================================================*/
-static int xirc2ps_suspend(struct pcmcia_device *p_dev)
+static int xirc2ps_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- do_powerdown(dev);
- }
- pcmcia_release_configuration(link->handle);
+ if (link->open) {
+ netif_device_detach(dev);
+ do_powerdown(dev);
}
return 0;
}
-static int xirc2ps_resume(struct pcmcia_device *p_dev)
+static int xirc2ps_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- do_reset(dev,1);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ do_reset(dev,1);
+ netif_device_attach(dev);
}
return 0;
@@ -1552,13 +1519,13 @@ static int
do_open(struct net_device *dev)
{
local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(0, "do_open(%p)\n", dev);
/* Check that the PCMCIA card is still here. */
/* Physical device present signature. */
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
/* okay */
@@ -1882,7 +1849,7 @@ do_stop(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(0, "do_stop(%p)\n", dev);
@@ -1935,7 +1902,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
.drv = {
.name = "xirc2ps_cs",
},
- .probe = xirc2ps_attach,
+ .probe = xirc2ps_probe,
.remove = xirc2ps_detach,
.id_table = xirc2ps_ids,
.suspend = xirc2ps_suspend,
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 35dbf05c7f06..a70c2b0cc104 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -78,6 +78,8 @@ static const struct pci_device_id skge_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 68f9c206a620..227df9876a2c 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -51,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.1"
+#define DRV_VERSION "1.2"
#define PFX DRV_NAME " "
/*
@@ -99,8 +99,6 @@ MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
@@ -579,8 +577,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
reg = gma_read16(hw, port, GM_PHY_ADDR);
gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
- for (i = 0; i < GM_MIB_CNT_SIZE; i++)
- gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
+ for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
+ gma_read16(hw, port, i);
gma_write16(hw, port, GM_PHY_ADDR, reg);
/* transmit control */
@@ -927,8 +925,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
if (likely(skb)) {
unsigned long p = (unsigned long) skb->data;
- skb_reserve(skb,
- ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+ skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p);
}
return skb;
@@ -1688,13 +1685,12 @@ static void sky2_tx_timeout(struct net_device *dev)
}
-#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
/* Want receive buffer size to be multiple of 64 bits
* and incl room for vlan and truncation
*/
static inline unsigned sky2_buf_size(int mtu)
{
- return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
+ return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
}
static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -2088,6 +2084,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port,
}
}
+/* If idle then force a fake soft NAPI poll once a second
+ * to work around cases where sharing an edge triggered interrupt.
+ */
+static void sky2_idle(unsigned long arg)
+{
+ struct net_device *dev = (struct net_device *) arg;
+
+ local_irq_disable();
+ if (__netif_rx_schedule_prep(dev))
+ __netif_rx_schedule(dev);
+ local_irq_enable();
+}
+
+
static int sky2_poll(struct net_device *dev0, int *budget)
{
struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
@@ -2095,6 +2105,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
int work_done = 0;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
+ restart_poll:
if (unlikely(status & ~Y2_IS_STAT_BMU)) {
if (status & Y2_IS_HW_ERR)
sky2_hw_intr(hw);
@@ -2125,7 +2136,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
}
if (status & Y2_IS_STAT_BMU) {
- work_done = sky2_status_intr(hw, work_limit);
+ work_done += sky2_status_intr(hw, work_limit - work_done);
*budget -= work_done;
dev0->quota -= work_done;
@@ -2135,9 +2146,24 @@ static int sky2_poll(struct net_device *dev0, int *budget)
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
}
- netif_rx_complete(dev0);
+ mod_timer(&hw->idle_timer, jiffies + HZ);
+
+ local_irq_disable();
+ __netif_rx_complete(dev0);
status = sky2_read32(hw, B0_Y2_SP_LISR);
+
+ if (unlikely(status)) {
+ /* More work pending, try and keep going */
+ if (__netif_rx_schedule_prep(dev0)) {
+ __netif_rx_reschedule(dev0, work_done);
+ status = sky2_read32(hw, B0_Y2_SP_EISR);
+ local_irq_enable();
+ goto restart_poll;
+ }
+ }
+
+ local_irq_enable();
return 0;
}
@@ -2155,8 +2181,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
prefetch(&hw->st_le[hw->st_idx]);
if (likely(__netif_rx_schedule_prep(dev0)))
__netif_rx_schedule(dev0);
- else
- printk(KERN_DEBUG PFX "irq race detected\n");
return IRQ_HANDLED;
}
@@ -2195,7 +2219,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
}
-static int sky2_reset(struct sky2_hw *hw)
+static int __devinit sky2_reset(struct sky2_hw *hw)
{
u16 status;
u8 t8, pmd_type;
@@ -3278,6 +3302,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev);
+
pci_set_drvdata(pdev, hw);
return 0;
@@ -3313,13 +3339,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
if (!hw)
return;
+ del_timer_sync(&hw->idle_timer);
+
+ sky2_write32(hw, B0_IMSK, 0);
dev0 = hw->dev[0];
dev1 = hw->dev[1];
if (dev1)
unregister_netdev(dev1);
unregister_netdev(dev0);
- sky2_write32(hw, B0_IMSK, 0);
sky2_set_power_state(hw, PCI_D3hot);
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
sky2_write8(hw, B0_CTST, CS_RST_SET);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 62532b4e45c5..b026f5653f04 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1375,7 +1375,7 @@ enum {
GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
/* MIB Counters */
GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */
- GM_MIB_CNT_SIZE = 256,
+ GM_MIB_CNT_END = 0x025C, /* Last MIB counter */
};
@@ -1880,6 +1880,8 @@ struct sky2_hw {
struct sky2_status_le *st_le;
u32 st_idx;
dma_addr_t st_dma;
+
+ struct timer_list idle_timer;
int msi_detected;
wait_queue_head_t msi_wait;
};
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 35b18057fbdd..9b7805be21da 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -335,7 +335,7 @@ do { \
/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n"
KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
@@ -2122,8 +2122,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct netdev_private *np = netdev_priv(dev);
- if (!dev)
- BUG();
+ BUG_ON(!dev);
unregister_netdev(dev);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index cb0aba95d4e3..046371ee5bbe 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -275,7 +275,7 @@ static int bcm5411_init(struct mii_phy* phy)
return 0;
}
-static int bcm5411_suspend(struct mii_phy* phy)
+static int generic_suspend(struct mii_phy* phy)
{
phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -738,7 +738,7 @@ static struct mii_phy_def bcm5401_phy_def = {
/* Broadcom BCM 5411 */
static struct mii_phy_ops bcm5411_phy_ops = {
.init = bcm5411_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -757,7 +757,7 @@ static struct mii_phy_def bcm5411_phy_def = {
/* Broadcom BCM 5421 */
static struct mii_phy_ops bcm5421_phy_ops = {
.init = bcm5421_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -776,7 +776,7 @@ static struct mii_phy_def bcm5421_phy_def = {
/* Broadcom BCM 5421 built-in K2 */
static struct mii_phy_ops bcm5421k2_phy_ops = {
.init = bcm5421_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -795,7 +795,7 @@ static struct mii_phy_def bcm5421k2_phy_def = {
/* Broadcom BCM 5462 built-in Vesta */
static struct mii_phy_ops bcm5462V_phy_ops = {
.init = bcm5421_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -816,6 +816,7 @@ static struct mii_phy_def bcm5462V_phy_def = {
* would be useful here) --BenH.
*/
static struct mii_phy_ops marvell_phy_ops = {
+ .suspend = generic_suspend,
.setup_aneg = marvell_setup_aneg,
.setup_forced = marvell_setup_forced,
.poll_link = genmii_poll_link,
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 964c09644832..73e271e59c6a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.55"
-#define DRV_MODULE_RELDATE "Mar 27, 2006"
+#define DRV_MODULE_VERSION "3.56"
+#define DRV_MODULE_RELDATE "Apr 1, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -497,18 +497,18 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
- if (tp->write32 != tg3_write_indirect_reg32) {
- tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
- tw32_f(TG3PCI_MEM_WIN_DATA, val);
-
- /* Always leave this as zero. */
- tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
- } else {
+ if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ } else {
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+ tw32_f(TG3PCI_MEM_WIN_DATA, val);
+
+ /* Always leave this as zero. */
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
}
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
@@ -518,18 +518,18 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
- if (tp->write32 != tg3_write_indirect_reg32) {
- tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
- *val = tr32(TG3PCI_MEM_WIN_DATA);
-
- /* Always leave this as zero. */
- tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
- } else {
+ if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ } else {
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+ *val = tr32(TG3PCI_MEM_WIN_DATA);
+
+ /* Always leave this as zero. */
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
}
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
@@ -2966,9 +2966,7 @@ static void tg3_tx(struct tg3 *tp)
struct sk_buff *skb = ri->skb;
int i;
- if (unlikely(skb == NULL))
- BUG();
-
+ BUG_ON(skb == NULL);
pci_unmap_single(tp->pdev,
pci_unmap_addr(ri, mapping),
skb_headlen(skb),
@@ -2979,12 +2977,10 @@ static void tg3_tx(struct tg3 *tp)
sw_idx = NEXT_TX(sw_idx);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- if (unlikely(sw_idx == hw_idx))
- BUG();
+ BUG_ON(sw_idx == hw_idx);
ri = &tp->tx_buffers[sw_idx];
- if (unlikely(ri->skb != NULL))
- BUG();
+ BUG_ON(ri->skb != NULL);
pci_unmap_page(tp->pdev,
pci_unmap_addr(ri, mapping),
@@ -4935,9 +4931,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
{
int i;
- if (offset == TX_CPU_BASE &&
- (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
- BUG();
+ BUG_ON(offset == TX_CPU_BASE &&
+ (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
if (offset == RX_CPU_BASE) {
for (i = 0; i < 10000; i++) {
@@ -5840,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp)
GRC_MODE_NO_TX_PHDR_CSUM |
GRC_MODE_NO_RX_PHDR_CSUM);
tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
- if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
- tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
- if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
- tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+ /* Pseudo-header checksum is done by hardware logic and not
+ * the offload processers, so make the chip do the pseudo-
+ * header checksums on receive. For transmit it is more
+ * convenient to do the pseudo-header checksum in software
+ * as Linux does that on transmit for us in all cases.
+ */
+ tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
tw32(GRC_MODE,
tp->grc_mode |
@@ -8046,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp)
for (i = 0; i < size; i++)
csum8 += buf8[i];
- if (csum8 == 0)
- return 0;
- return -EIO;
+ if (csum8 == 0) {
+ err = 0;
+ goto out;
+ }
+
+ err = -EIO;
+ goto out;
}
/* Bootstrap checksum at offset 0x10 */
@@ -9543,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
/* Do not even try poking around in here on Sun parts. */
- if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
+ if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+ /* All SUN chips are built-in LOMs. */
+ tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
return;
+ }
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -9642,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
- (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
+ if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
@@ -10269,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
}
+ if (tp->write32 == tg3_write_indirect_reg32 ||
+ ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
+ (tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+ tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
+
/* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
* determined before calling tg3_set_power_state() so that
@@ -10311,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
- /* Pseudo-header checksum is done by hardware logic and not
- * the offload processers, so make the chip do the pseudo-
- * header checksums on receive. For transmit it is more
- * convenient to do the pseudo-header checksum in software
- * as Linux does that on transmit for us in all cases.
- */
- tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
- tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
-
/* Derive initial jumbo mode from MTU assigned in
* ether_setup() via the alloc_etherdev() call
*/
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index c43cc3264202..8c8b987d1250 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2171,8 +2171,7 @@ struct tg3 {
#define TG3_FLAG_PCIX_MODE 0x00020000
#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
#define TG3_FLAG_PCI_32BIT 0x00080000
-#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000
-#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000
+#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000
#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
#define TG3_FLAG_10_100_ONLY 0x01000000
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 9345e68c451e..649d8ea354f5 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -438,8 +438,7 @@ static void __devexit abyss_detach (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (!dev)
- BUG();
+ BUG_ON(!dev);
unregister_netdev(dev);
release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
free_irq(dev->irq, dev);
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 3a25d191ea4a..19e6f4dfd69c 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -735,8 +735,7 @@ static int __devexit madgemc_remove(struct device *device)
struct net_local *tp;
struct card_info *card;
- if (!dev)
- BUG();
+ BUG_ON(!dev);
tp = dev->priv;
card = tp->tmspriv;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index c1ce87a5f8d3..d9258d42090c 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -134,7 +134,7 @@ static const int multicast_filter_limit = 32;
#include "typhoon.h"
#include "typhoon-firmware.h"
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
"typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index a9b2150909d6..6a23964c1317 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -469,7 +469,7 @@ struct rhine_private {
struct sk_buff *tx_skbuff[TX_RING_SIZE];
dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
- /* Tx bounce buffers */
+ /* Tx bounce buffers (Rhine-I only) */
unsigned char *tx_buf[TX_RING_SIZE];
unsigned char *tx_bufs;
dma_addr_t tx_bufs_dma;
@@ -1043,7 +1043,8 @@ static void alloc_tbufs(struct net_device* dev)
rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
next += sizeof(struct tx_desc);
rp->tx_ring[i].next_desc = cpu_to_le32(next);
- rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
+ if (rp->quirks & rqRhineI)
+ rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
}
rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
@@ -1091,7 +1092,7 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
}
/* Called after status of force_media possibly changed */
-void rhine_set_carrier(struct mii_if_info *mii)
+static void rhine_set_carrier(struct mii_if_info *mii)
{
if (mii->force_media) {
/* autoneg is off: Link is always assumed to be up */
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 883cf7da10fc..b5328b0ff927 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -410,103 +410,6 @@ config WAN_ROUTER_DRIVERS
If unsure, say N.
-config VENDOR_SANGOMA
- tristate "Sangoma WANPIPE(tm) multiprotocol cards"
- depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN
- ---help---
- Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA).
-
- WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/>
- is a family of intelligent multiprotocol WAN adapters with data
- transfer rates up to 4Mbps. Cards support:
-
- - X.25, Frame Relay, PPP, Cisco HDLC protocols.
-
- - API for protocols like HDLC (LAPB), HDLC Streaming, X.25,
- Frame Relay and BiSync.
-
- - Ethernet Bridging over Frame Relay protocol.
-
- - MULTILINK PPP
-
- - Async PPP (Modem Dialup)
-
- The next questions will ask you about the protocols you want
- the driver to support.
-
- If you have one or more of these cards, say M to this option;
- and read <file:Documentation/networking/wan-router.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called wanpipe.
-
-config WANPIPE_CHDLC
- bool "WANPIPE Cisco HDLC support"
- depends on VENDOR_SANGOMA
- ---help---
- Connect a WANPIPE card to a leased line using the Cisco HDLC.
-
- - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards
- which allows user to build applications using the HDLC streaming API.
-
- - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1
- cards into a single logical channel.
-
- Say Y and the Cisco HDLC support, HDLC streaming API and
- MULTILINK PPP will be included in the driver.
-
-config WANPIPE_FR
- bool "WANPIPE Frame Relay support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to a Frame Relay network, or use Frame Relay
- API to develop custom applications.
-
- Contains the Ethernet Bridging over Frame Relay feature, where
- a WANPIPE frame relay link can be directly connected to the Linux
- kernel bridge. The Frame Relay option is supported on S514-PCI
- and S508-ISA cards.
-
- Say Y and the Frame Relay support will be included in the driver.
-
-config WANPIPE_X25
- bool "WANPIPE X.25 support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to an X.25 network.
-
- Includes the X.25 API support for custom applications over the
- X.25 protocol. The X.25 option is supported on S514-PCI and
- S508-ISA cards.
-
- Say Y and the X.25 support will be included in the driver.
-
-config WANPIPE_PPP
- bool "WANPIPE PPP support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to a leased line using Point-to-Point
- Protocol (PPP).
-
- The PPP option is supported on S514-PCI/S508-ISA cards.
-
- Say Y and the PPP support will be included in the driver.
-
-config WANPIPE_MULTPPP
- bool "WANPIPE Multi-Port PPP support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to a leased line using Point-to-Point
- Protocol (PPP).
-
- Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming
- adapter. In this case each Sangoma adapter port can support an
- independent PPP connection. For example, a single Quad-Port PCI
- adapter can support up to four independent PPP links. The PPP
- option is supported on S514-PCI/S508-ISA cards.
-
- Say Y and the Multi-Port PPP support will be included in the driver.
-
config CYCLADES_SYNC
tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index ce6c56b903e7..823c6d5ab90d 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -5,14 +5,6 @@
# Rewritten to use lists instead of if-statements.
#
-wanpipe-y := sdlamain.o sdla_ft1.o
-wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o
-wanpipe-$(CONFIG_WANPIPE_FR) += sdla_fr.o
-wanpipe-$(CONFIG_WANPIPE_CHDLC) += sdla_chdlc.o
-wanpipe-$(CONFIG_WANPIPE_PPP) += sdla_ppp.o
-wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o
-wanpipe-objs := $(wanpipe-y)
-
cyclomx-y := cycx_main.o
cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o
cyclomx-objs := $(cyclomx-y)
@@ -43,11 +35,6 @@ obj-$(CONFIG_LANMEDIA) += lmc/
obj-$(CONFIG_DLCI) += dlci.o
obj-$(CONFIG_SDLA) += sdla.o
-ifeq ($(CONFIG_WANPIPE_MULTPPP),y)
- obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o
-else
- obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o
-endif
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
deleted file mode 100644
index 496d29237e92..000000000000
--- a/drivers/net/wan/sdla_chdlc.c
+++ /dev/null
@@ -1,4428 +0,0 @@
-/*****************************************************************************
-* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Feb 28, 2001 Nenad Corbic Updated if_tx_timeout() routine for
-* 2.4.X kernels.
-* Jan 25, 2001 Nenad Corbic Added a TTY Sync serial driver over the
-* HDLC streaming protocol
-* Added a TTY Async serial driver over the
-* Async protocol.
-* Dec 15, 2000 Nenad Corbic Updated for 2.4.X Kernel support
-* Nov 13, 2000 Nenad Corbic Added true interface type encoding option.
-* Tcpdump doesn't support CHDLC inteface
-* types, to fix this "true type" option will set
-* the interface type to RAW IP mode.
-* Nov 07, 2000 Nenad Corbic Added security features for UDP debugging:
-* Deny all and specify allowed requests.
-* Jun 20, 2000 Nenad Corbic Fixed the API IP ERROR bug. Caused by the
-* latest update.
-* May 09, 2000 Nenad Corbic Option to bring down an interface
-* upon disconnect.
-* Mar 23, 2000 Nenad Corbic Improved task queue, bh handling.
-* Mar 16, 2000 Nenad Corbic Fixed the SLARP Dynamic IP addressing.
-* Mar 06, 2000 Nenad Corbic Bug Fix: corrupted mbox recovery.
-* Feb 10, 2000 Gideon Hack Added ASYNC support.
-* Feb 09, 2000 Nenad Corbic Fixed two shutdown bugs in update() and
-* if_stats() functions.
-* Jan 24, 2000 Nenad Corbic Fixed a startup wanpipe state racing,
-* condition between if_open and isr.
-* Jan 10, 2000 Nenad Corbic Added new socket API support.
-* Dev 15, 1999 Nenad Corbic Fixed up header files for 2.0.X kernels
-* Nov 20, 1999 Nenad Corbic Fixed zero length API bug.
-* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
-* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
-* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
-* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
-* Aug 07, 1998 David Fong Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h> /* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h> /* Socket Driver common area */
-#include <linux/if_wanpipe.h>
-
-/* TTY Includes */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_CONFIG 0x10
-
-#define MAX_IP_ERRORS 10
-
-#define TTY_CHDLC_MAX_MTU 2000
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF 10
-
-//#define PRINT_DEBUG
-#ifdef PRINT_DEBUG
-#define dbg_printk(format, a...) printk(format, ## a)
-#else
-#define dbg_printk(format, a...)
-#endif
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- wanpipe_common_t common;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- u32 ip_local;
- u32 ip_remote;
- u32 ip_local_tmp;
- u32 ip_remote_tmp;
- u8 ip_error;
- u8 config_chdlc;
- u8 config_chdlc_timeout;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
-
- bh_data_t *bh_head; /* Circular buffer for chdlc_bh */
- unsigned long tq_working;
- volatile int bh_write;
- volatile int bh_read;
- atomic_t bh_buff_used;
-
- unsigned char interface_down;
-
- /* Polling work queue entry. Each interface
- * has its own work queue entry, which is used
- * to defer events from the interrupt */
- struct work_struct poll_work;
- struct timer_list poll_delay_timer;
-
- u8 gateway;
- u8 true_if_encoding;
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
- two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-
-/* Network device interface */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr,
- unsigned len);
-
-static int if_rebuild_hdr (struct sk_buff *skb);
-static struct net_device_stats* if_stats(struct net_device* dev);
-
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure (sdla_t* card, void* data);
-static int chdlc_comm_enable (sdla_t* card);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-
-
-static int chdlc_disable_comm_shutdown (sdla_t *card);
-static void if_tx_timeout(struct net_device *dev);
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff( sdla_t* card);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area);
-static int configure_ip (sdla_t* card);
-static int unconfigure_ip (sdla_t* card);
-static void process_route(sdla_t *card);
-static void port_set_state (sdla_t *card, int);
-static int config_chdlc (sdla_t *card);
-static void disable_comm (sdla_t *card);
-
-static void trigger_chdlc_poll(struct net_device *dev);
-static void chdlc_poll(struct net_device *dev);
-static void chdlc_poll_delay (unsigned long dev_ptr);
-
-
-/* Miscellaneous asynchronous interface Functions */
-static int set_asy_config (sdla_t* card);
-static int asy_comm_enable (sdla_t* card);
-
-/* Interrupt handlers */
-static void wpc_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Bottom half handlers */
-static void chdlc_work(struct net_device *dev);
-static int chdlc_work_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-/* Miscellaneous functions */
-static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev,
- struct sk_buff *skb);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-
-
-static int Intr_test_counter;
-
-/* TTY Global Definitions */
-
-#define NR_PORTS 4
-#define WAN_TTY_MAJOR 226
-#define WAN_TTY_MINOR 0
-
-#define WAN_CARD(port) (tty_card_map[port])
-#define MIN_PORT 0
-#define MAX_PORT NR_PORTS-1
-
-#define CRC_LENGTH 2
-
-static int wanpipe_tty_init(sdla_t *card);
-static void wanpipe_tty_receive(sdla_t *, unsigned, unsigned int);
-static void wanpipe_tty_trigger_poll(sdla_t *card);
-
-static struct tty_driver serial_driver;
-static int tty_init_cnt=0;
-
-static struct serial_state rs_table[NR_PORTS];
-
-static char tty_driver_mode=WANOPT_TTY_SYNC;
-
-static char *opt_decode[] = {"NONE","CRTSCTS","XONXOFF-RX",
- "CRTSCTS XONXOFF-RX","XONXOFF-TX",
- "CRTSCTS XONXOFF-TX","CRTSCTS XONXOFF"};
-static char *p_decode[] = {"NONE","ODD","EVEN"};
-
-static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL};
-
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpc_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
- unsigned long max_permitted_baud = 0;
- SHARED_MEMORY_INFO_STRUCT *flags;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_CHDLC) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Find out which Port to use */
- if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
- if (card->next){
-
- if (conf->comm_port != card->next->u.c.comm_port){
- card->u.c.comm_port = conf->comm_port;
- }else{
- printk(KERN_INFO "%s: ERROR - %s port used!\n",
- card->wandev.name, PORT(conf->comm_port));
- return -EINVAL;
- }
- }else{
- card->u.c.comm_port = conf->comm_port;
- }
- }else{
- printk(KERN_INFO "%s: ERROR - Invalid Port Selected!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
-
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase +
- SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
- }
- }else{
- /* for a S514 adapter, set a pointer to the actual mailbox in the */
- /* allocated virtual memory area */
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }else{
- card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
- }
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if ((jiffies - timeout) > 1*HZ) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running Cisco HDLC firmware v%s\n",
- card->devname, u.str);
-
- card->isr = &wpc_isr;
- card->poll = NULL;
- card->exec = NULL;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = NULL;
- card->wandev.udp_port = conf->udp_port;
- card->disable_comm = &disable_comm;
- card->wandev.new_if_cnt = 0;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = conf->ttl;
- card->wandev.interface = conf->interface;
-
- if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
- card->hw.type != SDLA_S514){
- printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
- card->devname, PORT(card->u.c.comm_port));
- return -EIO;
- }
-
- card->wandev.clocking = conf->clocking;
-
- port_num = card->u.c.comm_port;
-
- /* in API mode, we can configure for "receive only" buffering */
- if(card->hw.type == SDLA_S514) {
- card->u.c.receive_only = conf->receive_only;
- if(conf->receive_only) {
- printk(KERN_INFO
- "%s: Configured for 'receive only' mode\n",
- card->devname);
- }
- }
-
- /* Setup Port Bps */
-
- if(card->wandev.clocking) {
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
- /* For Primary Port 0 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- PRI_MAX_BAUD_RATE_S514 :
- PRI_MAX_BAUD_RATE_S508;
-
- }else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- SEC_MAX_BAUD_RATE_S514 :
- SEC_MAX_BAUD_RATE_S508;
- }
-
- if(conf->bps > max_permitted_baud) {
- conf->bps = max_permitted_baud;
- printk(KERN_INFO "%s: Baud too high!\n",
- card->wandev.name);
- printk(KERN_INFO "%s: Baud rate set to %lu bps\n",
- card->wandev.name, max_permitted_baud);
- }
- card->wandev.bps = conf->bps;
- }else{
- card->wandev.bps = 0;
- }
-
- /* Setup the Port MTU */
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
- /* For Primary Port 0 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- } else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- }
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- if(card->hw.type != SDLA_S514)
- enable_irq(card->hw.irq);
-
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- flags = card->u.c.flags;
-
- /* This is for the ports link state */
- card->wandev.state = WAN_DUALPORT;
- card->u.c.state = WAN_DISCONNECTED;
-
-
- if (!card->wandev.piggyback){
- int err;
-
- /* Perform interrupt testing */
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_INFO "%s: Interrupt test failed (%i)\n",
- card->devname, Intr_test_counter);
- printk(KERN_INFO "%s: Please choose another interrupt\n",
- card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt test passed (%i)\n",
- card->devname, Intr_test_counter);
- card->configured = 1;
- }
-
- if ((card->tty_opt=conf->tty) == WANOPT_YES){
- int err;
- card->tty_minor = conf->tty_minor;
-
- /* On ASYNC connections internal clocking
- * is mandatory */
- if ((card->u.c.async_mode = conf->tty_mode)){
- card->wandev.clocking = 1;
- }
- err=wanpipe_tty_init(card);
- if (err){
- return err;
- }
- }else{
-
-
- if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: "
- "Failed to set interrupt triggers!\n",
- card->devname);
- return -EIO;
- }
-
- /* Mask the Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- }
-
- /* If we are using CHDLC in backup mode, this flag will
- * indicate not to look for IP addresses in config_chdlc()*/
- card->u.c.backup = conf->backup;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3
- * different locations:
- * 1) The 'if_stats' recorded for the device.
- * 2) Communication error statistics on the adapter.
- * 3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile chdlc_private_area_t* chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags;
- unsigned long timeout;
-
- /* sanity checks */
- if((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if(wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* more sanity checks */
- if(!card->u.c.flags)
- return -ENODEV;
-
- if(test_bit(PERI_CRIT, (void*)&card->wandev.critical))
- return -EAGAIN;
-
- if((dev=card->wandev.dev) == NULL)
- return -ENODEV;
-
- if((chdlc_priv_area=dev->priv) == NULL)
- return -ENODEV;
-
- flags = card->u.c.flags;
- if(chdlc_priv_area->update_comms_stats){
- return -EAGAIN;
- }
-
- /* we will need 2 timer interrupts to complete the */
- /* reading of the statistics */
- chdlc_priv_area->update_comms_stats = 2;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies;
- for(;;) {
- if(chdlc_priv_area->update_comms_stats == 0)
- break;
- if ((jiffies - timeout) > (1 * HZ)){
- chdlc_priv_area->update_comms_stats = 0;
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- chdlc_private_area_t* chdlc_priv_area;
-
-
- printk(KERN_INFO "%s: Configuring Interface: %s\n",
- card->devname, conf->name);
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
- printk(KERN_INFO "%s: Invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-
- if(chdlc_priv_area == NULL)
- return -ENOMEM;
-
- memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
- chdlc_priv_area->card = card;
- chdlc_priv_area->common.sk = NULL;
- chdlc_priv_area->common.func = NULL;
-
- /* initialize data */
- strcpy(card->u.c.if_name, conf->name);
-
- if(card->wandev.new_if_cnt > 0) {
- kfree(chdlc_priv_area);
- return -EEXIST;
- }
-
- card->wandev.new_if_cnt++;
-
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_priv_area->route_status = NO_ROUTE;
- chdlc_priv_area->route_removed = 0;
-
- card->u.c.async_mode = conf->async_mode;
-
- /* setup for asynchronous mode */
- if(conf->async_mode) {
- printk(KERN_INFO "%s: Configuring for asynchronous mode\n",
- wandev->name);
-
- if(card->u.c.comm_port == WANOPT_PRI) {
- printk(KERN_INFO
- "%s:Asynchronous mode on secondary port only\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- if(strcmp(conf->usedby, "WANPIPE") == 0) {
- printk(KERN_INFO
- "%s: Running in WANIPE Async Mode\n", wandev->name);
- card->u.c.usedby = WANPIPE;
- }else{
- card->u.c.usedby = API;
- }
-
- if(!card->wandev.clocking) {
- printk(KERN_INFO
- "%s: Asynch. clocking must be 'Internal'\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- if((card->wandev.bps < MIN_ASY_BAUD_RATE) ||
- (card->wandev.bps > MAX_ASY_BAUD_RATE)) {
- printk(KERN_INFO "%s: Selected baud rate is invalid.\n",
- wandev->name);
- printk(KERN_INFO "Must be between %u and %u bps.\n",
- MIN_ASY_BAUD_RATE, MAX_ASY_BAUD_RATE);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- card->u.c.api_options = 0;
- if (conf->asy_data_trans == WANOPT_YES) {
- card->u.c.api_options |= ASY_RX_DATA_TRANSPARENT;
- }
-
- card->u.c.protocol_options = 0;
- if (conf->rts_hs_for_receive == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_RTS_HS_FOR_RX;
- }
- if (conf->xon_xoff_hs_for_receive == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_RX;
- }
- if (conf->xon_xoff_hs_for_transmit == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_TX;
- }
- if (conf->dcd_hs_for_transmit == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_DCD_HS_FOR_TX;
- }
- if (conf->cts_hs_for_transmit == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_CTS_HS_FOR_TX;
- }
-
- card->u.c.tx_bits_per_char = conf->tx_bits_per_char;
- card->u.c.rx_bits_per_char = conf->rx_bits_per_char;
- card->u.c.stop_bits = conf->stop_bits;
- card->u.c.parity = conf->parity;
- card->u.c.break_timer = conf->break_timer;
- card->u.c.inter_char_timer = conf->inter_char_timer;
- card->u.c.rx_complete_length = conf->rx_complete_length;
- card->u.c.xon_char = conf->xon_char;
-
- } else { /* setup for synchronous mode */
-
- card->u.c.protocol_options = 0;
- if (conf->ignore_dcd == WANOPT_YES){
- card->u.c.protocol_options |= IGNORE_DCD_FOR_LINK_STAT;
- }
- if (conf->ignore_cts == WANOPT_YES){
- card->u.c.protocol_options |= IGNORE_CTS_FOR_LINK_STAT;
- }
-
- if (conf->ignore_keepalive == WANOPT_YES) {
- card->u.c.protocol_options |=
- IGNORE_KPALV_FOR_LINK_STAT;
- card->u.c.kpalv_tx = MIN_Tx_KPALV_TIMER;
- card->u.c.kpalv_rx = MIN_Rx_KPALV_TIMER;
- card->u.c.kpalv_err = MIN_KPALV_ERR_TOL;
-
- } else { /* Do not ignore keepalives */
- card->u.c.kpalv_tx =
- ((conf->keepalive_tx_tmr - MIN_Tx_KPALV_TIMER)
- >= 0) ?
- min_t(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) :
- DEFAULT_Tx_KPALV_TIMER;
-
- card->u.c.kpalv_rx =
- ((conf->keepalive_rx_tmr - MIN_Rx_KPALV_TIMER)
- >= 0) ?
- min_t(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) :
- DEFAULT_Rx_KPALV_TIMER;
-
- card->u.c.kpalv_err =
- ((conf->keepalive_err_margin-MIN_KPALV_ERR_TOL)
- >= 0) ?
- min_t(unsigned int, conf->keepalive_err_margin,
- MAX_KPALV_ERR_TOL) :
- DEFAULT_KPALV_ERR_TOL;
- }
-
- /* Setup slarp timer to control delay between slarps */
- card->u.c.slarp_timer =
- ((conf->slarp_timer - MIN_SLARP_REQ_TIMER) >= 0) ?
- min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) :
- DEFAULT_SLARP_REQ_TIMER;
-
- if (conf->hdlc_streaming == WANOPT_YES) {
- printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n",
- wandev->name);
- card->u.c.protocol_options = HDLC_STREAMING_MODE;
- }
-
- if ((chdlc_priv_area->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){
- printk(KERN_INFO
- "%s: Enabling, true interface type encoding.\n",
- card->devname);
- }
-
- /* Setup wanpipe as a router (WANPIPE) or as an API */
- if( strcmp(conf->usedby, "WANPIPE") == 0) {
-
- printk(KERN_INFO "%s: Running in WANPIPE mode!\n",
- wandev->name);
- card->u.c.usedby = WANPIPE;
-
- /* Option to bring down the interface when
- * the link goes down */
- if (conf->if_down){
- set_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down);
- printk(KERN_INFO
- "%s: Dynamic interface configuration enabled\n",
- card->devname);
- }
-
- } else if( strcmp(conf->usedby, "API") == 0) {
- card->u.c.usedby = API;
- printk(KERN_INFO "%s: Running in API mode !\n",
- wandev->name);
- }
- }
-
- /* Tells us that if this interface is a
- * gateway or not */
- if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){
- printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
- card->devname,card->u.c.if_name);
- }
-
- /* Get Multicast Information */
- chdlc_priv_area->mc = conf->mc;
-
- /* prepare network device data space for registration */
- strcpy(dev->name,card->u.c.if_name);
-
- dev->init = &if_init;
- dev->priv = chdlc_priv_area;
-
- /* Initialize the polling work routine */
- INIT_WORK(&chdlc_priv_area->poll_work, (void*)(void*)chdlc_poll, dev);
-
- /* Initialize the polling delay timer */
- init_timer(&chdlc_priv_area->poll_delay_timer);
- chdlc_priv_area->poll_delay_timer.data = (unsigned long)dev;
- chdlc_priv_area->poll_delay_timer.function = chdlc_poll_delay;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct wan_device* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* Initialize media-specific parameters */
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- /* Enable Mulitcasting if user selected */
- if (chdlc_priv_area->mc == WANOPT_YES){
- dev->flags |= IFF_MULTICAST;
- }
-
- if (chdlc_priv_area->true_if_encoding){
- dev->type = ARPHRD_HDLC; /* This breaks the tcpdump */
- }else{
- dev->type = ARPHRD_PPP;
- }
-
- dev->mtu = card->wandev.mtu;
- /* for API usage, add the API header size to the requested MTU size */
- if(card->u.c.usedby == API) {
- dev->mtu += sizeof(api_tx_hdr_t);
- }
-
- dev->hard_header_len = CHDLC_HDR_LEN;
-
- /* Initialize hardware parameters */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length
- * If too low packets will not be retransmitted
- * by stack.
- */
- dev->tx_queue_len = 100;
- SET_MODULE_OWNER(dev);
-
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct timeval tv;
- int err = 0;
-
- /* Only one open per interface is allowed */
-
- if (netif_running(dev))
- return -EBUSY;
-
- /* Initialize the work queue entry */
- chdlc_priv_area->tq_working=0;
-
- INIT_WORK(&chdlc_priv_area->common.wanpipe_work,
- (void *)(void *)chdlc_work, dev);
-
- /* Allocate and initialize BH circular buffer */
- /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
- chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
- memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
- atomic_set(&chdlc_priv_area->bh_buff_used, 0);
-
- do_gettimeofday(&tv);
- chdlc_priv_area->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
-
- /* TTY is configured during wanpipe_set_termios
- * call, not here */
- if (card->tty_opt)
- return err;
-
- set_bit(0,&chdlc_priv_area->config_chdlc);
- chdlc_priv_area->config_chdlc_timeout=jiffies;
-
- /* Start the CHDLC configuration after 1sec delay.
- * This will give the interface initilization time
- * to finish its configuration */
- mod_timer(&chdlc_priv_area->poll_delay_timer, jiffies + HZ);
- return err;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
-
- if (chdlc_priv_area->bh_head){
- int i;
- struct sk_buff *skb;
-
- for (i=0; i<(MAX_BH_BUFF+1); i++){
- skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb;
- if (skb != NULL){
- dev_kfree_skb_any(skb);
- }
- }
- kfree(chdlc_priv_area->bh_head);
- chdlc_priv_area->bh_head=NULL;
- }
-
- netif_stop_queue(dev);
- wanpipe_close(card);
- del_timer(&chdlc_priv_area->poll_delay_timer);
- return 0;
-}
-
-static void disable_comm (sdla_t *card)
-{
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- if (card->u.c.comm_enabled){
- chdlc_disable_comm_shutdown (card);
- }else{
- flags->interrupt_info_struct.interrupt_permission = 0;
- }
-
- if (!tty_init_cnt)
- return;
-
- if (card->tty_opt){
- struct serial_state * state;
- if (!(--tty_init_cnt)){
- int e1;
- serial_driver.refcount=0;
-
- if ((e1 = tty_unregister_driver(&serial_driver)))
- printk("SERIAL: failed to unregister serial driver (%d)\n",
- e1);
- printk(KERN_INFO "%s: Unregistering TTY Driver, Major %i\n",
- card->devname,WAN_TTY_MAJOR);
- }
- card->tty=NULL;
- tty_card_map[card->tty_minor]=NULL;
- state = &rs_table[card->tty_minor];
- memset(state, 0, sizeof(*state));
- }
- return;
-}
-
-
-/*============================================================================
- * Build media header.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it. If packet type is not
- * supported, set skb->protocol to 0 and discard packet later.
- *
- * Return: media header length.
- */
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr,
- unsigned len)
-{
- skb->protocol = htons(type);
-
- return CHDLC_HDR_LEN;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- netif_wake_queue (dev);
-}
-
-
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff *skb)
-{
- return 1;
-}
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- int udp_type = 0;
- unsigned long smp_flags;
- int err=0;
-
- netif_stop_queue(dev);
-
- if (skb == NULL){
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: interface %s got kicked!\n",
- card->devname, dev->name);
-
- netif_wake_queue(dev);
- return 0;
- }
-
- if (ntohs(skb->protocol) != htons(PVC_PROT)){
-
- /* check the udp packet type */
-
- udp_type = udp_pkt_type(skb, card);
-
- if (udp_type == UDP_CPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- chdlc_priv_area)){
- chdlc_int->interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- netif_start_queue(dev);
- return 0;
- }
-
- /* check to see if the source IP address is a broadcast or */
- /* multicast IP address */
- if(chk_bcast_mcast_addr(card, dev, skb)){
- ++card->wandev.stats.tx_dropped;
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if(test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
-
- if(card->u.c.state != WAN_CONNECTED){
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
-
- }else if(!skb->protocol){
- ++card->wandev.stats.tx_errors;
- netif_start_queue(dev);
-
- }else {
- void* data = skb->data;
- unsigned len = skb->len;
- unsigned char attr;
-
- /* If it's an API packet pull off the API
- * header. Also check that the packet size
- * is larger than the API header
- */
- if (card->u.c.usedby == API){
- api_tx_hdr_t* api_tx_hdr;
-
- /* discard the frame if we are configured for */
- /* 'receive only' mode or if there is no data */
- if (card->u.c.receive_only ||
- (len <= sizeof(api_tx_hdr_t))) {
-
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
-
- api_tx_hdr = (api_tx_hdr_t *)data;
- attr = api_tx_hdr->attr;
- data += sizeof(api_tx_hdr_t);
- len -= sizeof(api_tx_hdr_t);
- }
-
- if(chdlc_send(card, data, len)) {
- netif_stop_queue(dev);
- }else{
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += len;
-
- netif_start_queue(dev);
-
- dev->trans_start = jiffies;
- }
- }
-
-if_send_exit_crit:
-
- if (!(err=netif_queue_stopped(dev))) {
- dev_kfree_skb_any(skb);
- }else{
- chdlc_priv_area->tick_counter = jiffies;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb)
-{
- u32 src_ip_addr;
- u32 broadcast_ip_addr = 0;
- struct in_device *in_dev;
-
- /* read the IP source address from the outgoing packet */
- src_ip_addr = *(u32 *)(skb->data + 12);
-
- /* read the IP broadcast address for the device */
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa= in_dev->ifa_list;
- if(ifa != NULL)
- broadcast_ip_addr = ifa->ifa_broadcast;
- else
- return 0;
- }
-
- /* check if the IP Source Address is a Broadcast address */
- if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
- printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- /* check if the IP Source Address is a Multicast address */
- if((ntohl(src_ip_addr) >= 0xE0000001) &&
- (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
- printk(KERN_INFO "%s: Multicast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* fill in UDP reply */
- c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- c_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = c_udp_pkt->udp_pkt.udp_src_port;
- c_udp_pkt->udp_pkt.udp_src_port =
- c_udp_pkt->udp_pkt.udp_dst_port;
- c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-
- /* calculate UDP checksum */
- c_udp_pkt->udp_pkt.udp_checksum = 0;
- c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- c_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
- c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
- c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- c_udp_pkt->ip_pkt.hdr_checksum = 0;
- c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
- sdla_t *my_card;
- chdlc_private_area_t* chdlc_priv_area;
-
- if ((chdlc_priv_area=dev->priv) == NULL)
- return NULL;
-
- my_card = chdlc_priv_area->card;
- return &my_card->wandev.stats;
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*-----------------------------------------------------------------------------
- * Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
- int err;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-
- mailbox->buffer_length = data_length;
- memcpy(mailbox->data, data, data_length);
- mailbox->command = SET_CHDLC_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-
- return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- int_data->CHDLC_interrupt_triggers = mode;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
- return err;
-}
-
-
-/*===========================================================
- * chdlc_disable_comm_shutdown
- *
- * Shutdown() disables the communications. We must
- * have a sparate functions, because we must not
- * call chdlc_error() hander since the private
- * area has already been replaced */
-
-static int chdlc_disable_comm_shutdown (sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- /* Disable Interrutps */
- int_data->CHDLC_interrupt_triggers = 0;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- /* Disable Communications */
-
- if (card->u.c.async_mode) {
- mb->command = DISABLE_ASY_COMMUNICATIONS;
- }else{
- mb->command = DISABLE_CHDLC_COMMUNICATIONS;
- }
-
- mb->buffer_length = 0;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- card->u.c.comm_enabled = 0;
-
- return 0;
-}
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card, err, mb);
- else
- card->u.c.comm_enabled = 1;
-
- return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_COMMS_ERROR_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_OPERATIONAL_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Update communications error and general packet statistics.
- */
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- COMMS_ERROR_STATS_STRUCT* err_stats;
- CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
-
- /* on the first timer interrupt, read the comms error statistics */
- if(chdlc_priv_area->update_comms_stats == 2) {
- if(chdlc_read_comm_err_stats(card))
- return 1;
- err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_over_errors =
- err_stats->Rx_overrun_err_count;
- card->wandev.stats.rx_crc_errors =
- err_stats->CRC_err_count;
- card->wandev.stats.rx_frame_errors =
- err_stats->Rx_abort_count;
- card->wandev.stats.rx_fifo_errors =
- err_stats->Rx_dis_pri_bfrs_full_count;
- card->wandev.stats.rx_missed_errors =
- card->wandev.stats.rx_fifo_errors;
- card->wandev.stats.tx_aborted_errors =
- err_stats->sec_Tx_abort_count;
- }
-
- /* on the second timer interrupt, read the operational statistics */
- else {
- if(chdlc_read_op_stats(card))
- return 1;
- op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_length_errors =
- (op_stats->Rx_Data_discard_short_count +
- op_stats->Rx_Data_discard_long_count);
- }
-
- return 0;
-}
-
-/*============================================================================
- * Send packet.
- * Return: 0 - o.k.
- * 1 - no transmit buffers available
- */
-static int chdlc_send (sdla_t* card, void* data, unsigned len)
-{
- CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
-
- if (txbuf->opp_flag)
- return 1;
-
- sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
-
- txbuf->frame_length = len;
- txbuf->opp_flag = 1; /* start transmission */
-
- /* Update transmit buffer control fields */
- card->u.c.txbuf = ++txbuf;
-
- if ((void*)txbuf > card->u.c.txbuf_last)
- card->u.c.txbuf = card->u.c.txbuf_base;
-
- return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
- unsigned cmd = mb->command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_INFO "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- case S514_BOTH_PORTS_SAME_CLK_MODE:
- if(cmd == SET_CHDLC_CONFIGURATION) {
- printk(KERN_INFO
- "%s: Configure both ports for the same clock source\n",
- card->devname);
- break;
- }
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- }
-
- return 0;
-}
-
-
-/********** Bottom Half Handlers ********************************************/
-
-/* NOTE: There is no API, BH support for Kernels lower than 2.2.X.
- * DO NOT INSERT ANY CODE HERE, NOTICE THE
- * PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE
- * DOING */
-
-static void chdlc_work(struct net_device * dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
- struct sk_buff *skb;
-
- if (atomic_read(&chan->bh_buff_used) == 0){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- while (atomic_read(&chan->bh_buff_used)){
-
- skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
- if (skb != NULL){
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- ++card->wandev.stats.rx_dropped;
- dev_kfree_skb_any(skb);
- chdlc_work_cleanup(dev);
- continue;
- }
-
- if (chan->common.func(skb,dev,chan->common.sk) != 0){
- /* Sock full cannot send, queue us for another
- * try */
- atomic_set(&chan->common.receive_block,1);
- return;
- }else{
- chdlc_work_cleanup(dev);
- }
- }else{
- chdlc_work_cleanup(dev);
- }
- }
- clear_bit(0, &chan->tq_working);
-
- return;
-}
-
-static int chdlc_work_cleanup(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
-
- ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
- if (chan->bh_read == MAX_BH_BUFF){
- chan->bh_read=0;
- }else{
- ++chan->bh_read;
- }
-
- atomic_dec(&chan->bh_buff_used);
- return 0;
-}
-
-
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
- /* Check for full */
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
- ++card->wandev.stats.rx_dropped;
- dev_kfree_skb_any(skb);
- return 1;
- }
-
- ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
- if (chan->bh_write == MAX_BH_BUFF){
- chan->bh_write=0;
- }else{
- ++chan->bh_write;
- }
-
- atomic_inc(&chan->bh_buff_used);
-
- return 0;
-}
-
-/* END OF API BH Support */
-
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * Cisco HDLC interrupt service routine.
- */
-static void wpc_isr (sdla_t* card)
-{
- struct net_device* dev;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
- int i;
- sdla_t *my_card;
-
-
- /* Check for which port the interrupt has been generated
- * Since Secondary Port is piggybacking on the Primary
- * the check must be done here.
- */
-
- flags = card->u.c.flags;
- if (!flags->interrupt_info_struct.interrupt_type){
- /* Check for a second port (piggybacking) */
- if ((my_card = card->next)){
- flags = my_card->u.c.flags;
- if (flags->interrupt_info_struct.interrupt_type){
- card = my_card;
- card->isr(card);
- return;
- }
- }
- }
-
- flags = card->u.c.flags;
- card->in_isr = 1;
- dev = card->wandev.dev;
-
- /* If we get an interrupt with no network device, stop the interrupts
- * and issue an error */
- if (!card->tty_opt && !dev &&
- flags->interrupt_info_struct.interrupt_type !=
- COMMAND_COMPLETE_APP_INT_PEND){
-
- goto isr_done;
- }
-
- /* if critical due to peripheral operations
- * ie. update() or getstats() then reset the interrupt and
- * wait for the board to retrigger.
- */
- if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "ISR CRIT TO PERI\n");
- goto isr_done;
- }
-
- /* On a 508 Card, if critical due to if_send
- * Major Error !!! */
- if(card->hw.type != SDLA_S514) {
- if(test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
- card->devname, card->wandev.critical);
- card->in_isr = 0;
- flags->interrupt_info_struct.interrupt_type = 0;
- return;
- }
- }
-
- switch(flags->interrupt_info_struct.interrupt_type) {
-
- case RX_APP_INT_PEND: /* 0x01: receive interrupt */
- rx_intr(card);
- break;
-
- case TX_APP_INT_PEND: /* 0x02: transmit interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TX_FRAME;
-
- if (card->tty_opt){
- wanpipe_tty_trigger_poll(card);
- break;
- }
-
- if (dev && netif_queue_stopped(dev)){
- if (card->u.c.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- break;
-
- case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
- ++ Intr_test_counter;
- break;
-
- case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */
- process_chdlc_exception(card);
- break;
-
- case GLOBAL_EXCEP_COND_APP_INT_PEND:
- process_global_exception(card);
- break;
-
- case TIMER_APP_INT_PEND:
- timer_intr(card);
- break;
-
- default:
- printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
- card->devname,
- flags->interrupt_info_struct.interrupt_type);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
- break;
- }
-
-isr_done:
-
- card->in_isr = 0;
- flags->interrupt_info_struct.interrupt_type = 0;
- return;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr (sdla_t* card)
-{
- struct net_device *dev;
- chdlc_private_area_t *chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
- struct sk_buff *skb;
- unsigned len;
- unsigned addr = rxbuf->ptr_data_bfr;
- void *buf;
- int i,udp_type;
-
- if (rxbuf->opp_flag != 0x01) {
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
-
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it measn that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- chdlc_set_intr_mode(card,0);
- return;
- }
-
- len = rxbuf->frame_length;
-
- if (card->tty_opt){
-
- if (rxbuf->error_flag){
- goto rx_exit;
- }
-
- if (len <= CRC_LENGTH){
- goto rx_exit;
- }
-
- if (!card->u.c.async_mode){
- len -= CRC_LENGTH;
- }
-
- wanpipe_tty_receive(card,addr,len);
- goto rx_exit;
- }
-
- dev = card->wandev.dev;
-
- if (!dev){
- goto rx_exit;
- }
-
- if (!netif_running(dev))
- goto rx_exit;
-
- chdlc_priv_area = dev->priv;
-
-
- /* Allocate socket buffer */
- skb = dev_alloc_skb(len);
-
- if (skb == NULL) {
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- ++card->wandev.stats.rx_dropped;
- goto rx_exit;
- }
-
- /* Copy data to the socket buffer */
- if((addr + len) > card->u.c.rx_top + 1) {
- unsigned tmp = card->u.c.rx_top - addr + 1;
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, addr, buf, tmp);
- addr = card->u.c.rx_base;
- len -= tmp;
- }
-
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, addr, buf, len);
-
- skb->protocol = htons(ETH_P_IP);
-
- card->wandev.stats.rx_packets ++;
- card->wandev.stats.rx_bytes += skb->len;
- udp_type = udp_pkt_type( skb, card );
-
- if(udp_type == UDP_CPIPE_TYPE) {
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
- card, skb, dev, chdlc_priv_area)) {
- flags->interrupt_info_struct.
- interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- } else if(card->u.c.usedby == API) {
-
- api_rx_hdr_t* api_rx_hdr;
- skb_push(skb, sizeof(api_rx_hdr_t));
- api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];
- api_rx_hdr->error_flag = rxbuf->error_flag;
- api_rx_hdr->time_stamp = rxbuf->time_stamp;
-
- skb->protocol = htons(PVC_PROT);
- skb->mac.raw = skb->data;
- skb->dev = dev;
- skb->pkt_type = WAN_PACKET_DATA;
-
- bh_enqueue(dev, skb);
-
- if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))
- wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);
- }else{
- /* FIXME: we should check to see if the received packet is a
- multicast packet so that we can increment the multicast
- statistic
- ++ chdlc_priv_area->if_stats.multicast;
- */
- /* Pass it up the protocol stack */
-
- skb->dev = dev;
- skb->mac.raw = skb->data;
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
-
-rx_exit:
- /* Release buffer element and calculate a pointer to the next one */
- rxbuf->opp_flag = 0x00;
- card->u.c.rxmb = ++ rxbuf;
- if((void*)rxbuf > card->u.c.rxbuf_last){
- card->u.c.rxmb = card->u.c.rxbuf_base;
- }
-}
-
-/*============================================================================
- * Timer interrupt handler.
- * The timer interrupt is used for two purposes:
- * 1) Processing udp calls from 'cpipemon'.
- * 2) Reading board-level statistics for updating the proc file system.
- */
-void timer_intr(sdla_t *card)
-{
- struct net_device* dev;
- chdlc_private_area_t* chdlc_priv_area = NULL;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-
- if ((dev = card->wandev.dev)==NULL){
- flags = card->u.c.flags;
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- return;
- }
-
- chdlc_priv_area = dev->priv;
-
- if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
- if (!config_chdlc(card)){
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
- }
- }
-
- /* process a udp call if pending */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
- process_udp_mgmt_pkt(card, dev,
- chdlc_priv_area);
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
- }
-
- /* read the communications statistics if required */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
- update_comms_stats(card, chdlc_priv_area);
- if(!(-- chdlc_priv_area->update_comms_stats)) {
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- /* only disable the timer interrupt if there are no udp or statistic */
- /* updates pending */
- if(!chdlc_priv_area->timer_int_enabled) {
- flags = card->u.c.flags;
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- }
-}
-
-/*------------------------------------------------------------------------------
- Miscellaneous Functions
- - set_chdlc_config() used to set configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_chdlc_config(sdla_t* card)
-{
- CHDLC_CONFIGURATION_STRUCT cfg;
-
- memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
-
- if(card->wandev.clocking){
- cfg.baud_rate = card->wandev.bps;
- }
-
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
- cfg.modem_config_options = 0;
- cfg.modem_status_timer = 100;
-
- cfg.CHDLC_protocol_options = card->u.c.protocol_options;
-
- if (card->tty_opt){
- cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES;
- }
-
- cfg.percent_data_buffer_for_Tx = (card->u.c.receive_only) ? 0 : 50;
- cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
-
- if (card->tty_opt){
- card->wandev.mtu = TTY_CHDLC_MAX_MTU;
- }
- cfg.max_CHDLC_data_field_length = card->wandev.mtu;
- cfg.transmit_keepalive_timer = card->u.c.kpalv_tx;
- cfg.receive_keepalive_timer = card->u.c.kpalv_rx;
- cfg.keepalive_error_tolerance = card->u.c.kpalv_err;
- cfg.SLARP_request_timer = card->u.c.slarp_timer;
-
- if (cfg.SLARP_request_timer) {
- cfg.IP_address = 0;
- cfg.IP_netmask = 0;
-
- }else if (card->wandev.dev){
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
-
- struct in_device *in_dev = dev->ip_ptr;
-
- if(in_dev != NULL) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
-
- if (ifa != NULL ) {
- cfg.IP_address = ntohl(ifa->ifa_local);
- cfg.IP_netmask = ntohl(ifa->ifa_mask);
- chdlc_priv_area->IP_address = ntohl(ifa->ifa_local);
- chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask);
- }
- }
-
- /* FIXME: We must re-think this message in next release
- if((cfg.IP_address & 0x000000FF) > 2) {
- printk(KERN_WARNING "\n");
- printk(KERN_WARNING " WARNING:%s configured with an\n",
- card->devname);
- printk(KERN_WARNING " invalid local IP address.\n");
- printk(KERN_WARNING " Slarp pragmatics will fail.\n");
- printk(KERN_WARNING " IP address should be of the\n");
- printk(KERN_WARNING " format A.B.C.1 or A.B.C.2.\n");
- }
- */
- }
-
- return chdlc_configure(card, &cfg);
-}
-
-
-/*-----------------------------------------------------------------------------
- set_asy_config() used to set asynchronous configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_asy_config(sdla_t* card)
-{
-
- ASY_CONFIGURATION_STRUCT cfg;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int err;
-
- memset(&cfg, 0, sizeof(ASY_CONFIGURATION_STRUCT));
-
- if(card->wandev.clocking)
- cfg.baud_rate = card->wandev.bps;
-
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
- cfg.modem_config_options = 0;
- cfg.asy_API_options = card->u.c.api_options;
- cfg.asy_protocol_options = card->u.c.protocol_options;
- cfg.Tx_bits_per_char = card->u.c.tx_bits_per_char;
- cfg.Rx_bits_per_char = card->u.c.rx_bits_per_char;
- cfg.stop_bits = card->u.c.stop_bits;
- cfg.parity = card->u.c.parity;
- cfg.break_timer = card->u.c.break_timer;
- cfg.asy_Rx_inter_char_timer = card->u.c.inter_char_timer;
- cfg.asy_Rx_complete_length = card->u.c.rx_complete_length;
- cfg.XON_char = card->u.c.xon_char;
- cfg.XOFF_char = card->u.c.xoff_char;
- cfg.asy_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
-
- mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT);
- memcpy(mailbox->data, &cfg, mailbox->buffer_length);
- mailbox->command = SET_ASY_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mailbox);
- return err;
-}
-
-/*============================================================================
- * Enable asynchronous communications.
- */
-
-static int asy_comm_enable (sdla_t* card)
-{
-
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_ASY_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK && card->wandev.dev)
- chdlc_error(card, err, mb);
-
- if (!err)
- card->u.c.comm_enabled = 1;
-
- return err;
-}
-
-/*============================================================================
- * Process global exception condition
- */
-static int process_global_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int err;
-
- mbox->buffer_length = 0;
- mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
- err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
-
- if(err != CMD_TIMEOUT ){
-
- switch(mbox->return_code) {
-
- case EXCEP_MODEM_STATUS_CHANGE:
-
- printk(KERN_INFO "%s: Modem status change\n",
- card->devname);
-
- switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
- case (DCD_HIGH):
- printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
- break;
- case (CTS_HIGH):
- printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);
- break;
- case ((DCD_HIGH | CTS_HIGH)):
- printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
- break;
- default:
- printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
- break;
- }
- break;
-
- case EXCEP_TRC_DISABLED:
- printk(KERN_INFO "%s: Line trace disabled\n",
- card->devname);
- break;
-
- case EXCEP_IRQ_TIMEOUT:
- printk(KERN_INFO "%s: IRQ timeout occurred\n",
- card->devname);
- break;
-
- case 0x17:
- if (card->tty_opt){
- if (card->tty && card->tty_open){
- printk(KERN_INFO
- "%s: Modem Hangup Exception: Hanging Up!\n",
- card->devname);
- tty_hangup(card->tty);
- }
- break;
- }
-
- /* If TTY is not used just drop throught */
-
- default:
- printk(KERN_INFO "%s: Global exception %x\n",
- card->devname, mbox->return_code);
- break;
- }
- }
- return 0;
-}
-
-
-/*============================================================================
- * Process chdlc exception condition
- */
-static int process_chdlc_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_EXCEPTION_CONDITION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if(err != CMD_TIMEOUT) {
-
- switch (err) {
-
- case EXCEP_LINK_ACTIVE:
- port_set_state(card, WAN_CONNECTED);
- trigger_chdlc_poll(card->wandev.dev);
- break;
-
- case EXCEP_LINK_INACTIVE_MODEM:
- port_set_state(card, WAN_DISCONNECTED);
- unconfigure_ip(card);
- trigger_chdlc_poll(card->wandev.dev);
- break;
-
- case EXCEP_LINK_INACTIVE_KPALV:
- port_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO "%s: Keepalive timer expired.\n",
- card->devname);
- unconfigure_ip(card);
- trigger_chdlc_poll(card->wandev.dev);
- break;
-
- case EXCEP_IP_ADDRESS_DISCOVERED:
- if (configure_ip(card))
- return -1;
- break;
-
- case EXCEP_LOOPBACK_CONDITION:
- printk(KERN_INFO "%s: Loopback Condition Detected.\n",
- card->devname);
- break;
-
- case NO_CHDLC_EXCEP_COND_TO_REPORT:
- printk(KERN_INFO "%s: No exceptions reported.\n",
- card->devname);
- break;
- }
-
- }
- return 0;
-}
-
-
-/*============================================================================
- * Configure IP from SLARP negotiation
- * This adds dynamic routes when SLARP has provided valid addresses
- */
-
-static int configure_ip (sdla_t* card)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area;
- char err;
-
- if (!dev)
- return 0;
-
- chdlc_priv_area = dev->priv;
-
-
- /* set to discover */
- if(card->u.c.slarp_timer != 0x00) {
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_CONFIGURATION_STRUCT *cfg;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- return -1;
- }
-
- cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data;
- chdlc_priv_area->IP_address = cfg->IP_address;
- chdlc_priv_area->IP_netmask = cfg->IP_netmask;
-
- /* Set flag to add route */
- chdlc_priv_area->route_status = ADD_ROUTE;
-
- /* The idea here is to add the route in the poll routine.
- This way, we aren't in interrupt context when adding routes */
- trigger_chdlc_poll(dev);
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Un-Configure IP negotiated by SLARP
- * This removes dynamic routes when the link becomes inactive.
- */
-
-static int unconfigure_ip (sdla_t* card)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area;
-
- if (!dev)
- return 0;
-
- chdlc_priv_area= dev->priv;
-
- if (chdlc_priv_area->route_status == ROUTE_ADDED) {
-
- /* Note: If this function is called, the
- * port state has been DISCONNECTED. This state
- * change will trigger a poll_disconnected
- * function, that will check for this condition.
- */
- chdlc_priv_area->route_status = REMOVE_ROUTE;
-
- }
- return 0;
-}
-
-/*============================================================================
- * Routine to add/remove routes
- * Called like a polling routine when Routes are flagged to be added/removed.
- */
-
-static void process_route (sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
- unsigned char port_num;
- chdlc_private_area_t *chdlc_priv_area = NULL;
- u32 local_IP_addr = 0;
- u32 remote_IP_addr = 0;
- u32 IP_netmask, IP_addr;
- int err = 0;
- struct in_device *in_dev;
- mm_segment_t fs;
- struct ifreq if_info;
- struct sockaddr_in *if_data1, *if_data2;
-
- chdlc_priv_area = dev->priv;
- port_num = card->u.c.comm_port;
-
- /* Bug Fix Mar 16 2000
- * AND the IP address to the Mask before checking
- * the last two bits. */
-
- if((chdlc_priv_area->route_status == ADD_ROUTE) &&
- ((chdlc_priv_area->IP_address & ~chdlc_priv_area->IP_netmask) > 2)) {
-
- printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname);
-
- if(card->u.c.slarp_timer) {
- u32 addr_net = htonl(chdlc_priv_area->IP_address);
-
- printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u received\n",
- card->devname,
- NIPQUAD(addr_net));
- printk(KERN_INFO "%s: from remote station.\n",
- card->devname);
-
- }else{
- u32 addr_net = htonl(chdlc_priv_area->IP_address);
-
- printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u issued\n",
- card->devname,
- NIPQUAD(addr_net));
- printk(KERN_INFO "%s: to remote station. Local\n",
- card->devname);
- printk(KERN_INFO "%s: IP address must be A.B.C.1\n",
- card->devname);
- printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname);
- }
-
- /* remove the route due to the IP address error condition */
- chdlc_priv_area->route_status = REMOVE_ROUTE;
- err = 1;
- }
-
- /* If we are removing a route with bad IP addressing, then use the */
- /* locally configured IP addresses */
- if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) {
-
- /* do not remove a bad route that has already been removed */
- if(chdlc_priv_area->route_removed) {
- return;
- }
-
- in_dev = dev->ip_ptr;
-
- if(in_dev != NULL) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
- if (ifa != NULL ) {
- local_IP_addr = ifa->ifa_local;
- IP_netmask = ifa->ifa_mask;
- }
- }
- }else{
- /* According to Cisco HDLC, if the point-to-point address is
- A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.
- */
- IP_netmask = ntohl(chdlc_priv_area->IP_netmask);
- remote_IP_addr = ntohl(chdlc_priv_area->IP_address);
-
-
- /* If Netmask is 255.255.255.255 the local address
- * calculation will fail. Default it back to 255.255.255.0 */
- if (IP_netmask == 0xffffffff)
- IP_netmask &= 0x00ffffff;
-
- /* Bug Fix Mar 16 2000
- * AND the Remote IP address with IP netmask, instead
- * of static netmask of 255.255.255.0 */
- local_IP_addr = (remote_IP_addr & IP_netmask) +
- (~remote_IP_addr & ntohl(0x0003));
-
- if(!card->u.c.slarp_timer) {
- IP_addr = local_IP_addr;
- local_IP_addr = remote_IP_addr;
- remote_IP_addr = IP_addr;
- }
- }
-
- fs = get_fs(); /* Save file system */
- set_fs(get_ds()); /* Get user space block */
-
- /* Setup a structure for adding/removing routes */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- switch (chdlc_priv_area->route_status) {
-
- case ADD_ROUTE:
-
- if(!card->u.c.slarp_timer) {
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = remote_IP_addr;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- } else {
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = local_IP_addr;
- if_data1->sin_family = AF_INET;
- if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = remote_IP_addr;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- }
- }
-
- if(err) {
- printk(KERN_INFO "%s: Add route %u.%u.%u.%u failed (%d)\n",
- card->devname, NIPQUAD(remote_IP_addr), err);
- } else {
- ((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED;
- printk(KERN_INFO "%s: Dynamic route added.\n",
- card->devname);
- printk(KERN_INFO "%s: Local IP addr : %u.%u.%u.%u\n",
- card->devname, NIPQUAD(local_IP_addr));
- printk(KERN_INFO "%s: Remote IP addr: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(remote_IP_addr));
- chdlc_priv_area->route_removed = 0;
- }
- break;
-
-
- case REMOVE_ROUTE:
-
- /* Change the local ip address of the interface to 0.
- * This will also delete the destination route.
- */
- if(!card->u.c.slarp_timer) {
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = 0;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- } else {
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = 0;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFADDR,&if_info);
-
- }
- if(err) {
- printk(KERN_INFO
- "%s: Remove route %u.%u.%u.%u failed, (err %d)\n",
- card->devname, NIPQUAD(remote_IP_addr),
- err);
- } else {
- ((chdlc_private_area_t *)dev->priv)->route_status =
- NO_ROUTE;
- printk(KERN_INFO "%s: Dynamic route removed: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(local_IP_addr));
- chdlc_priv_area->route_removed = 1;
- }
- break;
- }
-
- set_fs(fs); /* Restore file system */
-
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area)
-{
- int udp_pkt_stored = 0;
-
- if(!chdlc_priv_area->udp_pkt_lgth &&
- (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
- chdlc_priv_area->udp_pkt_lgth = skb->len;
- chdlc_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-/*=============================================================================
- * Process UDP management packet.
- */
-
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area )
-{
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short buffer_length, real_len;
- unsigned long data_ptr;
- unsigned data_length;
- int udp_mgmt_req_valid = 1;
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- chdlc_udp_pkt_t *chdlc_udp_pkt;
- struct timeval tv;
- int err;
- char ut_char;
-
- chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
-
- /* Only these commands are support for remote debugging.
- * All others are not */
- switch(chdlc_udp_pkt->cblock.command) {
-
- case READ_GLOBAL_STATISTICS:
- case READ_MODEM_STATUS:
- case READ_CHDLC_LINK_STATUS:
- case CPIPE_ROUTER_UP_TIME:
- case READ_COMMS_ERROR_STATS:
- case READ_CHDLC_OPERATIONAL_STATS:
-
- /* These two commands are executed for
- * each request */
- case READ_CHDLC_CONFIGURATION:
- case READ_CHDLC_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
-
- /* set length to 0 */
- chdlc_udp_pkt->cblock.buffer_length = 0;
-
- /* set return code */
- chdlc_udp_pkt->cblock.return_code = 0xCD;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,chdlc_udp_pkt->cblock.command);
- }
-
- } else {
- unsigned long trace_status_cfg_addr = 0;
- TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
- TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
-
- switch(chdlc_udp_pkt->cblock.command) {
-
- case CPIPE_ENABLE_TRACING:
- if (!chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
-
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_ACTIVE;
- /* Trace delay mode is not used because it slows
- down transfer and results in a standoff situation
- when there is a lot of data */
-
- /* Configure the Trace based on user inputs */
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |=
- chdlc_udp_pkt->data[0];
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_deactivation_timer = 4000;
-
-
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- card->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- /* Get the base address of the trace element list */
- mb->buffer_length = 0;
- mb->command = READ_TRACE_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
- mb->data) -> ptr_trace_stat_el_cfg_struct;
-
- sdla_peek(&card->hw, trace_status_cfg_addr,
- &trace_cfg_struct, sizeof(trace_cfg_struct));
-
- chdlc_priv_area->start_trace_addr = trace_cfg_struct.
- base_addr_trace_status_elements;
-
- chdlc_priv_area->number_trace_elements =
- trace_cfg_struct.number_trace_status_elements;
-
- chdlc_priv_area->end_trace_addr = (unsigned long)
- ((TRACE_STATUS_ELEMENT_STRUCT *)
- chdlc_priv_area->start_trace_addr +
- (chdlc_priv_area->number_trace_elements - 1));
-
- chdlc_priv_area->base_addr_trace_buffer =
- trace_cfg_struct.base_addr_trace_buffer;
-
- chdlc_priv_area->end_addr_trace_buffer =
- trace_cfg_struct.end_addr_trace_buffer;
-
- chdlc_priv_area->curr_trace_addr =
- trace_cfg_struct.next_trace_element_to_use;
-
- chdlc_priv_area->available_buffer_space = 2000 -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t) -
- sizeof(trace_info_t);
- }
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- chdlc_priv_area->TracingEnabled = 1;
- break;
-
-
- case CPIPE_DISABLE_TRACING:
- if (chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_INACTIVE;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
-
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- break;
-
-
- case CPIPE_GET_TRACE_INFO:
-
- if (!chdlc_priv_area->TracingEnabled) {
- chdlc_udp_pkt->cblock.return_code = 1;
- mb->buffer_length = 0;
- break;
- }
-
- chdlc_udp_pkt->trace_info.ismoredata = 0x00;
- buffer_length = 0; /* offset of packet already occupied */
-
- for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
-
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &chdlc_udp_pkt->data[buffer_length];
-
- sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
- (unsigned char *)&trace_element_struct,
- sizeof(TRACE_STATUS_ELEMENT_STRUCT));
-
- if (trace_element_struct.opp_flag == 0x00) {
- break;
- }
-
- /* get pointer to real data */
- data_ptr = trace_element_struct.ptr_data_bfr;
-
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element_struct.trace_length;
- }else{
- data_length = 0;
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
-
- if( (chdlc_priv_area->available_buffer_space - buffer_length)
- < ( sizeof(trace_pkt_t) + data_length) ) {
-
- /* indicate there are more frames on board & exit */
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- break;
- }
-
- trace_pkt->status = trace_element_struct.trace_type;
-
- trace_pkt->time_stamp =
- trace_element_struct.trace_time_stamp;
-
- trace_pkt->real_length =
- trace_element_struct.trace_length;
-
- /* see if we can fit the frame into the user buffer */
- real_len = trace_pkt->real_length;
-
- if (data_ptr == 0) {
- trace_pkt->data_avail = 0x00;
- } else {
- unsigned tmp = 0;
-
- /* get the data from circular buffer
- must check for end of buffer */
- trace_pkt->data_avail = 0x01;
-
- if ((data_ptr + real_len) >
- chdlc_priv_area->end_addr_trace_buffer + 1){
-
- tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
- sdla_peek(&card->hw, data_ptr,
- trace_pkt->data,tmp);
- data_ptr = chdlc_priv_area->base_addr_trace_buffer;
- }
-
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data[tmp], real_len - tmp);
- }
-
- /* zero the opp flag to show we got the frame */
- ut_char = 0x00;
- sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
-
- /* now move onto the next frame */
- chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
-
- /* check if we went over the last address */
- if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
- chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
- }
-
- if(trace_pkt->data_avail == 0x01) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += sizeof(trace_pkt_t);
-
- } /* For Loop */
-
- if (frames == chdlc_priv_area->number_trace_elements){
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
- chdlc_udp_pkt->trace_info.num_frames = frames;
-
- mb->buffer_length = buffer_length;
- chdlc_udp_pkt->cblock.buffer_length = buffer_length;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-
- break;
-
-
- case CPIPE_FT1_READ_STATUS:
- ((unsigned char *)chdlc_udp_pkt->data )[0] =
- flags->FT1_info_struct.parallel_port_A_input;
-
- ((unsigned char *)chdlc_udp_pkt->data )[1] =
- flags->FT1_info_struct.parallel_port_B_input;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- chdlc_udp_pkt->cblock.buffer_length = 2;
- mb->buffer_length = 2;
- break;
-
- case CPIPE_ROUTER_UP_TIME:
- do_gettimeofday( &tv );
- chdlc_priv_area->router_up_time = tv.tv_sec -
- chdlc_priv_area->router_start_time;
- *(unsigned long *)&chdlc_udp_pkt->data =
- chdlc_priv_area->router_up_time;
- mb->buffer_length = sizeof(unsigned long);
- chdlc_udp_pkt->cblock.buffer_length = sizeof(unsigned long);
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- break;
-
- case FT1_MONITOR_STATUS_CTRL:
- /* Enable FT1 MONITOR STATUS */
- if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||
- (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-
- if( rCount++ != 0 ) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if( chdlc_udp_pkt->data[0] == 0) {
-
- if( --rCount != 0) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
- goto dflt_1;
-
- default:
-dflt_1:
- /* it's a board command */
- mb->command = chdlc_udp_pkt->cblock.command;
- mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
- if (mb->buffer_length) {
- memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
- data, mb->buffer_length);
- }
- /* run the command on the board */
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- break;
- }
-
- /* copy the result back to our buffer */
- memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t));
-
- if (mb->buffer_length) {
- memcpy(&chdlc_udp_pkt->data, &mb->data,
- mb->buffer_length);
- }
-
- } /* end of switch */
- } /* end of else */
-
- /* Fill UDP TTL */
- chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
-
- len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
-
- /* Must check if we interrupted if_send() routine. The
- * tx buffers might be used. If so drop the packet */
- if (!test_bit(SEND_CRIT,&card->wandev.critical)) {
-
- if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
- ++ card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += len;
- }
- }
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, len);
- memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
-
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- dev->last_rx = jiffies;
- } else {
-
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- }
-
- chdlc_priv_area->udp_pkt_lgth = 0;
-
- return 0;
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-
-static void init_chdlc_tx_rx_buff( sdla_t* card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
- CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
- char err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- if (card->wandev.dev){
- chdlc_error(card,err,mb);
- }
- return;
- }
-
- if(card->hw.type == SDLA_S514) {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct));
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- tx_config->base_addr_Tx_status_elements);
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)
- card->u.c.txbuf_base +
- (tx_config->number_Tx_status_elements - 1);
-
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- rx_config->base_addr_Rx_status_elements);
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)
- card->u.c.rxbuf_base +
- (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- tx_config->next_Tx_status_element_to_use);
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- rx_config->next_Rx_status_element_to_use);
- }
- else {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
- + (tx_config->number_Tx_status_elements - 1);
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
- + (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
- }
-
- /* Setup Actual Buffer Start and end addresses */
- card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
- card->u.c.rx_top = rx_config->end_addr_Rx_buffer;
-
-}
-
-/*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err,i;
-
- Intr_test_counter = 0;
-
- err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
-
- if (err == CMD_OK) {
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != CMD_OK)
- chdlc_error(card, err, mb);
- }
- }
- else {
- return err;
- }
-
- err = chdlc_set_intr_mode(card, 0);
-
- if (err != CMD_OK)
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
-static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
-{
- chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
-
-#ifdef _WAN_UDP_DEBUG
- printk(KERN_INFO "SIG %s = %s\n\
- UPP %x = %x\n\
- PRT %x = %x\n\
- REQ %i = %i\n\
- 36 th = %x 37th = %x\n",
- chdlc_udp_pkt->wp_mgmt.signature,
- UDPMGMT_SIGNATURE,
- chdlc_udp_pkt->udp_pkt.udp_dst_port,
- ntohs(card->wandev.udp_port),
- chdlc_udp_pkt->ip_pkt.protocol,
- UDPMGMT_UDP_PROTOCOL,
- chdlc_udp_pkt->wp_mgmt.request_reply,
- UDPMGMT_REQUEST,
- skb->data[36], skb->data[37]);
-#endif
-
- if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
- (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-
- return UDP_CPIPE_TYPE;
-
- }else{
- return UDP_INVALID_TYPE;
- }
-}
-
-/*============================================================================
- * Set PORT state.
- */
-static void port_set_state (sdla_t *card, int state)
-{
- if (card->u.c.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: Link connected!\n",
- card->devname);
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: Link connecting...\n",
- card->devname);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: Link disconnected!\n",
- card->devname);
- break;
- }
-
- card->wandev.state = card->u.c.state = state;
- if (card->wandev.dev){
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- chdlc_priv_area->common.state = state;
- }
- }
-}
-
-/*===========================================================================
- * config_chdlc
- *
- * Configure the chdlc protocol and enable communications.
- *
- * The if_open() function binds this function to the poll routine.
- * Therefore, this function will run every time the chdlc interface
- * is brought up. We cannot run this function from the if_open
- * because if_open does not have access to the remote IP address.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses have changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- *
- */
-
-static int config_chdlc (sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- if (card->u.c.comm_enabled){
-
- /* Jun 20. 2000: NC
- * IP addresses are not used in the API mode */
-
- if ((chdlc_priv_area->ip_local_tmp != chdlc_priv_area->ip_local ||
- chdlc_priv_area->ip_remote_tmp != chdlc_priv_area->ip_remote) &&
- card->u.c.usedby == WANPIPE) {
-
- /* The IP addersses have changed, we must
- * stop the communications and reconfigure
- * the card. Reason: the firmware must know
- * the local and remote IP addresses. */
- disable_comm(card);
- port_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO
- "%s: IP addresses changed!\n",
- card->devname);
- printk(KERN_INFO
- "%s: Restarting communications ...\n",
- card->devname);
- }else{
- /* IP addresses are the same and the link is up,
- * we don't have to do anything here. Therefore, exit */
- return 0;
- }
- }
-
- chdlc_priv_area->ip_local = chdlc_priv_area->ip_local_tmp;
- chdlc_priv_area->ip_remote = chdlc_priv_area->ip_remote_tmp;
-
-
- /* Setup the Board for asynchronous mode */
- if (card->u.c.async_mode){
-
- if (set_asy_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n",
- card->devname);
- return 0;
- }
- }else{
- /* Setup the Board for CHDLC */
- if (set_chdlc_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC configuration!\n",
- card->devname);
- return 0;
- }
- }
-
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return 0;
- }
-
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
- /* In TTY mode, receive interrupt will be enabled during
- * wanpipe_tty_open() operation */
- if (card->tty_opt){
- flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_RX_FRAME;
- }
-
- /* Enable communications */
- if (card->u.c.async_mode){
- if (asy_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable async commnunication!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
- }else{
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
- }
-
- /* Initialize Rx/Tx buffer control fields */
- init_chdlc_tx_rx_buff(card);
- port_set_state(card, WAN_CONNECTING);
- return 0;
-}
-
-
-/*============================================================
- * chdlc_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * CHDLC polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each CHDLC
- * interface through a tq_schedule bottom half.
- *
- * trigger_chdlc_poll() function is used to kick
- * the chldc_poll routine.
- */
-
-static void chdlc_poll(struct net_device *dev)
-{
- chdlc_private_area_t *chdlc_priv_area;
- sdla_t *card;
- u8 check_gateway=0;
- SHARED_MEMORY_INFO_STRUCT* flags;
-
-
- if (!dev || (chdlc_priv_area=dev->priv) == NULL)
- return;
-
- card = chdlc_priv_area->card;
- flags = card->u.c.flags;
-
- /* (Re)Configuraiton is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* if_open() function has triggered the polling routine
- * to determine the configured IP addresses. Once the
- * addresses are found, trigger the chdlc configuration */
- if (test_bit(0,&chdlc_priv_area->config_chdlc)){
-
- chdlc_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP);
- chdlc_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- /* Jun 20. 2000 Bug Fix
- * Only perform this check in WANPIPE mode, since
- * IP addresses are not used in the API mode. */
-
- if (chdlc_priv_area->ip_local_tmp == chdlc_priv_area->ip_remote_tmp &&
- card->u.c.slarp_timer == 0x00 &&
- !card->u.c.backup &&
- card->u.c.usedby == WANPIPE){
-
- if (++chdlc_priv_area->ip_error > MAX_IP_ERRORS){
- printk(KERN_INFO "\n%s: --- WARNING ---\n",
- card->devname);
- printk(KERN_INFO
- "%s: The local IP address is the same as the\n",
- card->devname);
- printk(KERN_INFO
- "%s: Point-to-Point IP address.\n",
- card->devname);
- printk(KERN_INFO "%s: --- WARNING ---\n\n",
- card->devname);
- }else{
- clear_bit(POLL_CRIT,&card->wandev.critical);
- chdlc_priv_area->poll_delay_timer.expires = jiffies+HZ;
- add_timer(&chdlc_priv_area->poll_delay_timer);
- return;
- }
- }
-
- clear_bit(0,&chdlc_priv_area->config_chdlc);
- clear_bit(POLL_CRIT,&card->wandev.critical);
-
- chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- return;
- }
- /* Dynamic interface implementation, as well as dynamic
- * routing. */
-
- switch (card->u.c.state){
-
- case WAN_DISCONNECTED:
-
- /* If the dynamic interface configuration is on, and interface
- * is up, then bring down the netowrk interface */
-
- if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
- !test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) &&
- card->wandev.dev->flags & IFF_UP){
-
- printk(KERN_INFO "%s: Interface %s down.\n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags&~IFF_UP));
- set_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
- chdlc_priv_area->route_status = NO_ROUTE;
-
- }else{
- /* We need to check if the local IP address is
- * zero. If it is, we shouldn't try to remove it.
- */
-
- if (card->wandev.dev->flags & IFF_UP &&
- get_ip_address(card->wandev.dev,WAN_LOCAL_IP) &&
- chdlc_priv_area->route_status != NO_ROUTE &&
- card->u.c.slarp_timer){
-
- process_route(card);
- }
- }
- break;
-
- case WAN_CONNECTED:
-
- /* In SMP machine this code can execute before the interface
- * comes up. In this case, we must make sure that we do not
- * try to bring up the interface before dev_open() is finished */
-
-
- /* DEV_DOWN will be set only when we bring down the interface
- * for the very first time. This way we know that it was us
- * that brought the interface down */
-
- if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
- test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) &&
- !(card->wandev.dev->flags & IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s up.\n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
- clear_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
- check_gateway=1;
- }
-
- if (chdlc_priv_area->route_status == ADD_ROUTE &&
- card->u.c.slarp_timer){
-
- process_route(card);
- check_gateway=1;
- }
-
- if (chdlc_priv_area->gateway && check_gateway)
- add_gateway(card,dev);
-
- break;
- }
-
- clear_bit(POLL_CRIT,&card->wandev.critical);
-}
-
-/*============================================================
- * trigger_chdlc_poll
- *
- * Description:
- * Add a chdlc_poll() work entry into the keventd work queue
- * for a specific dlci/interface. This will kick
- * the fr_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
-static void trigger_chdlc_poll(struct net_device *dev)
-{
- chdlc_private_area_t *chdlc_priv_area;
- sdla_t *card;
-
- if (!dev)
- return;
-
- if ((chdlc_priv_area = dev->priv)==NULL)
- return;
-
- card = chdlc_priv_area->card;
-
- if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- return;
- }
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
- schedule_work(&chdlc_priv_area->poll_work);
-}
-
-
-static void chdlc_poll_delay (unsigned long dev_ptr)
-{
- struct net_device *dev = (struct net_device *)dev_ptr;
- trigger_chdlc_poll(dev);
-}
-
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-//*********** TTY SECTION ****************
-
-static void wanpipe_tty_trigger_tx_irq(sdla_t *card)
-{
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
-}
-
-static void wanpipe_tty_trigger_poll(sdla_t *card)
-{
- schedule_work(&card->tty_work);
-}
-
-static void tty_poll_work (void* data)
-{
- sdla_t *card = (sdla_t*)data;
- struct tty_struct *tty;
-
- if ((tty=card->tty)==NULL)
- return;
-
- tty_wakeup(tty);
-#if defined(SERIAL_HAVE_POLL_WAIT)
- wake_up_interruptible(&tty->poll_wait);
-#endif
- return;
-}
-
-static void wanpipe_tty_close(struct tty_struct *tty, struct file * filp)
-{
- sdla_t *card;
- unsigned long smp_flags;
-
- if (!tty || !tty->driver_data){
- return;
- }
-
- card = (sdla_t*)tty->driver_data;
-
- if (!card)
- return;
-
- printk(KERN_INFO "%s: Closing TTY Driver!\n",
- card->devname);
-
- /* Sanity Check */
- if (!card->tty_open)
- return;
-
- wanpipe_close(card);
- if (--card->tty_open == 0){
-
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=NULL;
- chdlc_disable_comm_shutdown(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-
- kfree(card->tty_buf);
- card->tty_buf = NULL;
- kfree(card->tty_rx);
- card->tty_rx = NULL;
- }
- return;
-}
-static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp)
-{
- unsigned long smp_flags;
- sdla_t *card;
-
- if (!tty){
- return -ENODEV;
- }
-
- if (!tty->driver_data){
- int port;
- port = tty->index;
- if ((port < 0) || (port >= NR_PORTS))
- return -ENODEV;
-
- tty->driver_data = WAN_CARD(port);
- if (!tty->driver_data)
- return -ENODEV;
- }
-
- card = (sdla_t*)tty->driver_data;
-
- if (!card){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=NULL;
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- return -ENODEV;
- }
-
- printk(KERN_INFO "%s: Opening TTY Driver!\n",
- card->devname);
-
- if (card->tty_open == 0){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=tty;
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-
- if (!card->tty_buf){
- card->tty_buf = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
- if (!card->tty_buf){
- card->tty_buf=NULL;
- card->tty=NULL;
- return -ENOMEM;
- }
- }
-
- if (!card->tty_rx){
- card->tty_rx = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
- if (!card->tty_rx){
- /* Free the buffer above */
- kfree(card->tty_buf);
- card->tty_buf=NULL;
- card->tty=NULL;
- return -ENOMEM;
- }
- }
- }
-
- ++card->tty_open;
- wanpipe_open(card);
- return 0;
-}
-
-static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
- unsigned long smp_flags=0;
- sdla_t *card=NULL;
-
- if (!tty){
- dbg_printk(KERN_INFO "NO TTY in Write\n");
- return -ENODEV;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card){
- dbg_printk(KERN_INFO "No Card in TTY Write\n");
- return -ENODEV;
- }
-
- if (count > card->wandev.mtu){
- dbg_printk(KERN_INFO "Frame too big in Write %i Max: %i\n",
- count,card->wandev.mtu);
- return -EINVAL;
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- dbg_printk(KERN_INFO "Card not connected in TTY Write\n");
- return -EINVAL;
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
- printk(KERN_INFO "%s: Critical in TTY Write\n",
- card->devname);
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return -EINVAL;
- }
-
- if (chdlc_send(card,(void*)buf,count)){
- dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n",
- card->devname);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- wanpipe_tty_trigger_tx_irq(card);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return 0;
- }
- dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return count;
-}
-
-static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
-{
- unsigned offset=0;
- unsigned olen=len;
- char fp=0;
- struct tty_struct *tty;
- int i;
- struct tty_ldisc *ld;
-
- if (!card->tty_open){
- dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
- card->devname);
- return;
- }
-
- if ((tty=card->tty) == NULL){
- dbg_printk(KERN_INFO "%s: No TTY on receive\n",
- card->devname);
- return;
- }
-
- if (!tty->driver_data){
- dbg_printk(KERN_INFO "%s: No Driver Data, or Flip on receive\n",
- card->devname);
- return;
- }
-
-
- if (card->u.c.async_mode){
- if ((tty->flip.count+len) >= TTY_FLIPBUF_SIZE){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Received packet size too big: %i bytes, Max: %i!\n",
- card->devname,len,TTY_FLIPBUF_SIZE);
- }
- return;
- }
-
-
- if((addr + len) > card->u.c.rx_top + 1) {
- offset = card->u.c.rx_top - addr + 1;
-
- sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, offset);
-
- addr = card->u.c.rx_base;
- len -= offset;
-
- tty->flip.char_buf_ptr+=offset;
- tty->flip.count+=offset;
- for (i=0;i<offset;i++){
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- }
- }
-
- sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, len);
-
- tty->flip.char_buf_ptr+=len;
- card->tty->flip.count+=len;
- for (i=0;i<len;i++){
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- }
-
- tty->low_latency=1;
- tty_flip_buffer_push(tty);
- }else{
- if (!card->tty_rx){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Receive sync buffer not available!\n",
- card->devname);
- }
- return;
- }
-
- if (len > TTY_CHDLC_MAX_MTU){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Received packet size too big: %i bytes, Max: %i!\n",
- card->devname,len,TTY_FLIPBUF_SIZE);
- }
- return;
- }
-
-
- if((addr + len) > card->u.c.rx_top + 1) {
- offset = card->u.c.rx_top - addr + 1;
-
- sdla_peek(&card->hw, addr, card->tty_rx, offset);
-
- addr = card->u.c.rx_base;
- len -= offset;
- }
- sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
- ld = tty_ldisc_ref(tty);
- if (ld) {
- if (ld->receive_buf)
- ld->receive_buf(tty,card->tty_rx,&fp,olen);
- tty_ldisc_deref(ld);
- }else{
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: NO TTY Sync line discipline!\n",
- card->devname);
- }
- }
- }
-
- dbg_printk(KERN_INFO "%s: Received Data %i\n",card->devname,olen);
- return;
-}
-
-#if 0
-static int wanpipe_tty_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
-#endif
-
-static void wanpipe_tty_stop(struct tty_struct *tty)
-{
- return;
-}
-
-static void wanpipe_tty_start(struct tty_struct *tty)
-{
- return;
-}
-
-static int config_tty (sdla_t *card)
-{
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- /* Setup the Board for asynchronous mode */
- if (card->u.c.async_mode){
-
- if (set_asy_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n",
- card->devname);
- return -EINVAL;
- }
- }else{
- /* Setup the Board for CHDLC */
- if (set_chdlc_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC configuration!\n",
- card->devname);
- return -EINVAL;
- }
- }
-
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return -EINVAL;
- }
-
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-
- /* Enable communications */
- if (card->u.c.async_mode){
- if (asy_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable async commnunication!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return -EINVAL;
- }
- }else{
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return -EINVAL;
- }
- }
-
- /* Initialize Rx/Tx buffer control fields */
- init_chdlc_tx_rx_buff(card);
- port_set_state(card, WAN_CONNECTING);
- return 0;
-}
-
-
-static int change_speed(sdla_t *card, struct tty_struct *tty,
- struct termios *old_termios)
-{
- int baud, ret=0;
- unsigned cflag;
- int dbits,sbits,parity,handshaking;
-
- cflag = tty->termios->c_cflag;
-
- /* There is always one stop bit */
- sbits=WANOPT_ONE;
-
- /* Parity is defaulted to NONE */
- parity = WANOPT_NONE;
-
- handshaking=0;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: dbits = 5; break;
- case CS6: dbits = 6; break;
- case CS7: dbits = 7; break;
- case CS8: dbits = 8; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: dbits = 8; break;
- }
-
- /* One more stop bit should be supported, thus increment
- * the number of stop bits Max=2 */
- if (cflag & CSTOPB) {
- sbits = WANOPT_TWO;
- }
- if (cflag & PARENB) {
- parity = WANOPT_EVEN;
- }
- if (cflag & PARODD){
- parity = WANOPT_ODD;
- }
-
- /* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(tty);
-
- if (!baud)
- baud = 9600; /* B0 transition handled in rs_set_termios */
-
- if (cflag & CRTSCTS) {
- handshaking|=ASY_RTS_HS_FOR_RX;
- }
-
- if (I_IGNPAR(tty))
- parity = WANOPT_NONE;
-
- if (I_IXOFF(tty)){
- handshaking|=ASY_XON_XOFF_HS_FOR_RX;
- handshaking|=ASY_XON_XOFF_HS_FOR_TX;
- }
-
- if (I_IXON(tty)){
- handshaking|=ASY_XON_XOFF_HS_FOR_RX;
- handshaking|=ASY_XON_XOFF_HS_FOR_TX;
- }
-
- if (card->u.c.async_mode){
- if (card->wandev.bps != baud)
- ret=1;
- card->wandev.bps = baud;
- }
-
- if (card->u.c.async_mode){
- if (card->u.c.protocol_options != handshaking)
- ret=1;
- card->u.c.protocol_options = handshaking;
-
- if (card->u.c.tx_bits_per_char != dbits)
- ret=1;
- card->u.c.tx_bits_per_char = dbits;
-
- if (card->u.c.rx_bits_per_char != dbits)
- ret=1;
- card->u.c.rx_bits_per_char = dbits;
-
- if (card->u.c.stop_bits != sbits)
- ret=1;
- card->u.c.stop_bits = sbits;
-
- if (card->u.c.parity != parity)
- ret=1;
- card->u.c.parity = parity;
-
- card->u.c.break_timer = 50;
- card->u.c.inter_char_timer = 10;
- card->u.c.rx_complete_length = 100;
- card->u.c.xon_char = 0xFE;
- }else{
- card->u.c.protocol_options = HDLC_STREAMING_MODE;
- }
-
- return ret;
-}
-
-
-static void wanpipe_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
- sdla_t *card;
- int err=1;
-
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card)
- return;
-
- if (change_speed(card, tty, old_termios) || !card->u.c.comm_enabled){
- unsigned long smp_flags;
-
- if (card->u.c.comm_enabled){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- chdlc_disable_comm_shutdown(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- }
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- err = config_tty(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- if (card->u.c.async_mode){
- printk(KERN_INFO "%s: TTY Async Configuration:\n"
- " Baud =%i\n"
- " Handshaking =%s\n"
- " Tx Dbits =%i\n"
- " Rx Dbits =%i\n"
- " Parity =%s\n"
- " Stop Bits =%i\n",
- card->devname,
- card->wandev.bps,
- opt_decode[card->u.c.protocol_options],
- card->u.c.tx_bits_per_char,
- card->u.c.rx_bits_per_char,
- p_decode[card->u.c.parity] ,
- card->u.c.stop_bits);
- }else{
- printk(KERN_INFO "%s: TTY Sync Configuration:\n"
- " Baud =%i\n"
- " Protocol =HDLC_STREAMING\n",
- card->devname,card->wandev.bps);
- }
- if (!err){
- port_set_state(card,WAN_CONNECTED);
- }else{
- port_set_state(card,WAN_DISCONNECTED);
- }
- }
- return;
-}
-
-static void wanpipe_tty_put_char(struct tty_struct *tty, unsigned char ch)
-{
- sdla_t *card;
- unsigned long smp_flags=0;
-
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card)
- return;
-
- if (card->wandev.state != WAN_CONNECTED)
- return;
-
- if(card->hw.type != SDLA_S514)
- s508_lock(card,&smp_flags);
-
- if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
-
- wanpipe_tty_trigger_tx_irq(card);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return;
- }
-
- if (chdlc_send(card,(void*)&ch,1)){
- wanpipe_tty_trigger_tx_irq(card);
- dbg_printk("%s: Failed to TX char!\n",card->devname);
- }
-
- dbg_printk("%s: Char TX OK\n",card->devname);
-
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return;
-}
-
-static void wanpipe_tty_flush_chars(struct tty_struct *tty)
-{
- return;
-}
-
-static void wanpipe_tty_flush_buffer(struct tty_struct *tty)
-{
- if (!tty)
- return;
-
-#if defined(SERIAL_HAVE_POLL_WAIT)
- wake_up_interruptible(&tty->poll_wait);
-#endif
- tty_wakeup(tty);
- return;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void wanpipe_tty_send_xchar(struct tty_struct *tty, char ch)
-{
- return;
-}
-
-
-static int wanpipe_tty_chars_in_buffer(struct tty_struct *tty)
-{
- return 0;
-}
-
-
-static int wanpipe_tty_write_room(struct tty_struct *tty)
-{
- sdla_t *card;
-
- printk(KERN_INFO "TTY Write Room\n");
-
- if (!tty){
- return 0;
- }
-
- card = (sdla_t *)tty->driver_data;
- if (!card)
- return 0;
-
- if (card->wandev.state != WAN_CONNECTED)
- return 0;
-
- return SEC_MAX_NO_DATA_BYTES_IN_FRAME;
-}
-
-
-static int set_modem_status(sdla_t *card, unsigned char data)
-{
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- int err;
-
- mb->buffer_length=1;
- mb->command=SET_MODEM_STATUS;
- mb->data[0]=data;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
-
- return err;
-}
-
-static void wanpipe_tty_hangup(struct tty_struct *tty)
-{
- sdla_t *card;
- unsigned long smp_flags;
-
- printk(KERN_INFO "TTY Hangup!\n");
-
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
- if (!card)
- return;
-
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- set_modem_status(card,0);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- return;
-}
-
-static void wanpipe_tty_break(struct tty_struct *tty, int break_state)
-{
- return;
-}
-
-static void wanpipe_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- return;
-}
-
-static void wanpipe_tty_throttle(struct tty_struct * tty)
-{
- return;
-}
-
-static void wanpipe_tty_unthrottle(struct tty_struct * tty)
-{
- return;
-}
-
-int wanpipe_tty_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- return 0;
-}
-
-/*
- * The serial driver boot-time initialization code!
- */
-int wanpipe_tty_init(sdla_t *card)
-{
- struct serial_state * state;
-
- /* Initialize the tty_driver structure */
-
- if (card->tty_minor < 0 || card->tty_minor > NR_PORTS){
- printk(KERN_INFO "%s: Illegal Minor TTY number (0-4): %i\n",
- card->devname,card->tty_minor);
- return -EINVAL;
- }
-
- if (WAN_CARD(card->tty_minor)){
- printk(KERN_INFO "%s: TTY Minor %i, already in use\n",
- card->devname,card->tty_minor);
- return -EBUSY;
- }
-
- if (tty_init_cnt==0){
-
- printk(KERN_INFO "%s: TTY %s Driver Init: Major %i, Minor Range %i-%i\n",
- card->devname,
- card->u.c.async_mode ? "ASYNC" : "SYNC",
- WAN_TTY_MAJOR,MIN_PORT,MAX_PORT);
-
- tty_driver_mode = card->u.c.async_mode;
-
- memset(&serial_driver, 0, sizeof(struct tty_driver));
- serial_driver.magic = TTY_DRIVER_MAGIC;
- serial_driver.owner = THIS_MODULE;
- serial_driver.driver_name = "wanpipe_tty";
- serial_driver.name = "ttyW";
- serial_driver.major = WAN_TTY_MAJOR;
- serial_driver.minor_start = WAN_TTY_MINOR;
- serial_driver.num = NR_PORTS;
- serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver.subtype = SERIAL_TYPE_NORMAL;
-
- serial_driver.init_termios = tty_std_termios;
- serial_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver.flags = TTY_DRIVER_REAL_RAW;
-
- serial_driver.refcount = 1; /* !@!@^#^&!! */
-
- serial_driver.open = wanpipe_tty_open;
- serial_driver.close = wanpipe_tty_close;
- serial_driver.write = wanpipe_tty_write;
-
- serial_driver.put_char = wanpipe_tty_put_char;
- serial_driver.flush_chars = wanpipe_tty_flush_chars;
- serial_driver.write_room = wanpipe_tty_write_room;
- serial_driver.chars_in_buffer = wanpipe_tty_chars_in_buffer;
- serial_driver.flush_buffer = wanpipe_tty_flush_buffer;
- //serial_driver.ioctl = wanpipe_tty_ioctl;
- serial_driver.throttle = wanpipe_tty_throttle;
- serial_driver.unthrottle = wanpipe_tty_unthrottle;
- serial_driver.send_xchar = wanpipe_tty_send_xchar;
- serial_driver.set_termios = wanpipe_tty_set_termios;
- serial_driver.stop = wanpipe_tty_stop;
- serial_driver.start = wanpipe_tty_start;
- serial_driver.hangup = wanpipe_tty_hangup;
- serial_driver.break_ctl = wanpipe_tty_break;
- serial_driver.wait_until_sent = wanpipe_tty_wait_until_sent;
- serial_driver.read_proc = wanpipe_tty_read_proc;
-
- if (tty_register_driver(&serial_driver)){
- printk(KERN_INFO "%s: Failed to register serial driver!\n",
- card->devname);
- }
- }
-
-
- /* The subsequent ports must comply to the initial configuration */
- if (tty_driver_mode != card->u.c.async_mode){
- printk(KERN_INFO "%s: Error: TTY Driver operation mode mismatch!\n",
- card->devname);
- printk(KERN_INFO "%s: The TTY driver is configured for %s!\n",
- card->devname, tty_driver_mode ? "ASYNC" : "SYNC");
- return -EINVAL;
- }
-
- tty_init_cnt++;
-
- printk(KERN_INFO "%s: Initializing TTY %s Driver Minor %i\n",
- card->devname,
- tty_driver_mode ? "ASYNC" : "SYNC",
- card->tty_minor);
-
- tty_card_map[card->tty_minor] = card;
- state = &rs_table[card->tty_minor];
-
- state->magic = SSTATE_MAGIC;
- state->line = 0;
- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
- state->irq = card->wandev.irq;
-
- INIT_WORK(&card->tty_work, tty_poll_work, (void*)card);
- return 0;
-}
-
-
-MODULE_LICENSE("GPL");
-
-/****** End ****************************************************************/
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
deleted file mode 100644
index 7f1ce9d4333e..000000000000
--- a/drivers/net/wan/sdla_fr.c
+++ /dev/null
@@ -1,5061 +0,0 @@
-/*****************************************************************************
-* sdla_fr.c WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module.
-*
-* Author(s): Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Nov 23, 2000 Nenad Corbic o Added support for 2.4.X kernels
-* Nov 15, 2000 David Rokavarg
-* Nenad Corbic o Added frame relay bridging support.
-* Original code from Mark Wells and Kristian Hoffmann has
-* been integrated into the frame relay driver.
-* Nov 13, 2000 Nenad Corbic o Added true interface type encoding option.
-* Tcpdump doesn't support Frame Relay inteface
-* types, to fix this true type option will set
-* the interface type to RAW IP mode.
-* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging:
-* Deny all and specify allowed requests.
-* Nov 06, 2000 Nenad Corbic o Wanpipe interfaces conform to raw packet interfaces.
-* Moved the if_header into the if_send() routine.
-* The if_header() was breaking the libpcap
-* support. i.e. support for tcpdump, ethereal ...
-* Oct 12. 2000 Nenad Corbic o Added error message in fr_configure
-* Jul 31, 2000 Nenad Corbic o Fixed the Router UP Time.
-* Apr 28, 2000 Nenad Corbic o Added the option to shutdown an interface
-* when the channel gets disconnected.
-* Apr 28, 2000 Nenad Corbic o Added M.Grants patch: disallow duplicate
-* interface setups.
-* Apr 25, 2000 Nenad Corbic o Added M.Grants patch: dynamically add/remove
-* new dlcis/interfaces.
-* Mar 23, 2000 Nenad Corbic o Improved task queue, bh handling.
-* Mar 16, 2000 Nenad Corbic o Added Inverse ARP support
-* Mar 13, 2000 Nenad Corbic o Added new socket API support.
-* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.
-* Feb 24, 2000 Nenad Corbic o Fixed up FT1 UDP debugging problem.
-* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels
-*
-* Nov 08, 1999 Nenad Corbic o Combined all debug UDP calls into one function
-* o Removed the ARP support. This has to be done
-* in the next version.
-* o Only a Node can implement NO signalling.
-* Initialize DLCI during if_open() if NO
-* signalling.
-* o Took out IPX support, implement in next
-* version
-* Sep 29, 1999 Nenad Corbic o Added SMP support and changed the update
-* function to use timer interrupt.
-* o Fixed the CIR bug: Set the value of BC
-* to CIR when the CIR is enabled.
-* o Updated comments, statistics and tracing.
-* Jun 02, 1999 Gideon Hack o Updated for S514 support.
-* Sep 18, 1998 Jaspreet Singh o Updated for 2.2.X kernels.
-* Jul 31, 1998 Jaspreet Singh o Removed wpf_poll routine. The channel/DLCI
-* status is received through an event interrupt.
-* Jul 08, 1998 David Fong o Added inverse ARP support.
-* Mar 26, 1997 Jaspreet Singh o Returning return codes for failed UDP cmds.
-* Jan 28, 1997 Jaspreet Singh o Improved handling of inactive DLCIs.
-* Dec 30, 1997 Jaspreet Singh o Replaced dev_tint() with mark_bh(NET_BH)
-* Dec 16, 1997 Jaspreet Singh o Implemented Multiple IPX support.
-* Nov 26, 1997 Jaspreet Singh o Improved load sharing with multiple boards
-* o Added Cli() to protect enabling of interrupts
-* while polling is called.
-* Nov 24, 1997 Jaspreet Singh o Added counters to avoid enabling of interrupts
-* when they have been disabled by another
-* interface or routine (eg. wpf_poll).
-* Nov 06, 1997 Jaspreet Singh o Added INTR_TEST_MODE to avoid polling
-* routine disable interrupts during interrupt
-* testing.
-* Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time.
-* Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow
-* control by avoiding RACE conditions. The
-* cli() and restore_flags() are taken out.
-* The fr_channel structure is appended for
-* Driver Statistics.
-* Oct 15, 1997 Farhan Thawar o updated if_send() and receive for IPX
-* Aug 29, 1997 Farhan Thawar o Removed most of the cli() and sti()
-* o Abstracted the UDP management stuff
-* o Now use tbusy and critical more intelligently
-* Jul 21, 1997 Jaspreet Singh o Can configure T391, T392, N391, N392 & N393
-* through router.conf.
-* o Protected calls to sdla_peek() by adDing
-* save_flags(), cli() and restore_flags().
-* o Added error message for Inactive DLCIs in
-* fr_event() and update_chan_state().
-* o Fixed freeing up of buffers using kfree()
-* when packets are received.
-* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets
-* o Added ability to discard multicast and
-* broadcast source addressed packets
-* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities
-* New case (0x44) statement in if_send routine
-* Added a global variable rCount to keep track
-* of FT1 status enabled on the board.
-* May 29, 1997 Jaspreet Singh o Fixed major Flow Control Problem
-* With multiple boards a problem was seen where
-* the second board always stopped transmitting
-* packet after running for a while. The code
-* got into a stage where the interrupts were
-* disabled and dev->tbusy was set to 1.
-* This caused the If_send() routine to get into
-* the if clause for it(0,dev->tbusy)
-* forever.
-* The code got into this stage due to an
-* interrupt occurring within the if clause for
-* set_bit(0,dev->tbusy). Since an interrupt
-* disables furhter transmit interrupt and
-* makes dev->tbusy = 0, this effect was undone
-* by making dev->tbusy = 1 in the if clause.
-* The Fix checks to see if Transmit interrupts
-* are disabled then do not make dev->tbusy = 1
-* Introduced a global variable: int_occur and
-* added tx_int_enabled in the wan_device
-* structure.
-* May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple
-* boards.
-*
-* Apr 25, 1997 Farhan Thawar o added UDP Management stuff
-* o fixed bug in if_send() and tx_intr() to
-* sleep and wakeup all devices
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o fixed (+1) bug in fr508_rx_intr()
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* o added tx_intr() routine
-* Jan 30, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* o fixed a bug causing driver configured as
-* a FR switch to be stuck in WAN_
-* mode
-* Jan 02, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/workqueue.h>
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <asm/io.h> /* for inb(), outb(), etc. */
-#include <linux/time.h> /* for do_gettimeofday */
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/jiffies.h> /* time_after() macro */
-#include <asm/errno.h>
-
-#include <linux/ip.h>
-#include <linux/if.h>
-
-#include <linux/if_wanpipe_common.h> /* Wanpipe Socket */
-#include <linux/if_wanpipe.h>
-
-#include <linux/sdla_fr.h> /* frame relay firmware API definitions */
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <net/route.h> /* Dynamic Route Creation */
-#include <linux/etherdevice.h> /* eth_type_trans() used for bridging */
-#include <linux/random.h>
-
-/****** Defines & Macros ****************************************************/
-
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-
-#define FR_HEADER_LEN 8 /* max encapsulation header size */
-#define FR_CHANNEL_MTU 1500 /* unfragmented logical channel MTU */
-
-/* Q.922 frame types */
-#define Q922_UI 0x03 /* Unnumbered Info frame */
-#define Q922_XID 0xAF
-
-/* DLCI configured or not */
-#define DLCI_NOT_CONFIGURED 0x00
-#define DLCI_CONFIG_PENDING 0x01
-#define DLCI_CONFIGURED 0x02
-
-/* CIR enabled or not */
-#define CIR_ENABLED 0x00
-#define CIR_DISABLED 0x01
-
-#define FRAME_RELAY_API 1
-#define MAX_BH_BUFF 10
-
-/* For handle_IPXWAN() */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-/****** Data Structures *****************************************************/
-
-/* This is an extention of the 'struct device' we create for each network
- * interface to keep the rest of channel-specific data.
- */
-typedef struct fr_channel
-{
- wanpipe_common_t common;
- char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
- unsigned dlci_configured ; /* check whether configured or not */
- unsigned cir_status; /* check whether CIR enabled or not */
- unsigned dlci; /* logical channel number */
- unsigned cir; /* committed information rate */
- unsigned bc; /* committed burst size */
- unsigned be; /* excess burst size */
- unsigned mc; /* multicast support on or off */
- unsigned tx_int_status; /* Transmit Interrupt Status */
- unsigned short pkt_length; /* Packet Length */
- unsigned long router_start_time;/* Router start time in seconds */
- unsigned long tick_counter; /* counter for transmit time out */
- char dev_pending_devtint; /* interface pending dev_tint() */
- void *dlci_int_interface; /* pointer to the DLCI Interface */
- unsigned long IB_addr; /* physical address of Interface Byte */
- unsigned long state_tick; /* time of the last state change */
- unsigned char enable_IPX; /* Enable/Disable the use of IPX */
- unsigned long network_number; /* Internal Network Number for IPX*/
- sdla_t *card; /* -> owner */
- unsigned route_flag; /* Add/Rem dest addr in route tables */
- unsigned inarp; /* Inverse Arp Request status */
- long inarp_ready; /* Ready to send requests */
- int inarp_interval; /* Time between InArp Requests */
- unsigned long inarp_tick; /* InArp jiffies tick counter */
- long interface_down; /* Bring interface down on disconnect */
- struct net_device_stats ifstats; /* interface statistics */
- if_send_stat_t drvstats_if_send;
- rx_intr_stat_t drvstats_rx_intr;
- pipe_mgmt_stat_t drvstats_gen;
- unsigned long router_up_time;
-
- unsigned short transmit_length;
- struct sk_buff *delay_skb;
-
- bh_data_t *bh_head; /* Circular buffer for chdlc_bh */
- unsigned long tq_working;
- volatile int bh_write;
- volatile int bh_read;
- atomic_t bh_buff_used;
-
- /* Polling task queue. Each interface
- * has its own task queue, which is used
- * to defer events from the interrupt */
- struct work_struct fr_poll_work;
- struct timer_list fr_arp_timer;
-
- u32 ip_local;
- u32 ip_remote;
- long config_dlci;
- long unconfig_dlci;
-
- /* Whether this interface should be setup as a gateway.
- * Used by dynamic route setup code */
- u8 gateway;
-
- /* True interface type */
- u8 true_if_encoding;
- u8 fr_header[FR_HEADER_LEN];
- char fr_header_len;
-
-} fr_channel_t;
-
-/* Route Flag options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-#define ARP_REQ 0x04
-
-/* inarp options */
-#define INARP_NONE 0x00
-#define INARP_REQUEST 0x01
-#define INARP_CONFIGURED 0x02
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_ARP 0x04
-#define TMR_INT_ENABLED_UPDATE_STATE 0x08
-#define TMR_INT_ENABLED_CONFIG 0x10
-#define TMR_INT_ENABLED_UNCONFIG 0x20
-
-
-typedef struct dlci_status
-{
- unsigned short dlci PACKED;
- unsigned char state PACKED;
-} dlci_status_t;
-
-typedef struct dlci_IB_mapping
-{
- unsigned short dlci PACKED;
- unsigned long addr_value PACKED;
-} dlci_IB_mapping_t;
-
-/* This structure is used for DLCI list Tx interrupt mode. It is used to
- enable interrupt bit and set the packet length for transmission
- */
-typedef struct fr_dlci_interface
-{
- unsigned char gen_interrupt PACKED;
- unsigned short packet_length PACKED;
- unsigned char reserved PACKED;
-} fr_dlci_interface_t;
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/* variable for keeping track of number of interrupts generated during
- * interrupt test routine
- */
-static int Intr_test_counter;
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev);
-static int new_if(struct wan_device *wandev, struct net_device *dev,
- wanif_conf_t *conf);
-static int del_if(struct wan_device *wandev, struct net_device *dev);
-static void disable_comm (sdla_t *card);
-
-/* WANPIPE-specific entry points */
-static int wpf_exec(struct sdla *card, void *u_cmd, void *u_data);
-
-/* Network device interface */
-static int if_init(struct net_device *dev);
-static int if_open(struct net_device *dev);
-static int if_close(struct net_device *dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-static int if_rebuild_hdr (struct sk_buff *skb);
-
-static int if_send(struct sk_buff *skb, struct net_device *dev);
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb);
-static struct net_device_stats *if_stats(struct net_device *dev);
-
-/* Interrupt handlers */
-static void fr_isr(sdla_t *card);
-static void rx_intr(sdla_t *card);
-static void tx_intr(sdla_t *card);
-static void timer_intr(sdla_t *card);
-static void spur_intr(sdla_t *card);
-
-/* Frame relay firmware interface functions */
-static int fr_read_version(sdla_t *card, char *str);
-static int fr_configure(sdla_t *card, fr_conf_t *conf);
-static int fr_dlci_configure(sdla_t *card, fr_dlc_conf_t *conf, unsigned dlci);
-static int fr_init_dlci (sdla_t *card, fr_channel_t *chan);
-static int fr_set_intr_mode (sdla_t *card, unsigned mode, unsigned mtu, unsigned short timeout);
-static int fr_comm_enable(sdla_t *card);
-static void fr_comm_disable(sdla_t *card);
-static int fr_get_err_stats(sdla_t *card);
-static int fr_get_stats(sdla_t *card);
-static int fr_add_dlci(sdla_t *card, int dlci);
-static int fr_activate_dlci(sdla_t *card, int dlci);
-static int fr_delete_dlci (sdla_t* card, int dlci);
-static int fr_issue_isf(sdla_t *card, int isf);
-static int fr_send(sdla_t *card, int dlci, unsigned char attr, int len,
- void *buf);
-static int fr_send_data_header(sdla_t *card, int dlci, unsigned char attr, int len,
- void *buf,unsigned char hdr_len);
-static unsigned int fr_send_hdr(sdla_t *card, int dlci, unsigned int offset);
-
-static int check_dlci_config (sdla_t *card, fr_channel_t *chan);
-static void initialize_rx_tx_buffers (sdla_t *card);
-
-
-/* Firmware asynchronous event handlers */
-static int fr_event(sdla_t *card, int event, fr_mbox_t *mbox);
-static int fr_modem_failure(sdla_t *card, fr_mbox_t *mbox);
-static int fr_dlci_change(sdla_t *card, fr_mbox_t *mbox);
-
-/* Miscellaneous functions */
-static int update_chan_state(struct net_device *dev);
-static void set_chan_state(struct net_device *dev, int state);
-static struct net_device *find_channel(sdla_t *card, unsigned dlci);
-static int is_tx_ready(sdla_t *card, fr_channel_t *chan);
-static unsigned int dec_to_uint(unsigned char *str, int len);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-
-static int intr_test( sdla_t* card );
-static void init_chan_statistics( fr_channel_t* chan );
-static void init_global_statistics( sdla_t* card );
-static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan );
-static int setup_for_delayed_transmit(struct net_device* dev,
- struct sk_buff *skb);
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev);
-static int check_tx_status(sdla_t *card, struct net_device *dev);
-
-/* Frame Relay Socket API */
-static void trigger_fr_bh (fr_channel_t *);
-static void fr_bh(struct net_device *dev);
-static int fr_bh_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-static void trigger_fr_poll(struct net_device *dev);
-static void fr_poll(struct net_device *dev);
-//static void add_gateway(struct net_device *dev);
-
-static void trigger_unconfig_fr(struct net_device *dev);
-static void unconfig_fr (sdla_t *);
-
-static void trigger_config_fr (sdla_t *);
-static void config_fr (sdla_t *);
-
-
-/* Inverse ARP and Dynamic routing functions */
-int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device *dev);
-int is_arp(void *buf);
-int send_inarp_request(sdla_t *card, struct net_device *dev);
-
-static void trigger_fr_arp(struct net_device *dev);
-static void fr_arp (unsigned long data);
-
-
-/* Udp management functions */
-static int process_udp_mgmt_pkt(sdla_t *card);
-static int udp_pkt_type( struct sk_buff *skb, sdla_t *card );
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, int dlci);
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket,
- unsigned long network_number, unsigned char incoming);
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname,
- unsigned char enable_IPX, unsigned long network_number);
-
-/* Lock Functions: SMP supported */
-void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags);
-void s508_s514_lock(sdla_t *card, unsigned long *smp_flags);
-
-unsigned short calc_checksum (char *, int);
-static int setup_fr_header(struct sk_buff *skb,
- struct net_device* dev, char op_mode);
-
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Frame relay protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpf_init(sdla_t *card, wandev_conf_t *conf)
-{
-
- int err;
- fr508_flags_t* flags;
-
- union
- {
- char str[80];
- fr_conf_t cfg;
- } u;
-
- fr_buf_info_t* buf_info;
- int i;
-
-
- printk(KERN_INFO "\n");
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_FR) {
-
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
-
- }
-
- /* Initialize protocol-specific fields of adapter data space */
- switch (card->hw.fwid) {
-
- case SFID_FR508:
- card->mbox = (void*)(card->hw.dpmbase +
- FR508_MBOX_OFFS);
- card->flags = (void*)(card->hw.dpmbase +
- FR508_FLAG_OFFS);
- if(card->hw.type == SDLA_S514) {
- card->mbox += FR_MB_VECTOR;
- card->flags += FR_MB_VECTOR;
- }
- card->isr = &fr_isr;
- break;
-
- default:
- return -EINVAL;
- }
-
- flags = card->flags;
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (fr_read_version(card, NULL) || fr_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: running frame relay firmware v%s\n",
- card->devname, u.str);
-
- /* Adjust configuration */
- conf->mtu += FR_HEADER_LEN;
- conf->mtu = (conf->mtu >= MIN_LGTH_FR_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) :
- FR_CHANNEL_MTU + FR_HEADER_LEN;
-
- conf->bps = min_t(unsigned int, conf->bps, 2048000);
-
- /* Initialze the configuration structure sent to the board to zero */
- memset(&u.cfg, 0, sizeof(u.cfg));
-
- memset(card->u.f.dlci_to_dev_map, 0, sizeof(card->u.f.dlci_to_dev_map));
-
- /* Configure adapter firmware */
-
- u.cfg.mtu = conf->mtu;
- u.cfg.kbps = conf->bps / 1000;
-
- u.cfg.cir_fwd = u.cfg.cir_bwd = 16;
- u.cfg.bc_fwd = u.cfg.bc_bwd = 16;
-
- u.cfg.options = 0x0000;
- printk(KERN_INFO "%s: Global CIR enabled by Default\n", card->devname);
-
- switch (conf->u.fr.signalling) {
-
- case WANOPT_FR_ANSI:
- u.cfg.options = 0x0000;
- break;
-
- case WANOPT_FR_Q933:
- u.cfg.options |= 0x0200;
- break;
-
- case WANOPT_FR_LMI:
- u.cfg.options |= 0x0400;
- break;
-
- case WANOPT_NO:
- u.cfg.options |= 0x0800;
- break;
- default:
- printk(KERN_INFO "%s: Illegal Signalling option\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- card->wandev.signalling = conf->u.fr.signalling;
-
- if (conf->station == WANOPT_CPE) {
-
-
- if (conf->u.fr.signalling == WANOPT_NO){
- printk(KERN_INFO
- "%s: ERROR - For NO signalling, station must be set to Node!",
- card->devname);
- return -EINVAL;
- }
-
- u.cfg.station = 0;
- u.cfg.options |= 0x8000; /* auto config DLCI */
- card->u.f.dlci_num = 0;
-
- } else {
-
- u.cfg.station = 1; /* switch emulation mode */
-
- /* For switch emulation we have to create a list of dlci(s)
- * that will be sent to be global SET_DLCI_CONFIGURATION
- * command in fr_configure() routine.
- */
-
- card->u.f.dlci_num = min_t(unsigned int, max_t(unsigned int, conf->u.fr.dlci_num, 1), 100);
-
- for ( i = 0; i < card->u.f.dlci_num; i++) {
-
- card->u.f.node_dlci[i] = (unsigned short)
- conf->u.fr.dlci[i] ? conf->u.fr.dlci[i] : 16;
-
- }
- }
-
- if (conf->clocking == WANOPT_INTERNAL)
- u.cfg.port |= 0x0001;
-
- if (conf->interface == WANOPT_RS232)
- u.cfg.port |= 0x0002;
-
- if (conf->u.fr.t391)
- u.cfg.t391 = min_t(unsigned int, conf->u.fr.t391, 30);
- else
- u.cfg.t391 = 5;
-
- if (conf->u.fr.t392)
- u.cfg.t392 = min_t(unsigned int, conf->u.fr.t392, 30);
- else
- u.cfg.t392 = 15;
-
- if (conf->u.fr.n391)
- u.cfg.n391 = min_t(unsigned int, conf->u.fr.n391, 255);
- else
- u.cfg.n391 = 2;
-
- if (conf->u.fr.n392)
- u.cfg.n392 = min_t(unsigned int, conf->u.fr.n392, 10);
- else
- u.cfg.n392 = 3;
-
- if (conf->u.fr.n393)
- u.cfg.n393 = min_t(unsigned int, conf->u.fr.n393, 10);
- else
- u.cfg.n393 = 4;
-
- if (fr_configure(card, &u.cfg))
- return -EIO;
-
- if (card->hw.type == SDLA_S514) {
-
- buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR +
- FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) +
- card->hw.dpmbase);
- }else{
- buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) -
- FR_MB_VECTOR + card->hw.dpmbase);
- }
-
- card->u.f.rx_base = buf_info->buf_base;
- card->u.f.rx_top = buf_info->buf_top;
-
- card->u.f.tx_interrupts_pending = 0;
-
- card->wandev.mtu = conf->mtu;
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->poll = NULL;
- card->exec = &wpf_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.state = WAN_DISCONNECTED;
- card->wandev.ttl = conf->ttl;
- card->wandev.udp_port = conf->udp_port;
- card->disable_comm = &disable_comm;
- card->u.f.arp_dev = NULL;
-
- /* Intialize global statistics for a card */
- init_global_statistics( card );
-
- card->TracingEnabled = 0;
-
- /* Interrupt Test */
- Intr_test_counter = 0;
- card->intr_mode = INTR_TEST_MODE;
- err = intr_test( card );
-
- printk(KERN_INFO "%s: End of Interrupt Test rc=0x%x count=%i\n",
- card->devname,err,Intr_test_counter);
-
- if (err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_ERR "%s: Interrupt Test Failed, Counter: %i\n",
- card->devname, Intr_test_counter);
- printk(KERN_ERR "Please choose another interrupt\n");
- err = -EIO;
- return err;
- }
-
- printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n",
- card->devname, Intr_test_counter);
-
-
- /* Apr 28 2000. Nenad Corbic
- * Enable commnunications here, not in if_open or new_if, since
- * interfaces come down when the link is disconnected.
- */
-
- /* If you enable comms and then set ints, you get a Tx int as you
- * perform the SET_INT_TRIGGERS command. So, we only set int
- * triggers and then adjust the interrupt mask (to disable Tx ints)
- * before enabling comms.
- */
- if (fr_set_intr_mode(card, (FR_INTR_RXRDY | FR_INTR_TXRDY |
- FR_INTR_DLC | FR_INTR_TIMER | FR_INTR_TX_MULT_DLCIs) ,
- card->wandev.mtu, 0)) {
- return -EIO;
- }
-
- flags->imask &= ~(FR_INTR_TXRDY | FR_INTR_TIMER);
-
- if (fr_comm_enable(card)) {
- return -EIO;
- }
- wanpipe_set_state(card, WAN_CONNECTED);
- spin_lock_init(&card->u.f.if_send_lock);
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update(struct wan_device* wandev)
-{
- volatile sdla_t* card;
- unsigned long timeout;
- fr508_flags_t* flags;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- card = wandev->private;
- flags = card->flags;
-
-
- card->u.f.update_comms_stats = 1;
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
- flags->imask |= FR_INTR_TIMER;
- timeout = jiffies;
- for(;;) {
- if(card->u.f.update_comms_stats == 0)
- break;
- if (time_after(jiffies, timeout + 1 * HZ)){
- card->u.f.update_comms_stats = 0;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- fr_channel_t* chan;
- int dlci = 0;
- int err = 0;
-
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-
- printk(KERN_INFO "%s: Invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chan = kmalloc(sizeof(fr_channel_t), GFP_KERNEL);
-
- if (chan == NULL)
- return -ENOMEM;
-
- memset(chan, 0, sizeof(fr_channel_t));
- strcpy(chan->name, conf->name);
- chan->card = card;
-
- /* verify media address */
- if (isdigit(conf->addr[0])) {
-
- dlci = dec_to_uint(conf->addr, 0);
-
- if (dlci && (dlci <= HIGHEST_VALID_DLCI)) {
-
- chan->dlci = dlci;
-
- } else {
-
- printk(KERN_ERR
- "%s: Invalid DLCI %u on interface %s!\n",
- wandev->name, dlci, chan->name);
- err = -EINVAL;
- }
-
- } else {
- printk(KERN_ERR
- "%s: Invalid media address on interface %s!\n",
- wandev->name, chan->name);
- err = -EINVAL;
- }
-
- if ((chan->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){
- printk(KERN_INFO
- "%s: Enabling, true interface type encoding.\n",
- card->devname);
- }
-
-
-
- /* Setup wanpipe as a router (WANPIPE) even if it is
- * a bridged DLCI, or as an API
- */
- if (strcmp(conf->usedby, "WANPIPE") == 0 ||
- strcmp(conf->usedby, "BRIDGE") == 0 ||
- strcmp(conf->usedby, "BRIDGE_N") == 0){
-
- if(strcmp(conf->usedby, "WANPIPE") == 0){
- chan->common.usedby = WANPIPE;
-
- printk(KERN_INFO "%s: Running in WANPIPE mode.\n",
- card->devname);
-
- }else if(strcmp(conf->usedby, "BRIDGE") == 0){
-
- chan->common.usedby = BRIDGE;
-
- printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n",
- card->devname);
- }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){
-
- chan->common.usedby = BRIDGE_NODE;
-
- printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n",
- card->devname);
- }
-
- if (!err){
- /* Dynamic interface configuration option.
- * On disconnect, if the options is selected,
- * the interface will be brought down */
- if (conf->if_down == WANOPT_YES){
- set_bit(DYN_OPT_ON,&chan->interface_down);
- printk(KERN_INFO
- "%s: Dynamic interface configuration enabled.\n",
- card->devname);
- }
- }
-
- } else if(strcmp(conf->usedby, "API") == 0){
-
- chan->common.usedby = API;
- printk(KERN_INFO "%s: Running in API mode.\n",
- wandev->name);
- }
-
- if (err) {
-
- kfree(chan);
- return err;
- }
-
- /* place cir,be,bc and other channel specific information into the
- * chan structure
- */
- if (conf->cir) {
-
- chan->cir = max_t(unsigned int, 1,
- min_t(unsigned int, conf->cir, 512));
- chan->cir_status = CIR_ENABLED;
-
-
- /* If CIR is enabled, force BC to equal CIR
- * this solves number of potential problems if CIR is
- * set and BC is not
- */
- chan->bc = chan->cir;
-
- if (conf->be){
- chan->be = max_t(unsigned int,
- 0, min_t(unsigned int, conf->be, 511));
- }else{
- conf->be = 0;
- }
-
- printk (KERN_INFO "%s: CIR enabled for DLCI %i \n",
- wandev->name,chan->dlci);
- printk (KERN_INFO "%s: CIR = %i ; BC = %i ; BE = %i\n",
- wandev->name,chan->cir,chan->bc,chan->be);
-
-
- }else{
- chan->cir_status = CIR_DISABLED;
- printk (KERN_INFO "%s: CIR disabled for DLCI %i\n",
- wandev->name,chan->dlci);
- }
-
- chan->mc = conf->mc;
-
- if (conf->inarp == WANOPT_YES){
- printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname);
- chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE;
- chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10;
- }else{
- printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname);
- chan->inarp = INARP_NONE;
- chan->inarp_interval = 10;
- }
-
-
- chan->dlci_configured = DLCI_NOT_CONFIGURED;
-
-
- /*FIXME: IPX disabled in this WANPIPE version */
- if (conf->enable_IPX == WANOPT_YES){
- printk(KERN_INFO "%s: ERROR - This version of WANPIPE doesn't support IPX\n",
- card->devname);
- kfree(chan);
- return -EINVAL;
- }else{
- chan->enable_IPX = WANOPT_NO;
- }
-
- if (conf->network_number){
- chan->network_number = conf->network_number;
- }else{
- chan->network_number = 0xDEADBEEF;
- }
-
- chan->route_flag = NO_ROUTE;
-
- init_chan_statistics(chan);
-
- chan->transmit_length = 0;
-
- /* prepare network device data space for registration */
- strcpy(dev->name,chan->name);
-
- dev->init = &if_init;
- dev->priv = chan;
-
- /* Initialize FR Polling Task Queue
- * We need a poll routine for each network
- * interface.
- */
- INIT_WORK(&chan->fr_poll_work, (void *)fr_poll, dev);
-
- init_timer(&chan->fr_arp_timer);
- chan->fr_arp_timer.data=(unsigned long)dev;
- chan->fr_arp_timer.function = fr_arp;
-
- wandev->new_if_cnt++;
-
- /* Tells us that if this interface is a
- * gateway or not */
- if ((chan->gateway = conf->gateway) == WANOPT_YES){
- printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
- card->devname,dev->name);
- }
-
- /* M. Grant Patch Apr 28 2000
- * Disallow duplicate dlci configurations. */
- if (card->u.f.dlci_to_dev_map[chan->dlci] != NULL) {
- kfree(chan);
- return -EBUSY;
- }
-
- /* Configure this dlci at a later date, when
- * the interface comes up. i.e. when if_open()
- * executes */
- set_bit(0,&chan->config_dlci);
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- unsigned long smp_flags=0;
-
- /* This interface is dead, make sure the
- * ARP timer is stopped */
- del_timer(&chan->fr_arp_timer);
-
- /* If we are a NODE, we must unconfigure this DLCI
- * Trigger an unconfigure command that will
- * be executed in timer interrupt. We must wait
- * for the command to complete. */
- trigger_unconfig_fr(dev);
-
- lock_adapter_irq(&wandev->lock, &smp_flags);
- wandev->new_if_cnt--;
- unlock_adapter_irq(&wandev->lock, &smp_flags);
-
- return 0;
-}
-
-
-/*=====================================================================
- * disable_comm
- *
- * Description:
- * Disable communications.
- * This code runs in shutdown (sdlamain.c)
- * under critical flag. Therefore it is not
- * necessary to set a critical flag here
- *
- * Usage:
- * Commnunications are disabled only on a card
- * shutdown.
- */
-
-static void disable_comm (sdla_t *card)
-{
- printk(KERN_INFO "%s: Disabling Communications!\n",
- card->devname);
- fr_comm_disable(card);
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-static int wpf_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err, len;
- fr_cmd_t cmd;
-
- if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))
- return -EFAULT;
-
- /* execute command */
- do
- {
- memcpy(&mbox->cmd, &cmd, sizeof(cmd));
-
- if (cmd.length){
- if( copy_from_user((void*)&mbox->data, u_data, cmd.length))
- return -EFAULT;
- }
-
- if (sdla_exec(mbox))
- err = mbox->cmd.result;
-
- else return -EIO;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- /* return result */
- if (copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t)))
- return -EFAULT;
-
- len = mbox->cmd.length;
-
- if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len))
- return -EFAULT;
- return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct wan_device* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = NULL;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- if (chan->common.usedby == WANPIPE || chan->common.usedby == API){
-
- /* Initialize media-specific parameters */
- if (chan->true_if_encoding){
- dev->type = ARPHRD_DLCI; /* This breaks tcpdump */
- }else{
- dev->type = ARPHRD_PPP; /* ARP h/w type */
- }
-
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- /* Enable Multicast addressing */
- if (chan->mc == WANOPT_YES){
- dev->flags |= IFF_MULTICAST;
- }
-
- dev->mtu = wandev->mtu - FR_HEADER_LEN;
- /* For an API, the maximum number of bytes that the stack will pass
- to the driver is (dev->mtu + dev->hard_header_len). So, adjust the
- mtu so that a frame of maximum size can be transmitted by the API.
- */
- if(chan->common.usedby == API) {
- dev->mtu += (sizeof(api_tx_hdr_t) - FR_HEADER_LEN);
- }
-
- dev->hard_header_len = FR_HEADER_LEN;/* media header length */
- dev->addr_len = 2; /* hardware address length */
- *(unsigned short*)dev->dev_addr = htons(chan->dlci);
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 100;
-
- }else{
-
- /* Setup the interface for Bridging */
- int hw_addr=0;
- ether_setup(dev);
-
- /* Use a random number to generate the MAC address */
- memcpy(dev->dev_addr, "\xFE\xFC\x00\x00\x00\x00", 6);
- get_random_bytes(&hw_addr, sizeof(hw_addr));
- *(int *)(dev->dev_addr + 2) += hw_addr;
- }
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
- SET_MODULE_OWNER(dev);
-
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o if this is the first open, then enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- int err = 0;
- struct timeval tv;
-
- if (netif_running(dev))
- return -EBUSY;
-
- /* Initialize the task queue */
- chan->tq_working=0;
-
- INIT_WORK(&chan->common.wanpipe_work, (void *)fr_bh, dev);
-
- /* Allocate and initialize BH circular buffer */
- chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC);
- memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF));
- atomic_set(&chan->bh_buff_used, 0);
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
- do_gettimeofday( &tv );
- chan->router_start_time = tv.tv_sec;
-
- if (test_bit(0,&chan->config_dlci)){
- trigger_config_fr (card);
- }else if (chan->inarp == INARP_REQUEST){
- trigger_fr_arp(dev);
- }
-
- return err;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last open, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->inarp == INARP_CONFIGURED) {
- chan->inarp = INARP_REQUEST;
- }
-
- netif_stop_queue(dev);
- wanpipe_close(card);
-
- return 0;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
- struct net_device *dev = skb->dev;
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- chan->drvstats_if_send.if_send_tbusy++;
- ++chan->ifstats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n",
- card->devname, dev->name);
- chan->drvstats_if_send.if_send_tbusy_timeout++;
- netif_wake_queue (dev);
-
-}
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o set critical flag when accessing board.
- * o check link state. If link is not up, then drop the packet.
- * o check channel status. If it's down then initiate a call.
- * o pass a packet to corresponding WAN device.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- *
- * 2. Using netif_start_queue() and netif_stop_queue()
- * will inhibit further transmit requests from the protocol stack
- * and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- int err;
- unsigned char *sendpacket;
- fr508_flags_t* adptr_flags = card->flags;
- int udp_type;
- long delay_tx_queued = 0;
- unsigned long smp_flags=0;
- unsigned char attr = 0;
-
- chan->drvstats_if_send.if_send_entry++;
-
- netif_stop_queue(dev);
-
- if (skb == NULL) {
- /* if we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: interface %s got kicked!\n",
- card->devname, dev->name);
- chan->drvstats_if_send.if_send_skb_null ++;
-
- netif_wake_queue(dev);
- return 0;
- }
-
- /* If a peripheral task is running just drop packets */
- if (test_bit(PERI_CRIT, &card->wandev.critical)){
-
- printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n",
- card->devname);
-
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
-
- /* We must set the 'tbusy' flag if we already have a packet queued for
- transmission in the transmit interrupt handler. However, we must
- ensure that the transmit interrupt does not reset the 'tbusy' flag
- just before we set it, as this will result in a "transmit timeout".
- */
- set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
- if(chan->transmit_length) {
- netif_stop_queue(dev);
- chan->tick_counter = jiffies;
- clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
- return 1;
- }
- clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
-
- /* Move the if_header() code to here. By inserting frame
- * relay header in if_header() we would break the
- * tcpdump and other packet sniffers */
- chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby);
- if (chan->fr_header_len < 0 ){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
-
- sendpacket = skb->data;
-
- udp_type = udp_pkt_type(skb, card);
-
- if(udp_type != UDP_INVALID_TYPE) {
- if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, skb,
- chan->dlci)) {
- adptr_flags->imask |= FR_INTR_TIMER;
- if (udp_type == UDP_FPIPE_TYPE){
- chan->drvstats_if_send.
- if_send_PIPE_request ++;
- }
- }
- netif_start_queue(dev);
- return 0;
- }
-
- //FIXME: can we do better than sendpacket[2]?
- if ((chan->common.usedby == WANPIPE) && (sendpacket[2] == 0x45)) {
-
- /* check to see if the source IP address is a broadcast or */
- /* multicast IP address */
- if(chk_bcast_mcast_addr(card, dev, skb)){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
- }
-
-
- /* Lock the S514/S508 card: SMP Supported */
- s508_s514_lock(card,&smp_flags);
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
- chan->drvstats_if_send.if_send_critical_non_ISR ++;
- chan->ifstats.tx_dropped ++;
- printk(KERN_INFO "%s Critical in IF_SEND: if_send() already running!\n",
- card->devname);
- goto if_send_start_and_exit;
- }
-
- /* API packet check: minimum packet size must be greater than
- * 16 byte API header */
- if((chan->common.usedby == API) && (skb->len <= sizeof(api_tx_hdr_t))) {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
-
- goto if_send_start_and_exit;
-
- }else{
- /* During API transmission, get rid of the API header */
- if (chan->common.usedby == API) {
- api_tx_hdr_t* api_tx_hdr;
- api_tx_hdr = (api_tx_hdr_t*)&skb->data[0x00];
- attr = api_tx_hdr->attr;
- skb_pull(skb,sizeof(api_tx_hdr_t));
- }
- }
-
- if (card->wandev.state != WAN_CONNECTED) {
- chan->drvstats_if_send.if_send_wan_disconnected ++;
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- } else if (chan->common.state != WAN_CONNECTED) {
- chan->drvstats_if_send.if_send_dlci_disconnected ++;
-
- /* Update the DLCI state in timer interrupt */
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE_STATE;
- adptr_flags->imask |= FR_INTR_TIMER;
-
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- } else if (!is_tx_ready(card, chan)) {
- /* No tx buffers available, store for delayed transmit */
- if (!setup_for_delayed_transmit(dev, skb)){
- set_bit(1,&delay_tx_queued);
- }
- chan->drvstats_if_send.if_send_no_bfrs++;
-
- } else if (!skb->protocol) {
- /* No protocols drop packet */
- chan->drvstats_if_send.if_send_protocol_error ++;
- ++card->wandev.stats.tx_errors;
-
- } else if (test_bit(ARP_CRIT,&card->wandev.critical)){
- /* We are trying to send an ARP Packet, block IP data until
- * ARP is sent */
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- } else {
- //FIXME: IPX is not implemented in this version of Frame Relay ?
- if((chan->common.usedby == WANPIPE) &&
- sendpacket[1] == 0x00 &&
- sendpacket[2] == 0x80 &&
- sendpacket[6] == 0x81 &&
- sendpacket[7] == 0x37) {
-
- if( chan->enable_IPX ) {
- switch_net_numbers(sendpacket,
- chan->network_number, 0);
- } else {
- //FIXME: Take this out when IPX is fixed
- printk(KERN_INFO
- "%s: WARNING: Unsupported IPX data in send, packet dropped\n",
- card->devname);
- }
-
- }else{
- err = fr_send_data_header(card, chan->dlci, attr, skb->len, skb->data, chan->fr_header_len);
- if (err) {
- switch(err) {
- case FRRES_CIR_OVERFLOW:
- case FRRES_BUFFER_OVERFLOW:
- if (!setup_for_delayed_transmit(dev, skb)){
- set_bit(1,&delay_tx_queued);
- }
- chan->drvstats_if_send.
- if_send_adptr_bfrs_full ++;
- break;
-
- case FRRES_TOO_LONG:
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Error: Frame too long, transmission failed %i\n",
- card->devname, (unsigned int)skb->len);
- }
- /* Drop down to default */
- default:
- chan->drvstats_if_send.
- if_send_dlci_disconnected ++;
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
- } else {
- chan->drvstats_if_send.
- if_send_bfr_passed_to_adptr++;
- ++chan->ifstats.tx_packets;
- ++card->wandev.stats.tx_packets;
-
- chan->ifstats.tx_bytes += skb->len;
- card->wandev.stats.tx_bytes += skb->len;
- dev->trans_start = jiffies;
- }
- }
- }
-
-if_send_start_and_exit:
-
- netif_start_queue(dev);
-
- /* If we queued the packet for transmission, we must not
- * deallocate it. The packet is unlinked from the IP stack
- * not copied. Therefore, we must keep the original packet */
- if (!test_bit(1,&delay_tx_queued)) {
- dev_kfree_skb_any(skb);
- }else{
- adptr_flags->imask |= FR_INTR_TXRDY;
- card->u.f.tx_interrupts_pending ++;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
-
- s508_s514_unlock(card,&smp_flags);
-
- return 0;
-}
-
-
-
-/*============================================================================
- * Setup so that a frame can be transmitted on the occurrence of a transmit
- * interrupt.
- */
-static int setup_for_delayed_transmit(struct net_device* dev,
- struct sk_buff *skb)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- fr_dlci_interface_t* dlci_interface;
- int len = skb->len;
-
- /* Check that the dlci is properly configured,
- * before using tx interrupt */
- if (!chan->dlci_int_interface){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: ERROR on DLCI %i: Not configured properly !\n",
- card->devname, chan->dlci);
- printk(KERN_INFO "%s: Please contact Sangoma Technologies\n",
- card->devname);
- }
- return 1;
- }
-
- dlci_interface = chan->dlci_int_interface;
-
- if(chan->transmit_length) {
- printk(KERN_INFO "%s: Big mess in setup_for_del...\n",
- card->devname);
- return 1;
- }
-
- if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) {
- //FIXME: increment some statistic */
- return 1;
- }
-
- chan->transmit_length = len;
- chan->delay_skb = skb;
-
- dlci_interface->gen_interrupt |= FR_INTR_TXRDY;
- dlci_interface->packet_length = len;
-
- /* Turn on TX interrupt at the end of if_send */
- return 0;
-}
-
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- * Return 0 if not broadcast/multicast address, otherwise return 1.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb)
-{
- u32 src_ip_addr;
- u32 broadcast_ip_addr = 0;
- struct in_device *in_dev;
- fr_channel_t* chan = dev->priv;
-
- /* read the IP source address from the outgoing packet */
- src_ip_addr = *(u32 *)(skb->data + 14);
-
- /* read the IP broadcast address for the device */
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa= in_dev->ifa_list;
- if(ifa != NULL)
- broadcast_ip_addr = ifa->ifa_broadcast;
- else
- return 0;
- }
-
- /* check if the IP Source Address is a Broadcast address */
- if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
- printk(KERN_INFO
- "%s: Broadcast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- /* check if the IP Source Address is a Multicast address */
- if((chan->mc == WANOPT_NO) && (ntohl(src_ip_addr) >= 0xE0000001) &&
- (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
- printk(KERN_INFO
- "%s: Multicast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- return 0;
-}
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return nothing.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
-
-
- fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = //sizeof(fr_encap_hdr_t)+
- sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* fill in UDP reply */
- fr_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- fr_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = fr_udp_pkt->udp_pkt.udp_src_port;
- fr_udp_pkt->udp_pkt.udp_src_port =
- fr_udp_pkt->udp_pkt.udp_dst_port;
- fr_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)
- (fr_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)
- (fr_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
- /* calculate UDP checksum */
- fr_udp_pkt->udp_pkt.udp_checksum = 0;
-
- fr_udp_pkt->udp_pkt.udp_checksum =
- calc_checksum(&data[UDP_OFFSET/*+sizeof(fr_encap_hdr_t)*/],
- udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = udp_length + sizeof(ip_pkt_t);
- temp = (ip_length<<8)|(ip_length>>8);
- fr_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = fr_udp_pkt->ip_pkt.ip_src_address;
- fr_udp_pkt->ip_pkt.ip_src_address =
- fr_udp_pkt->ip_pkt.ip_dst_address;
- fr_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-
- /* fill in IP checksum */
- fr_udp_pkt->ip_pkt.hdr_checksum = 0;
- fr_udp_pkt->ip_pkt.hdr_checksum =
- calc_checksum(&data[/*sizeof(fr_encap_hdr_t)*/0],
- sizeof(ip_pkt_t));
-
- return len;
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-/*
- If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- if incoming is 1 - if the net number is 0 make it ours
-
-*/
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[14] << 24) +
- (sendpacket[15] << 16) + (sendpacket[16] << 8) +
- sendpacket[17]);
-
- if (!incoming) {
- /* If the destination network number is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[14] = sendpacket[15] = sendpacket[16] =
- sendpacket[17] = 0x00;
- }
- } else {
- /* If the incoming network is 0, make it ours */
- if( pnetwork_number == 0) {
- sendpacket[14] = (unsigned char)(network_number >> 24);
- sendpacket[15] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[16] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[17] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[26] << 24) +
- (sendpacket[27] << 16) + (sendpacket[28] << 8) +
- sendpacket[29]);
-
- if( !incoming ) {
- /* If the source network is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[26] = sendpacket[27] = sendpacket[28] =
- sendpacket[29] = 0x00;
- }
- } else {
- /* If the source network is 0, make it ours */
- if( pnetwork_number == 0 ) {
- sendpacket[26] = (unsigned char)(network_number >> 24);
- sendpacket[27] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[28] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[29] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats *if_stats(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
-
- if(chan == NULL)
- return NULL;
-
- return &chan->ifstats;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * fr_isr: S508 frame relay interrupt service routine.
- *
- * Description:
- * Frame relay main interrupt service route. This
- * function check the interrupt type and takes
- * the appropriate action.
- */
-static void fr_isr (sdla_t* card)
-{
- fr508_flags_t* flags = card->flags;
- char *ptr = &flags->iflag;
- int i,err;
- fr_mbox_t* mbox = card->mbox;
-
- /* This flag prevents nesting of interrupts. See sdla_isr() routine
- * in sdlamain.c. */
- card->in_isr = 1;
-
- ++card->statistics.isr_entry;
-
-
- /* All peripheral (configuraiton, re-configuration) events
- * take presidence over the ISR. Thus, retrigger */
- if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- ++card->statistics.isr_already_critical;
- goto fr_isr_exit;
- }
-
- if(card->hw.type != SDLA_S514) {
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n",
- card->devname);
- ++card->statistics.isr_already_critical;
- goto fr_isr_exit;
- }
- }
-
- switch (flags->iflag) {
-
- case FR_INTR_RXRDY: /* receive interrupt */
- ++card->statistics.isr_rx;
- rx_intr(card);
- break;
-
-
- case FR_INTR_TXRDY: /* transmit interrupt */
- ++ card->statistics.isr_tx;
- tx_intr(card);
- break;
-
- case FR_INTR_READY:
- Intr_test_counter++;
- ++card->statistics.isr_intr_test;
- break;
-
- case FR_INTR_DLC: /* Event interrupt occurred */
- mbox->cmd.command = FR_READ_STATUS;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- fr_event(card, err, mbox);
- break;
-
- case FR_INTR_TIMER: /* Timer interrupt */
- timer_intr(card);
- break;
-
- default:
- ++card->statistics.isr_spurious;
- spur_intr(card);
- printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n",
- card->devname, flags->iflag);
-
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
-
- break;
- }
-
-fr_isr_exit:
-
- card->in_isr = 0;
- flags->iflag = 0;
- return;
-}
-
-
-
-/*===========================================================
- * rx_intr Receive interrupt handler.
- *
- * Description
- * Upon receiveing an interrupt:
- * 1. Check that the firmware is in sync with
- * the driver.
- * 2. Find an appropriate network interface
- * based on the received dlci number.
- * 3. Check that the netowrk interface exists
- * and that it's setup properly.
- * 4. Copy the data into an skb buffer.
- * 5. Check the packet type and take
- * appropriate acton: UPD, API, ARP or Data.
- */
-
-static void rx_intr (sdla_t* card)
-{
- fr_rx_buf_ctl_t* frbuf = card->rxmb;
- fr508_flags_t* flags = card->flags;
- fr_channel_t* chan;
- char *ptr = &flags->iflag;
- struct sk_buff* skb;
- struct net_device* dev;
- void* buf;
- unsigned dlci, len, offs, len_incl_hdr;
- int i, udp_type;
-
-
- /* Check that firmware buffers are in sync */
- if (frbuf->flag != 0x01) {
-
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)frbuf, frbuf->flag);
-
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
-
- ++card->statistics.rx_intr_corrupt_rx_bfr;
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it means that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- fr_set_intr_mode(card, 0, 0, 0);
- return;
- }
-
- len = frbuf->length;
- dlci = frbuf->dlci;
- offs = frbuf->offset;
-
- /* Find the network interface for this packet */
- dev = find_channel(card, dlci);
-
-
- /* Check that the network interface is active and
- * properly setup */
- if (dev == NULL) {
- if( net_ratelimit()) {
- printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",
- card->devname, dlci);
- }
- ++card->statistics.rx_intr_on_orphaned_DLCI;
- ++card->wandev.stats.rx_dropped;
- goto rx_done;
- }
-
- if ((chan = dev->priv) == NULL){
- if( net_ratelimit()) {
- printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",
- card->devname, dlci);
- }
- ++card->statistics.rx_intr_on_orphaned_DLCI;
- ++card->wandev.stats.rx_dropped;
- goto rx_done;
- }
-
- skb = dev_alloc_skb(len);
-
- if (!netif_running(dev) || (skb == NULL)){
-
- ++chan->ifstats.rx_dropped;
-
- if(skb == NULL) {
- if (net_ratelimit()) {
- printk(KERN_INFO
- "%s: no socket buffers available!\n",
- card->devname);
- }
- chan->drvstats_rx_intr.rx_intr_no_socket ++;
- }
-
- if (!netif_running(dev)){
- chan->drvstats_rx_intr.
- rx_intr_dev_not_started ++;
- if (skb){
- dev_kfree_skb_any(skb);
- }
- }
- goto rx_done;
- }
-
- /* Copy data from the board into the socket buffer */
- if ((offs + len) > card->u.f.rx_top + 1) {
- unsigned tmp = card->u.f.rx_top - offs + 1;
-
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, offs, buf, tmp);
- offs = card->u.f.rx_base;
- len -= tmp;
- }
-
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, offs, buf, len);
-
-
- /* We got the packet from the bard.
- * Check the packet type and take appropriate action */
-
- udp_type = udp_pkt_type( skb, card );
-
- if(udp_type != UDP_INVALID_TYPE) {
-
- /* UDP Debug packet received, store the
- * packet and handle it in timer interrupt */
-
- skb_pull(skb, 1);
- if (wanrouter_type_trans(skb, dev)){
- if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){
-
- flags->imask |= FR_INTR_TIMER;
-
- if (udp_type == UDP_FPIPE_TYPE){
- ++chan->drvstats_rx_intr.rx_intr_PIPE_request;
- }
- }
- }
-
- }else if (chan->common.usedby == API) {
-
- /* We are in API mode.
- * Add an API header to the RAW packet
- * and queue it into a circular buffer.
- * Then kick the fr_bh() bottom half handler */
-
- api_rx_hdr_t* api_rx_hdr;
- chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack ++;
- chan->ifstats.rx_packets ++;
- card->wandev.stats.rx_packets ++;
-
- chan->ifstats.rx_bytes += skb->len;
- card->wandev.stats.rx_bytes += skb->len;
-
- skb_push(skb, sizeof(api_rx_hdr_t));
- api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];
- api_rx_hdr->attr = frbuf->attr;
- api_rx_hdr->time_stamp = frbuf->tmstamp;
-
- skb->protocol = htons(ETH_P_IP);
- skb->mac.raw = skb->data;
- skb->dev = dev;
- skb->pkt_type = WAN_PACKET_DATA;
-
- bh_enqueue(dev, skb);
-
- trigger_fr_bh(chan);
-
- }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){
-
- //FIXME: Frame Relay IPX is not supported, Yet !
- //if (chan->enable_IPX) {
- // fr_send(card, dlci, 0, skb->len,skb->data);
- //}
- dev_kfree_skb_any(skb);
-
- } else if (is_arp(skb->data)) {
-
- /* ARP support enabled Mar 16 2000
- * Process incoming ARP reply/request, setup
- * dynamic routes. */
-
- if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) {
- if (net_ratelimit()){
- printk (KERN_INFO
- "%s: Error processing ARP Packet.\n",
- card->devname);
- }
- }
- dev_kfree_skb_any(skb);
-
- } else if (skb->data[0] != 0x03) {
-
- if (net_ratelimit()) {
- printk(KERN_INFO "%s: Non IETF packet discarded.\n",
- card->devname);
- }
- dev_kfree_skb_any(skb);
-
- } else {
-
- len_incl_hdr = skb->len;
- /* Decapsulate packet and pass it up the
- protocol stack */
- skb->dev = dev;
-
- if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){
-
- /* Make sure it's an Ethernet frame, otherwise drop it */
- if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) {
- skb_pull(skb, 8);
- skb->protocol=eth_type_trans(skb,dev);
- }else{
- ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
- ++chan->ifstats.rx_errors;
- ++card->wandev.stats.rx_errors;
- goto rx_done;
- }
- }else{
-
- /* remove hardware header */
- buf = skb_pull(skb, 1);
-
- if (!wanrouter_type_trans(skb, dev)) {
-
- /* can't decapsulate packet */
- dev_kfree_skb_any(skb);
-
- ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
- ++chan->ifstats.rx_errors;
- ++card->wandev.stats.rx_errors;
- goto rx_done;
- }
- skb->mac.raw = skb->data;
- }
-
-
- /* Send a packet up the IP stack */
- skb->dev->last_rx = jiffies;
- netif_rx(skb);
- ++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack;
- ++chan->ifstats.rx_packets;
- ++card->wandev.stats.rx_packets;
-
- chan->ifstats.rx_bytes += len_incl_hdr;
- card->wandev.stats.rx_bytes += len_incl_hdr;
- }
-
-rx_done:
-
- /* Release buffer element and calculate a pointer to the next one */
- frbuf->flag = 0;
- card->rxmb = ++frbuf;
- if ((void*)frbuf > card->u.f.rxmb_last)
- card->rxmb = card->u.f.rxmb_base;
-
-}
-
-/*==================================================================
- * tx_intr: Transmit interrupt handler.
- *
- * Rationale:
- * If the board is busy transmitting, if_send() will
- * buffers a single packet and turn on
- * the tx interrupt. Tx interrupt will be called
- * by the board, once the firmware can send more
- * data. Thus, no polling is required.
- *
- * Description:
- * Tx interrupt is called for each
- * configured dlci channel. Thus:
- * 1. Obtain the netowrk interface based on the
- * dlci number.
- * 2. Check that network interface is up and
- * properly setup.
- * 3. Check for a buffered packet.
- * 4. Transmit the packet.
- * 5. If we are in WANPIPE mode, mark the
- * NET_BH handler.
- * 6. If we are in API mode, kick
- * the AF_WANPIPE socket for more data.
- *
- */
-static void tx_intr(sdla_t *card)
-{
- fr508_flags_t* flags = card->flags;
- fr_tx_buf_ctl_t* bctl;
- struct net_device* dev;
- fr_channel_t* chan;
-
- if(card->hw.type == SDLA_S514){
- bctl = (void*)(flags->tse_offs + card->hw.dpmbase);
- }else{
- bctl = (void*)(flags->tse_offs - FR_MB_VECTOR +
- card->hw.dpmbase);
- }
-
- /* Find the structure and make it unbusy */
- dev = find_channel(card, flags->dlci);
- if (dev == NULL){
- printk(KERN_INFO "NO DEV IN TX Interrupt\n");
- goto end_of_tx_intr;
- }
-
- if ((chan = dev->priv) == NULL){
- printk(KERN_INFO "NO CHAN IN TX Interrupt\n");
- goto end_of_tx_intr;
- }
-
- if(!chan->transmit_length || !chan->delay_skb) {
- printk(KERN_INFO "%s: tx int error - transmit length zero\n",
- card->wandev.name);
- goto end_of_tx_intr;
- }
-
- /* If the 'if_send()' procedure is currently checking the 'tbusy'
- status, then we cannot transmit. Instead, we configure the microcode
- so as to re-issue this transmit interrupt at a later stage.
- */
- if (test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) {
-
- fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface;
- bctl->flag = 0xA0;
- dlci_interface->gen_interrupt |= FR_INTR_TXRDY;
- return;
-
- }else{
- bctl->dlci = flags->dlci;
- bctl->length = chan->transmit_length+chan->fr_header_len;
- sdla_poke(&card->hw,
- fr_send_hdr(card,bctl->dlci,bctl->offset),
- chan->delay_skb->data,
- chan->delay_skb->len);
- bctl->flag = 0xC0;
-
- ++chan->ifstats.tx_packets;
- ++card->wandev.stats.tx_packets;
- chan->ifstats.tx_bytes += chan->transmit_length;
- card->wandev.stats.tx_bytes += chan->transmit_length;
-
- /* We must free an sk buffer, which we used
- * for delayed transmission; Otherwise, the sock
- * will run out of memory */
- dev_kfree_skb_any(chan->delay_skb);
-
- chan->delay_skb = NULL;
- chan->transmit_length = 0;
-
- dev->trans_start = jiffies;
-
- if (netif_queue_stopped(dev)){
- /* If using API, than wakeup socket BH handler */
- if (chan->common.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- }
-
-end_of_tx_intr:
-
- /* if any other interfaces have transmit interrupts pending,
- * do not disable the global transmit interrupt */
- if(!(-- card->u.f.tx_interrupts_pending))
- flags->imask &= ~FR_INTR_TXRDY;
-
-
-}
-
-
-/*============================================================================
- * timer_intr: Timer interrupt handler.
- *
- * Rationale:
- * All commans must be executed within the timer
- * interrupt since no two commands should execute
- * at the same time.
- *
- * Description:
- * The timer interrupt is used to:
- * 1. Processing udp calls from 'fpipemon'.
- * 2. Processing update calls from /proc file system
- * 3. Reading board-level statistics for
- * updating the proc file system.
- * 4. Sending inverse ARP request packets.
- * 5. Configure a dlci/channel.
- * 6. Unconfigure a dlci/channel. (Node only)
- */
-
-static void timer_intr(sdla_t *card)
-{
- fr508_flags_t* flags = card->flags;
-
- /* UDP Debuging: fpipemon call */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UDP) {
- if(card->u.f.udp_type == UDP_FPIPE_TYPE) {
- if(process_udp_mgmt_pkt(card)) {
- card->u.f.timer_int_enabled &=
- ~TMR_INT_ENABLED_UDP;
- }
- }
- }
-
- /* /proc update call : triggered from update() */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
- fr_get_err_stats(card);
- fr_get_stats(card);
- card->u.f.update_comms_stats = 0;
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
- }
-
- /* Update the channel state call. This is call is
- * triggered by if_send() function */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE_STATE){
- struct net_device *dev;
- if (card->wandev.state == WAN_CONNECTED){
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)){
- fr_channel_t *chan = dev->priv;
- if (chan->common.state != WAN_CONNECTED){
- update_chan_state(dev);
- }
- }
- }
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE_STATE;
- }
-
- /* configure a dlci/channel */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_CONFIG){
- config_fr(card);
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
- }
-
- /* unconfigure a dlci/channel */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG){
- unconfig_fr(card);
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG;
- }
-
-
- /* Transmit ARP packets */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_ARP){
- int i=0;
- struct net_device *dev;
-
- if (card->u.f.arp_dev == NULL)
- card->u.f.arp_dev = card->wandev.dev;
-
- dev = card->u.f.arp_dev;
-
- for (;;){
-
- fr_channel_t *chan = dev->priv;
-
- /* If the interface is brought down cancel sending In-ARPs */
- if (!(dev->flags&IFF_UP)){
- clear_bit(0,&chan->inarp_ready);
- }
-
- if (test_bit(0,&chan->inarp_ready)){
-
- if (check_tx_status(card,dev)){
- set_bit(ARP_CRIT,&card->wandev.critical);
- break;
- }
-
- if (!send_inarp_request(card,dev)){
- trigger_fr_arp(dev);
- chan->inarp_tick = jiffies;
- }
-
- clear_bit(0,&chan->inarp_ready);
- dev = move_dev_to_next(card,dev);
- break;
- }
- dev = move_dev_to_next(card,dev);
-
- if (++i == card->wandev.new_if_cnt){
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_ARP;
- break;
- }
- }
- card->u.f.arp_dev = dev;
- }
-
- if(!card->u.f.timer_int_enabled)
- flags->imask &= ~FR_INTR_TIMER;
-}
-
-
-/*============================================================================
- * spur_intr: Spurious interrupt handler.
- *
- * Description:
- * We don't know this interrupt.
- * Print a warning.
- */
-
-static void spur_intr (sdla_t* card)
-{
- if (net_ratelimit()){
- printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
- }
-}
-
-
-//FIXME: Fix the IPX in next version
-/*===========================================================================
- * Return 0 for non-IPXWAN packet
- * 1 for IPXWAN packet or IPX is not enabled!
- * FIXME: Use a IPX structure here not offsets
- */
-static int handle_IPXWAN(unsigned char *sendpacket,
- char *devname, unsigned char enable_IPX,
- unsigned long network_number)
-{
- int i;
-
- if( sendpacket[1] == 0x00 && sendpacket[2] == 0x80 &&
- sendpacket[6] == 0x81 && sendpacket[7] == 0x37) {
-
- /* It's an IPX packet */
- if (!enable_IPX){
- /* Return 1 so we don't pass it up the stack. */
- //FIXME: Take this out when IPX is fixed
- if (net_ratelimit()){
- printk (KERN_INFO
- "%s: WARNING: Unsupported IPX packet received and dropped\n",
- devname);
- }
- return 1;
- }
- } else {
- /* It's not IPX so return and pass it up the stack. */
- return 0;
- }
-
- if( sendpacket[24] == 0x90 && sendpacket[25] == 0x04){
- /* It's IPXWAN */
-
- if( sendpacket[10] == 0x02 && sendpacket[42] == 0x00){
-
- /* It's a timer request packet */
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",
- devname);
-
- /* Go through the routing options and answer no to every
- * option except Unnumbered RIP/SAP
- */
- for(i = 49; sendpacket[i] == 0x00; i += 5){
- /* 0x02 is the option for Unnumbered RIP/SAP */
- if( sendpacket[i + 4] != 0x02){
- sendpacket[i + 1] = 0;
- }
- }
-
- /* Skip over the extended Node ID option */
- if( sendpacket[i] == 0x04 ){
- i += 8;
- }
-
- /* We also want to turn off all header compression opt.
- */
- for(; sendpacket[i] == 0x80 ;){
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- /* Set the packet type to timer response */
- sendpacket[42] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",
- devname);
-
- } else if( sendpacket[42] == 0x02 ){
-
- /* This is an information request packet */
- printk(KERN_INFO
- "%s: Received IPXWAN Information Request packet\n",
- devname);
-
- /* Set the packet type to information response */
- sendpacket[42] = 0x03;
-
- /* Set the router name */
- sendpacket[59] = 'F';
- sendpacket[60] = 'P';
- sendpacket[61] = 'I';
- sendpacket[62] = 'P';
- sendpacket[63] = 'E';
- sendpacket[64] = '-';
- sendpacket[65] = CVHexToAscii(network_number >> 28);
- sendpacket[66] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[67] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[68] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[69] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[70] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[71] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[72] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 73; i < 107; i+= 1)
- {
- sendpacket[i] = 0;
- }
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",
- devname);
- } else {
-
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- /* Set the WNodeID to our network address */
- sendpacket[43] = (unsigned char)(network_number >> 24);
- sendpacket[44] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[45] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[46] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- }
-
- /* If we get here, it's an IPX-data packet so it'll get passed up the
- * stack.
- * switch the network numbers
- */
- switch_net_numbers(sendpacket, network_number ,1);
- return 0;
-}
-/*============================================================================
- * process_route
- *
- * Rationale:
- * If the interface goes down, or we receive an ARP request,
- * we have to change the network interface ip addresses.
- * This cannot be done within the interrupt.
- *
- * Description:
- *
- * This routine is called as a polling routine to dynamically
- * add/delete routes negotiated by inverse ARP. It is in this
- * "task" because we don't want routes to be added while in
- * interrupt context.
- *
- * Usage:
- * This function is called by fr_poll() polling funtion.
- */
-
-static void process_route(struct net_device *dev)
-{
- fr_channel_t *chan = dev->priv;
- sdla_t *card = chan->card;
-
- struct ifreq if_info;
- struct sockaddr_in *if_data;
- mm_segment_t fs = get_fs();
- u32 ip_tmp;
- int err;
-
-
- switch(chan->route_flag){
-
- case ADD_ROUTE:
-
- /* Set remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- set_fs(get_ds()); /* get user space block */
-
- if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data->sin_addr.s_addr = chan->ip_remote;
- if_data->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
- set_fs(fs); /* restore old block */
-
- if (err) {
- printk(KERN_INFO
- "%s: Route Add failed. Error: %d\n",
- card->devname,err);
- printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
- chan->name, NIPQUAD(chan->ip_remote));
-
- }else {
- printk(KERN_INFO "%s: Route Added Successfully: %u.%u.%u.%u\n",
- card->devname,NIPQUAD(chan->ip_remote));
- chan->route_flag = ROUTE_ADDED;
- }
- break;
-
- case REMOVE_ROUTE:
-
- /* Set remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- ip_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- set_fs(get_ds()); /* get user space block */
-
- if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data->sin_addr.s_addr = 0;
- if_data->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
- set_fs(fs);
-
- if (err) {
- printk(KERN_INFO
- "%s: Deleting of route failed. Error: %d\n",
- card->devname,err);
- printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
- dev->name,NIPQUAD(chan->ip_remote) );
-
- } else {
- printk(KERN_INFO "%s: Route Removed Sucessfuly: %u.%u.%u.%u\n",
- card->devname,NIPQUAD(ip_tmp));
- chan->route_flag = NO_ROUTE;
- }
- break;
-
- } /* Case Statement */
-
-}
-
-
-
-/****** Frame Relay Firmware-Specific Functions *****************************/
-
-/*============================================================================
- * Read firmware code version.
- * o fill string str with firmware version info.
- */
-static int fr_read_version (sdla_t* card, char* str)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.command = FR_READ_CODE_VERSION;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err && str) {
- int len = mbox->cmd.length;
- memcpy(str, mbox->data, len);
- str[len] = '\0';
- }
- return err;
-}
-
-/*============================================================================
- * Set global configuration.
- */
-static int fr_configure (sdla_t* card, fr_conf_t *conf)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int dlci_num = card->u.f.dlci_num;
- int err, i;
-
- do
- {
- memcpy(mbox->data, conf, sizeof(fr_conf_t));
-
- if (dlci_num) for (i = 0; i < dlci_num; ++i)
- ((fr_conf_t*)mbox->data)->dlci[i] =
- card->u.f.node_dlci[i];
-
- mbox->cmd.command = FR_SET_CONFIG;
- mbox->cmd.length =
- sizeof(fr_conf_t) + dlci_num * sizeof(short);
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- /*NC Oct 12 2000 */
- if (err != CMD_OK){
- printk(KERN_ERR "%s: Frame Relay Configuration Failed: rc=0x%x\n",
- card->devname,err);
- }
-
- return err;
-}
-
-/*============================================================================
- * Set DLCI configuration.
- */
-static int fr_dlci_configure (sdla_t* card, fr_dlc_conf_t *conf, unsigned dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memcpy(mbox->data, conf, sizeof(fr_dlc_conf_t));
- mbox->cmd.dlci = (unsigned short) dlci;
- mbox->cmd.command = FR_SET_CONFIG;
- mbox->cmd.length = sizeof(fr_dlc_conf_t);
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry--);
-
- return err;
-}
-/*============================================================================
- * Set interrupt mode.
- */
-static int fr_set_intr_mode (sdla_t* card, unsigned mode, unsigned mtu,
- unsigned short timeout)
-{
- fr_mbox_t* mbox = card->mbox;
- fr508_intr_ctl_t* ictl = (void*)mbox->data;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(ictl, 0, sizeof(fr508_intr_ctl_t));
- ictl->mode = mode;
- ictl->tx_len = mtu;
- ictl->irq = card->hw.irq;
-
- /* indicate timeout on timer */
- if (mode & 0x20) ictl->timeout = timeout;
-
- mbox->cmd.length = sizeof(fr508_intr_ctl_t);
- mbox->cmd.command = FR_SET_INTR_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * Enable communications.
- */
-static int fr_comm_enable (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.command = FR_COMM_ENABLE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * fr_comm_disable
- *
- * Warning: This functin is called by the shutdown() procedure. It is void
- * since dev->priv are has already been deallocated and no
- * error checking is possible using fr_event() function.
- */
-static void fr_comm_disable (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do {
- mbox->cmd.command = FR_SET_MODEM_STATUS;
- mbox->cmd.length = 1;
- mbox->data[0] = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry--);
-
- retry = MAX_CMD_RETRY;
-
- do
- {
- mbox->cmd.command = FR_COMM_DISABLE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry--);
-
- return;
-}
-
-
-
-/*============================================================================
- * Get communications error statistics.
- */
-static int fr_get_err_stats (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
-
- do
- {
- mbox->cmd.command = FR_READ_ERROR_STATS;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_comm_stat_t* stats = (void*)mbox->data;
- card->wandev.stats.rx_over_errors = stats->rx_overruns;
- card->wandev.stats.rx_crc_errors = stats->rx_bad_crc;
- card->wandev.stats.rx_missed_errors = stats->rx_aborts;
- card->wandev.stats.rx_length_errors = stats->rx_too_long;
- card->wandev.stats.tx_aborted_errors = stats->tx_aborts;
-
- }
-
- return err;
-}
-
-/*============================================================================
- * Get statistics.
- */
-static int fr_get_stats (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
-
- do
- {
- mbox->cmd.command = FR_READ_STATISTICS;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_link_stat_t* stats = (void*)mbox->data;
- card->wandev.stats.rx_frame_errors = stats->rx_bad_format;
- card->wandev.stats.rx_dropped =
- stats->rx_dropped + stats->rx_dropped2;
- }
-
- return err;
-}
-
-/*============================================================================
- * Add DLCI(s) (Access Node only!).
- * This routine will perform the ADD_DLCIs command for the specified DLCI.
- */
-static int fr_add_dlci (sdla_t* card, int dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- unsigned short* dlci_list = (void*)mbox->data;
-
- mbox->cmd.length = sizeof(short);
- dlci_list[0] = dlci;
- mbox->cmd.command = FR_ADD_DLCI;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * Activate DLCI(s) (Access Node only!).
- * This routine will perform the ACTIVATE_DLCIs command with a DLCI number.
- */
-static int fr_activate_dlci (sdla_t* card, int dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- unsigned short* dlci_list = (void*)mbox->data;
-
- mbox->cmd.length = sizeof(short);
- dlci_list[0] = dlci;
- mbox->cmd.command = FR_ACTIVATE_DLCI;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * Delete DLCI(s) (Access Node only!).
- * This routine will perform the DELETE_DLCIs command with a DLCI number.
- */
-static int fr_delete_dlci (sdla_t* card, int dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- unsigned short* dlci_list = (void*)mbox->data;
-
- mbox->cmd.length = sizeof(short);
- dlci_list[0] = dlci;
- mbox->cmd.command = FR_DELETE_DLCI;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-
-
-/*============================================================================
- * Issue in-channel signalling frame.
- */
-static int fr_issue_isf (sdla_t* card, int isf)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->data[0] = isf;
- mbox->cmd.length = 1;
- mbox->cmd.command = FR_ISSUE_IS_FRAME;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-
-static unsigned int fr_send_hdr (sdla_t*card, int dlci, unsigned int offset)
-{
- struct net_device *dev = find_channel(card,dlci);
- fr_channel_t *chan;
-
- if (!dev || !(chan=dev->priv))
- return offset;
-
- if (chan->fr_header_len){
- sdla_poke(&card->hw, offset, chan->fr_header, chan->fr_header_len);
- }
-
- return offset+chan->fr_header_len;
-}
-
-/*============================================================================
- * Send a frame on a selected DLCI.
- */
-static int fr_send_data_header (sdla_t* card, int dlci, unsigned char attr, int len,
- void *buf, unsigned char hdr_len)
-{
- fr_mbox_t* mbox = card->mbox + 0x800;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.dlci = dlci;
- mbox->cmd.attr = attr;
- mbox->cmd.length = len+hdr_len;
- mbox->cmd.command = FR_WRITE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_tx_buf_ctl_t* frbuf;
-
- if(card->hw.type == SDLA_S514)
- frbuf = (void*)(*(unsigned long*)mbox->data +
- card->hw.dpmbase);
- else
- frbuf = (void*)(*(unsigned long*)mbox->data -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- sdla_poke(&card->hw, fr_send_hdr(card,dlci,frbuf->offset), buf, len);
- frbuf->flag = 0x01;
- }
-
- return err;
-}
-
-static int fr_send (sdla_t* card, int dlci, unsigned char attr, int len,
- void *buf)
-{
- fr_mbox_t* mbox = card->mbox + 0x800;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.dlci = dlci;
- mbox->cmd.attr = attr;
- mbox->cmd.length = len;
- mbox->cmd.command = FR_WRITE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_tx_buf_ctl_t* frbuf;
-
- if(card->hw.type == SDLA_S514)
- frbuf = (void*)(*(unsigned long*)mbox->data +
- card->hw.dpmbase);
- else
- frbuf = (void*)(*(unsigned long*)mbox->data -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- sdla_poke(&card->hw, frbuf->offset, buf, len);
- frbuf->flag = 0x01;
- }
-
- return err;
-}
-
-
-/****** Firmware Asynchronous Event Handlers ********************************/
-
-/*============================================================================
- * Main asyncronous event/error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
-{
- fr508_flags_t* flags = card->flags;
- char *ptr = &flags->iflag;
- int i;
-
- switch (event) {
-
- case FRRES_MODEM_FAILURE:
- return fr_modem_failure(card, mbox);
-
- case FRRES_CHANNEL_DOWN: {
- struct net_device *dev;
-
- /* Remove all routes from associated DLCI's */
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
- fr_channel_t *chan = dev->priv;
- if (chan->route_flag == ROUTE_ADDED) {
- chan->route_flag = REMOVE_ROUTE;
- }
-
- if (chan->inarp == INARP_CONFIGURED) {
- chan->inarp = INARP_REQUEST;
- }
-
- /* If the link becomes disconnected then,
- * all channels will be disconnected
- * as well.
- */
- set_chan_state(dev,WAN_DISCONNECTED);
- }
-
- wanpipe_set_state(card, WAN_DISCONNECTED);
- return 1;
- }
-
- case FRRES_CHANNEL_UP: {
- struct net_device *dev;
-
- /* FIXME: Only startup devices that are on the list */
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
-
- set_chan_state(dev,WAN_CONNECTED);
- }
-
- wanpipe_set_state(card, WAN_CONNECTED);
- return 1;
- }
-
- case FRRES_DLCI_CHANGE:
- return fr_dlci_change(card, mbox);
-
- case FRRES_DLCI_MISMATCH:
- printk(KERN_INFO "%s: DLCI list mismatch!\n",
- card->devname);
- return 1;
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, mbox->cmd.command);
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x18 + i));
- printk(KERN_INFO "\n");
-
- break;
-
- case FRRES_DLCI_INACTIVE:
- break;
-
- case FRRES_CIR_OVERFLOW:
- break;
-
- case FRRES_BUFFER_OVERFLOW:
- break;
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n"
- , card->devname, mbox->cmd.command, event);
- }
-
- return 0;
-}
-
-/*============================================================================
- * Handle modem error.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_modem_failure (sdla_t *card, fr_mbox_t* mbox)
-{
- printk(KERN_INFO "%s: physical link down! (modem error 0x%02X)\n",
- card->devname, mbox->data[0]);
-
- switch (mbox->cmd.command){
- case FR_WRITE:
-
- case FR_READ:
- return 0;
- }
-
- return 1;
-}
-
-/*============================================================================
- * Handle DLCI status change.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
-{
- dlci_status_t* status = (void*)mbox->data;
- int cnt = mbox->cmd.length / sizeof(dlci_status_t);
- fr_channel_t *chan;
- struct net_device* dev2;
-
-
- for (; cnt; --cnt, ++status) {
-
- unsigned short dlci= status->dlci;
- struct net_device* dev = find_channel(card, dlci);
-
- if (dev == NULL){
- printk(KERN_INFO
- "%s: CPE contains unconfigured DLCI= %d\n",
- card->devname, dlci);
-
- printk(KERN_INFO
- "%s: unconfigured DLCI %d reported by network\n"
- , card->devname, dlci);
-
- }else{
- if (status->state == FR_LINK_INOPER) {
- printk(KERN_INFO
- "%s: DLCI %u is inactive!\n",
- card->devname, dlci);
-
- if (dev && netif_running(dev))
- set_chan_state(dev, WAN_DISCONNECTED);
- }
-
- if (status->state & FR_DLCI_DELETED) {
-
- printk(KERN_INFO
- "%s: DLCI %u has been deleted!\n",
- card->devname, dlci);
-
- if (dev && netif_running(dev)){
-
- fr_channel_t *chan = dev->priv;
-
- if (chan->route_flag == ROUTE_ADDED) {
- chan->route_flag = REMOVE_ROUTE;
- /* The state change will trigger
- * the fr polling routine */
- }
-
- if (chan->inarp == INARP_CONFIGURED) {
- chan->inarp = INARP_REQUEST;
- }
-
- set_chan_state(dev, WAN_DISCONNECTED);
- }
-
- } else if (status->state & FR_DLCI_ACTIVE) {
-
- chan = dev->priv;
-
- /* This flag is used for configuring specific
- DLCI(s) when they become active.
- */
- chan->dlci_configured = DLCI_CONFIG_PENDING;
-
- set_chan_state(dev, WAN_CONNECTED);
-
- }
- }
- }
-
- for (dev2 = card->wandev.dev; dev2;
- dev2 = *((struct net_device **)dev2->priv)){
-
- chan = dev2->priv;
-
- if (chan->dlci_configured == DLCI_CONFIG_PENDING) {
- if (fr_init_dlci(card, chan)){
- return 1;
- }
- }
-
- }
- return 1;
-}
-
-
-static int fr_init_dlci (sdla_t *card, fr_channel_t *chan)
-{
- fr_dlc_conf_t cfg;
-
- memset(&cfg, 0, sizeof(cfg));
-
- if ( chan->cir_status == CIR_DISABLED) {
-
- cfg.cir_fwd = cfg.cir_bwd = 16;
- cfg.bc_fwd = cfg.bc_bwd = 16;
- cfg.conf_flags = 0x0001;
-
- }else if (chan->cir_status == CIR_ENABLED) {
-
- cfg.cir_fwd = cfg.cir_bwd = chan->cir;
- cfg.bc_fwd = cfg.bc_bwd = chan->bc;
- cfg.be_fwd = cfg.be_bwd = chan->be;
- cfg.conf_flags = 0x0000;
- }
-
- if (fr_dlci_configure( card, &cfg , chan->dlci)){
- printk(KERN_INFO
- "%s: DLCI Configure failed for %d\n",
- card->devname, chan->dlci);
- return 1;
- }
-
- chan->dlci_configured = DLCI_CONFIGURED;
-
- /* Read the interface byte mapping into the channel
- * structure.
- */
- read_DLCI_IB_mapping( card, chan );
-
- return 0;
-}
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Update channel state.
- */
-static int update_chan_state(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.command = FR_LIST_ACTIVE_DLCI;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
-
- unsigned short* list = (void*)mbox->data;
- int cnt = mbox->cmd.length / sizeof(short);
-
- err=1;
-
- for (; cnt; --cnt, ++list) {
-
- if (*list == chan->dlci) {
- set_chan_state(dev, WAN_CONNECTED);
-
-
- /* May 23 2000. NC
- * When a dlci is added or restarted,
- * the dlci_int_interface pointer must
- * be reinitialized. */
- if (!chan->dlci_int_interface){
- err=fr_init_dlci (card,chan);
- }
- break;
- }
- }
- }
-
- return err;
-}
-
-/*============================================================================
- * Set channel state.
- */
-static void set_chan_state(struct net_device* dev, int state)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->common.state != state) {
-
- switch (state) {
-
- case WAN_CONNECTED:
- printk(KERN_INFO
- "%s: Interface %s: DLCI %d connected\n",
- card->devname, dev->name, chan->dlci);
-
- /* If the interface was previoulsy down,
- * bring it up, since the channel is active */
-
- trigger_fr_poll (dev);
- trigger_fr_arp (dev);
- break;
-
- case WAN_CONNECTING:
- printk(KERN_INFO
- "%s: Interface %s: DLCI %d connecting\n",
- card->devname, dev->name, chan->dlci);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO
- "%s: Interface %s: DLCI %d disconnected!\n",
- card->devname, dev->name, chan->dlci);
-
- /* If the interface is up, bring it down,
- * since the channel is now disconnected */
- trigger_fr_poll (dev);
- break;
- }
-
- chan->common.state = state;
- }
-
- chan->state_tick = jiffies;
-}
-
-/*============================================================================
- * Find network device by its channel number.
- *
- * We need this critical flag because we change
- * the dlci_to_dev_map outside the interrupt.
- *
- * NOTE: del_if() functions updates this array, it uses
- * the spin locks to avoid corruption.
- */
-static struct net_device* find_channel(sdla_t* card, unsigned dlci)
-{
- if(dlci > HIGHEST_VALID_DLCI)
- return NULL;
-
- return(card->u.f.dlci_to_dev_map[dlci]);
-}
-
-/*============================================================================
- * Check to see if a frame can be sent. If no transmit buffers available,
- * enable transmit interrupts.
- *
- * Return: 1 - Tx buffer(s) available
- * 0 - no buffers available
- */
-static int is_tx_ready (sdla_t* card, fr_channel_t* chan)
-{
- unsigned char sb;
-
- if(card->hw.type == SDLA_S514)
- return 1;
-
- sb = inb(card->hw.port);
- if (sb & 0x02)
- return 1;
-
- return 0;
-}
-
-/*============================================================================
- * Convert decimal string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are converted.
- */
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
- unsigned val;
-
- if (!len)
- len = strlen(str);
-
- for (val = 0; len && isdigit(*str); ++str, --len)
- val = (val * 10) + (*str - (unsigned)'0');
-
- return val;
-}
-
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, int dlci)
-{
- int udp_pkt_stored = 0;
-
- struct net_device *dev = find_channel(card, dlci);
- fr_channel_t *chan;
-
- if (!dev || !(chan=dev->priv))
- return 1;
-
- if(!card->u.f.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){
- card->u.f.udp_pkt_lgth = skb->len + chan->fr_header_len;
- card->u.f.udp_type = udp_type;
- card->u.f.udp_pkt_src = udp_pkt_src;
- card->u.f.udp_dlci = dlci;
- memcpy(card->u.f.udp_pkt_data, skb->data, skb->len);
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
-
- }else{
- printk(KERN_INFO "ERROR: UDP packet not stored for DLCI %d\n",
- dlci);
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-/*==============================================================================
- * Process UDP call of type FPIPE8ND
- */
-static int process_udp_mgmt_pkt(sdla_t* card)
-{
-
- int c_retry = MAX_CMD_RETRY;
- unsigned char *buf;
- unsigned char frames;
- unsigned int len;
- unsigned short buffer_length;
- struct sk_buff *new_skb;
- fr_mbox_t* mbox = card->mbox;
- int err;
- struct timeval tv;
- int udp_mgmt_req_valid = 1;
- struct net_device* dev;
- fr_channel_t* chan;
- fr_udp_pkt_t *fr_udp_pkt;
- unsigned short num_trc_els;
- fr_trc_el_t* ptr_trc_el;
- fr_trc_el_t trc_el;
- fpipemon_trc_t* fpipemon_trc;
-
- char udp_pkt_src = card->u.f.udp_pkt_src;
- int dlci = card->u.f.udp_dlci;
-
- /* Find network interface for this packet */
- dev = find_channel(card, dlci);
- if (!dev){
- card->u.f.udp_pkt_lgth = 0;
- return 1;
- }
- if ((chan = dev->priv) == NULL){
- card->u.f.udp_pkt_lgth = 0;
- return 1;
- }
-
- /* If the UDP packet is from the network, we are going to have to
- transmit a response. Before doing so, we must check to see that
- we are not currently transmitting a frame (in 'if_send()') and
- that we are not already in a 'delayed transmit' state.
- */
- if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
- if (check_tx_status(card,dev)){
- card->u.f.udp_pkt_lgth = 0;
- return 1;
- }
- }
-
- fr_udp_pkt = (fr_udp_pkt_t *)card->u.f.udp_pkt_data;
-
- if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- switch(fr_udp_pkt->cblock.command) {
-
- case FR_READ_MODEM_STATUS:
- case FR_READ_STATUS:
- case FPIPE_ROUTER_UP_TIME:
- case FR_READ_ERROR_STATS:
- case FPIPE_DRIVER_STAT_GEN:
- case FR_READ_STATISTICS:
- case FR_READ_ADD_DLC_STATS:
- case FR_READ_CONFIG:
- case FR_READ_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
- /* set length to 0 */
- fr_udp_pkt->cblock.length = 0;
- /* set return code */
- fr_udp_pkt->cblock.result = 0xCD;
-
- chan->drvstats_gen.UDP_PIPE_mgmt_direction_err ++;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,fr_udp_pkt->cblock.command);
- }
-
- } else {
-
- switch(fr_udp_pkt->cblock.command) {
-
- case FPIPE_ENABLE_TRACING:
- if(!card->TracingEnabled) {
- do {
- mbox->cmd.command = FR_SET_TRACE_CONFIG;
- mbox->cmd.length = 1;
- mbox->cmd.dlci = 0x00;
- mbox->data[0] = fr_udp_pkt->data[0] |
- RESET_TRC;
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
- } while (err && c_retry-- && fr_event(card, err,
- mbox));
-
- if(err) {
- card->TracingEnabled = 0;
- /* set the return code */
- fr_udp_pkt->cblock.result =
- mbox->cmd.result;
- mbox->cmd.length = 0;
- break;
- }
-
- sdla_peek(&card->hw, NO_TRC_ELEMENTS_OFF,
- &num_trc_els, 2);
- sdla_peek(&card->hw, BASE_TRC_ELEMENTS_OFF,
- &card->u.f.trc_el_base, 4);
- card->u.f.curr_trc_el = card->u.f.trc_el_base;
- card->u.f.trc_el_last = card->u.f.curr_trc_el +
- ((num_trc_els - 1) *
- sizeof(fr_trc_el_t));
-
- /* Calculate the maximum trace data area in */
- /* the UDP packet */
- card->u.f.trc_bfr_space=(MAX_LGTH_UDP_MGNT_PKT -
- //sizeof(fr_encap_hdr_t) -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t));
-
- /* set return code */
- fr_udp_pkt->cblock.result = 0;
-
- } else {
- /* set return code to line trace already
- enabled */
- fr_udp_pkt->cblock.result = 1;
- }
-
- mbox->cmd.length = 0;
- card->TracingEnabled = 1;
- break;
-
-
- case FPIPE_DISABLE_TRACING:
- if(card->TracingEnabled) {
-
- do {
- mbox->cmd.command = FR_SET_TRACE_CONFIG;
- mbox->cmd.length = 1;
- mbox->cmd.dlci = 0x00;
- mbox->data[0] = ~ACTIVATE_TRC;
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
- } while (err && c_retry-- && fr_event(card, err, mbox));
- }
-
- /* set return code */
- fr_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 0;
- card->TracingEnabled = 0;
- break;
-
- case FPIPE_GET_TRACE_INFO:
-
- /* Line trace cannot be performed on the 502 */
- if(!card->TracingEnabled) {
- /* set return code */
- fr_udp_pkt->cblock.result = 1;
- mbox->cmd.length = 0;
- break;
- }
-
- ptr_trc_el = (void *)card->u.f.curr_trc_el;
-
- buffer_length = 0;
- fr_udp_pkt->data[0x00] = 0x00;
-
- for(frames = 0; frames < MAX_FRMS_TRACED; frames ++) {
-
- sdla_peek(&card->hw, (unsigned long)ptr_trc_el,
- (void *)&trc_el.flag,
- sizeof(fr_trc_el_t));
- if(trc_el.flag == 0x00) {
- break;
- }
- if((card->u.f.trc_bfr_space - buffer_length)
- < sizeof(fpipemon_trc_hdr_t)) {
- fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
- break;
- }
-
- fpipemon_trc =
- (fpipemon_trc_t *)&fr_udp_pkt->data[buffer_length];
- fpipemon_trc->fpipemon_trc_hdr.status =
- trc_el.attr;
- fpipemon_trc->fpipemon_trc_hdr.tmstamp =
- trc_el.tmstamp;
- fpipemon_trc->fpipemon_trc_hdr.length =
- trc_el.length;
-
- if(!trc_el.offset || !trc_el.length) {
-
- fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00;
-
- }else if((trc_el.length + sizeof(fpipemon_trc_hdr_t) + 1) >
- (card->u.f.trc_bfr_space - buffer_length)){
-
- fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00;
- fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
-
- }else {
- fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x01;
- sdla_peek(&card->hw, trc_el.offset,
- fpipemon_trc->data,
- trc_el.length);
- }
-
- trc_el.flag = 0x00;
- sdla_poke(&card->hw, (unsigned long)ptr_trc_el,
- &trc_el.flag, 1);
-
- ptr_trc_el ++;
- if((void *)ptr_trc_el > card->u.f.trc_el_last)
- ptr_trc_el = (void*)card->u.f.trc_el_base;
-
- buffer_length += sizeof(fpipemon_trc_hdr_t);
- if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
- buffer_length += trc_el.length;
- }
-
- if(fr_udp_pkt->data[0x00] & MORE_TRC_DATA) {
- break;
- }
- }
-
- if(frames == MAX_FRMS_TRACED) {
- fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
- }
-
- card->u.f.curr_trc_el = (void *)ptr_trc_el;
-
- /* set the total number of frames passed */
- fr_udp_pkt->data[0x00] |=
- ((frames << 1) & (MAX_FRMS_TRACED << 1));
-
- /* set the data length and return code */
- fr_udp_pkt->cblock.length = mbox->cmd.length = buffer_length;
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_FT1_READ_STATUS:
- sdla_peek(&card->hw, 0xF020,
- &fr_udp_pkt->data[0x00] , 2);
- fr_udp_pkt->cblock.length = mbox->cmd.length = 2;
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_FLUSH_DRIVER_STATS:
- init_chan_statistics(chan);
- init_global_statistics(card);
- mbox->cmd.length = 0;
- break;
-
- case FPIPE_ROUTER_UP_TIME:
- do_gettimeofday(&tv);
- chan->router_up_time = tv.tv_sec -
- chan->router_start_time;
- *(unsigned long *)&fr_udp_pkt->data =
- chan->router_up_time;
- mbox->cmd.length = fr_udp_pkt->cblock.length = 4;
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_DRIVER_STAT_IFSEND:
- memcpy(fr_udp_pkt->data,
- &chan->drvstats_if_send.if_send_entry,
- sizeof(if_send_stat_t));
- mbox->cmd.length = fr_udp_pkt->cblock.length =sizeof(if_send_stat_t);
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_DRIVER_STAT_INTR:
-
- memcpy(fr_udp_pkt->data,
- &card->statistics.isr_entry,
- sizeof(global_stats_t));
-
- memcpy(&fr_udp_pkt->data[sizeof(global_stats_t)],
- &chan->drvstats_rx_intr.rx_intr_no_socket,
- sizeof(rx_intr_stat_t));
-
- mbox->cmd.length = fr_udp_pkt->cblock.length =
- sizeof(global_stats_t) +
- sizeof(rx_intr_stat_t);
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_DRIVER_STAT_GEN:
- memcpy(fr_udp_pkt->data,
- &chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err,
- sizeof(pipe_mgmt_stat_t));
-
- memcpy(&fr_udp_pkt->data[sizeof(pipe_mgmt_stat_t)],
- &card->statistics, sizeof(global_stats_t));
-
- mbox->cmd.length = fr_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- fr_udp_pkt->cblock.result = 0;
- break;
-
-
- case FR_FT1_STATUS_CTRL:
- if(fr_udp_pkt->data[0] == 1) {
- if(rCount++ != 0 ){
- fr_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if(fr_udp_pkt->data[0] == 0) {
- if( --rCount != 0) {
- fr_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
- goto udp_mgmt_dflt;
-
-
- default:
-udp_mgmt_dflt:
- do {
- memcpy(&mbox->cmd,
- &fr_udp_pkt->cblock.command,
- sizeof(fr_cmd_t));
- if(mbox->cmd.length) {
- memcpy(&mbox->data,
- (char *)fr_udp_pkt->data,
- mbox->cmd.length);
- }
-
- err = sdla_exec(mbox) ? mbox->cmd.result :
- CMD_TIMEOUT;
- } while (err && c_retry-- && fr_event(card, err, mbox));
-
- if(!err)
- chan->drvstats_gen.
- UDP_PIPE_mgmt_adptr_cmnd_OK ++;
- else
- chan->drvstats_gen.
- UDP_PIPE_mgmt_adptr_cmnd_timeout ++;
-
- /* copy the result back to our buffer */
- memcpy(&fr_udp_pkt->cblock.command,
- &mbox->cmd, sizeof(fr_cmd_t));
-
- if(mbox->cmd.length) {
- memcpy(&fr_udp_pkt->data,
- &mbox->data, mbox->cmd.length);
- }
- }
- }
-
- /* Fill UDP TTL */
- fr_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(card->u.f.udp_pkt_data, mbox->cmd.length);
-
- if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- chan->fr_header_len=2;
- chan->fr_header[0]=Q922_UI;
- chan->fr_header[1]=NLPID_IP;
-
- err = fr_send_data_header(card, dlci, 0, len,
- card->u.f.udp_pkt_data,chan->fr_header_len);
- if (err){
- chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_passed ++;
- }else{
- chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_failed ++;
- }
-
- } else {
- /* Allocate socket buffer */
- if((new_skb = dev_alloc_skb(len)) != NULL) {
-
- /* copy data into new_skb */
- buf = skb_put(new_skb, len);
- memcpy(buf, card->u.f.udp_pkt_data, len);
-
- chan->drvstats_gen.
- UDP_PIPE_mgmt_passed_to_stack ++;
- new_skb->dev = dev;
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->mac.raw = new_skb->data;
- netif_rx(new_skb);
-
- } else {
- chan->drvstats_gen.UDP_PIPE_mgmt_no_socket ++;
- printk(KERN_INFO
- "%s: UDP mgmt cmnd, no socket buffers available!\n",
- card->devname);
- }
- }
-
- card->u.f.udp_pkt_lgth = 0;
-
- return 1;
-}
-
-/*==============================================================================
- * Send Inverse ARP Request
- */
-
-int send_inarp_request(sdla_t *card, struct net_device *dev)
-{
- int err=0;
-
- arphdr_1490_t *ArpPacket;
- arphdr_fr_t *arphdr;
- fr_channel_t *chan = dev->priv;
- struct in_device *in_dev;
-
- in_dev = dev->ip_ptr;
-
- if(in_dev != NULL ) {
-
- ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC);
- /* SNAP Header indicating ARP */
- ArpPacket->control = 0x03;
- ArpPacket->pad = 0x00;
- ArpPacket->NLPID = 0x80;
- ArpPacket->OUI[0] = 0;
- ArpPacket->OUI[1] = 0;
- ArpPacket->OUI[2] = 0;
- ArpPacket->PID = 0x0608;
-
- arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet
-
- /* InARP request */
- arphdr->ar_hrd = 0x0F00; /* Frame Relay HW type */
- arphdr->ar_pro = 0x0008; /* IP Protocol */
- arphdr->ar_hln = 2; /* HW addr length */
- arphdr->ar_pln = 4; /* IP addr length */
- arphdr->ar_op = htons(0x08); /* InARP Request */
- arphdr->ar_sha = 0; /* src HW DLCI - Doesn't matter */
- if(in_dev->ifa_list != NULL)
- arphdr->ar_sip = in_dev->ifa_list->ifa_local; /* Local Address */else
- arphdr->ar_sip = 0;
- arphdr->ar_tha = 0; /* dst HW DLCI - Doesn't matter */
- arphdr->ar_tip = 0; /* Remote Address -- what we want */
-
- err = fr_send(card, chan->dlci, 0, sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t),
- (void *)ArpPacket);
-
- if (!err){
- printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n",
- card->devname, chan->dlci);
- clear_bit(ARP_CRIT,&card->wandev.critical);
- }
-
- kfree(ArpPacket);
- }else{
- printk(KERN_INFO "%s: INARP ERROR: %s doesn't have a local IP address!\n",
- card->devname,dev->name);
- return 1;
- }
-
- return 0;
-}
-
-
-/*==============================================================================
- * Check packet for ARP Type
- */
-
-int is_arp(void *buf)
-{
- arphdr_1490_t *arphdr = (arphdr_1490_t *)buf;
-
- if (arphdr->pad == 0x00 &&
- arphdr->NLPID == 0x80 &&
- arphdr->PID == 0x0608)
- return 1;
- else return 0;
-}
-
-/*==============================================================================
- * Process ARP Packet Type
- */
-
-int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device* dev)
-{
-
-
- arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
- fr_rx_buf_ctl_t* frbuf = card->rxmb;
- struct in_device *in_dev;
- fr_channel_t *chan = dev->priv;
-
- /* Before we transmit ARP packet, we must check
- * to see that we are not currently transmitting a
- * frame (in 'if_send()') and that we are not
- * already in a 'delayed transmit' state. */
- if (check_tx_status(card,dev)){
- if (net_ratelimit()){
- printk(KERN_INFO "%s: Disabling comminication to process ARP\n",
- card->devname);
- }
- set_bit(ARP_CRIT,&card->wandev.critical);
- return 0;
- }
-
- in_dev = dev->ip_ptr;
-
- /* Check that IP addresses exist for our network address */
- if (in_dev == NULL || in_dev->ifa_list == NULL)
- return -1;
-
- switch (ntohs(arphdr->ar_op)) {
-
- case 0x08: // Inverse ARP request -- Send Reply, add route.
-
- /* Check for valid Address */
- printk(KERN_INFO "%s: Recvd PtP addr -InArp Req: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(arphdr->ar_sip));
-
-
- /* Check that the network address is the same as ours, only
- * if the netowrk mask is not 255.255.255.255. Otherwise
- * this check would not make sense */
-
- if (in_dev->ifa_list->ifa_mask != 0xFFFFFFFF &&
- (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) !=
- (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)){
- printk(KERN_INFO
- "%s: Invalid PtP address. %u.%u.%u.%u InARP ignored.\n",
- card->devname,NIPQUAD(arphdr->ar_sip));
-
- printk(KERN_INFO "%s: mask %u.%u.%u.%u\n",
- card->devname, NIPQUAD(in_dev->ifa_list->ifa_mask));
- printk(KERN_INFO "%s: local %u.%u.%u.%u\n",
- card->devname,NIPQUAD(in_dev->ifa_list->ifa_local));
- return -1;
- }
-
- if (in_dev->ifa_list->ifa_local == arphdr->ar_sip){
- printk(KERN_INFO
- "%s: Local addr = PtP addr. InARP ignored.\n",
- card->devname);
- return -1;
- }
-
- arphdr->ar_op = htons(0x09); /* InARP Reply */
-
- /* Set addresses */
- arphdr->ar_tip = arphdr->ar_sip;
- arphdr->ar_sip = in_dev->ifa_list->ifa_local;
-
- chan->ip_local = in_dev->ifa_list->ifa_local;
- chan->ip_remote = arphdr->ar_sip;
-
- fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket);
-
- if (test_bit(ARP_CRIT,&card->wandev.critical)){
- if (net_ratelimit()){
- printk(KERN_INFO "%s: ARP Processed Enabling Communication!\n",
- card->devname);
- }
- }
- clear_bit(ARP_CRIT,&card->wandev.critical);
-
- chan->ip_local = in_dev->ifa_list->ifa_local;
- chan->ip_remote = arphdr->ar_sip;
-
- /* Add Route Flag */
- /* The route will be added in the polling routine so
- that it is not interrupt context. */
-
- chan->route_flag = ADD_ROUTE;
- trigger_fr_poll (dev);
-
- break;
-
- case 0x09: // Inverse ARP reply
-
- /* Check for valid Address */
- printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n",
- card->devname, NIPQUAD(arphdr->ar_sip));
-
-
- /* Compare network addresses, only if network mask
- * is not 255.255.255.255 It would not make sense
- * to perform this test if the mask was all 1's */
-
- if (in_dev->ifa_list->ifa_mask != 0xffffffff &&
- (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) !=
- (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)) {
-
- printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n",
- card->devname);
- return -1;
- }
-
- /* Make sure that the received IP address is not
- * the same as our own local address */
- if (in_dev->ifa_list->ifa_local == arphdr->ar_sip) {
- printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n",
- card->devname);
- return -1;
- }
-
- chan->ip_local = in_dev->ifa_list->ifa_local;
- chan->ip_remote = arphdr->ar_sip;
-
- /* Add Route Flag */
- /* The route will be added in the polling routine so
- that it is not interrupt context. */
-
- chan->route_flag = ADD_ROUTE;
- chan->inarp = INARP_CONFIGURED;
- trigger_fr_poll(dev);
-
- break;
- default:
- break; // ARP's and RARP's -- Shouldn't happen.
- }
-
- return 0;
-}
-
-
-/*============================================================
- * trigger_fr_arp
- *
- * Description:
- * Add an fr_arp() task into a arp
- * timer handler for a specific dlci/interface.
- * This will kick the fr_arp() routine
- * within the specified time interval.
- *
- * Usage:
- * This timer is used to send ARP requests at
- * certain time intervals.
- * Called by an interrupt to request an action
- * at a later date.
- */
-
-static void trigger_fr_arp(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
-
- mod_timer(&chan->fr_arp_timer, jiffies + chan->inarp_interval * HZ);
- return;
-}
-
-
-
-/*==============================================================================
- * ARP Request Action
- *
- * This funciton is called by timer interrupt to send an arp request
- * to the remote end.
- */
-
-static void fr_arp (unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- fr_channel_t *chan = dev->priv;
- volatile sdla_t *card = chan->card;
- fr508_flags_t* flags = card->flags;
-
- /* Send ARP packets for all devs' until
- * ARP state changes to CONFIGURED */
-
- if (chan->inarp == INARP_REQUEST &&
- chan->common.state == WAN_CONNECTED &&
- card->wandev.state == WAN_CONNECTED){
- set_bit(0,&chan->inarp_ready);
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_ARP;
- flags->imask |= FR_INTR_TIMER;
- }
-
- return;
-}
-
-
-/*==============================================================================
- * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR_
- * TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card )
-{
- fr_mbox_t* mb = card->mbox;
- int err,i;
-
- err = fr_set_intr_mode(card, FR_INTR_READY, card->wandev.mtu, 0 );
-
- if (err == CMD_OK) {
-
- for ( i = 0; i < MAX_INTR_TEST_COUNTER; i++ ) {
- /* Run command READ_CODE_VERSION */
- mb->cmd.length = 0;
- mb->cmd.command = FR_READ_CODE_VERSION;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK)
- fr_event(card, err, mb);
- }
-
- } else {
- return err;
- }
-
- err = fr_set_intr_mode( card, 0, card->wandev.mtu, 0 );
-
- if( err != CMD_OK )
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. FPIPE8ND ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t* card )
-{
- fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)skb->data;
-
- /* Quick HACK */
-
-
- if((fr_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (fr_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) &&
- (fr_udp_pkt->udp_pkt.udp_dst_port ==
- ntohs(card->wandev.udp_port)) &&
- (fr_udp_pkt->wp_mgmt.request_reply ==
- UDPMGMT_REQUEST)) {
- if(!strncmp(fr_udp_pkt->wp_mgmt.signature,
- UDPMGMT_FPIPE_SIGNATURE, 8)){
- return UDP_FPIPE_TYPE;
- }
- }
- return UDP_INVALID_TYPE;
-}
-
-
-/*==============================================================================
- * Initializes the Statistics values in the fr_channel structure.
- */
-void init_chan_statistics( fr_channel_t* chan)
-{
- memset(&chan->drvstats_if_send.if_send_entry, 0,
- sizeof(if_send_stat_t));
- memset(&chan->drvstats_rx_intr.rx_intr_no_socket, 0,
- sizeof(rx_intr_stat_t));
- memset(&chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, 0,
- sizeof(pipe_mgmt_stat_t));
-}
-
-/*==============================================================================
- * Initializes the Statistics values in the Sdla_t structure.
- */
-void init_global_statistics( sdla_t* card )
-{
- /* Intialize global statistics for a card */
- memset(&card->statistics.isr_entry, 0, sizeof(global_stats_t));
-}
-
-static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan )
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- dlci_IB_mapping_t* result;
- int err, counter, found;
-
- do {
- mbox->cmd.command = FR_READ_DLCI_IB_MAPPING;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if( mbox->cmd.result != 0){
- printk(KERN_INFO "%s: Read DLCI IB Mapping failed\n",
- chan->name);
- }
-
- counter = mbox->cmd.length / sizeof(dlci_IB_mapping_t);
- result = (void *)mbox->data;
-
- found = 0;
- for (; counter; --counter, ++result) {
- if ( result->dlci == chan->dlci ) {
- chan->IB_addr = result->addr_value;
- if(card->hw.type == SDLA_S514){
- chan->dlci_int_interface =
- (void*)(card->hw.dpmbase +
- chan->IB_addr);
- }else{
- chan->dlci_int_interface =
- (void*)(card->hw.dpmbase +
- (chan->IB_addr & 0x00001FFF));
-
- }
- found = 1;
- break;
- }
- }
- if (!found)
- printk( KERN_INFO "%s: DLCI %d not found by IB MAPPING cmd\n",
- card->devname, chan->dlci);
-}
-
-
-
-void s508_s514_lock(sdla_t *card, unsigned long *smp_flags)
-{
- if (card->hw.type != SDLA_S514){
-
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- }else{
- spin_lock(&card->u.f.if_send_lock);
- }
- return;
-}
-
-
-void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags)
-{
- if (card->hw.type != SDLA_S514){
-
- spin_unlock_irqrestore (&card->wandev.lock, *smp_flags);
- }else{
- spin_unlock(&card->u.f.if_send_lock);
- }
- return;
-}
-
-
-
-/*----------------------------------------------------------------------
- RECEIVE INTERRUPT: BOTTOM HALF HANDLERS
- ----------------------------------------------------------------------*/
-
-
-/*========================================================
- * bh_enqueue
- *
- * Description:
- * Insert a received packet into a circular
- * rx queue. This packet will be picked up
- * by fr_bh() and sent up the stack to the
- * user.
- *
- * Usage:
- * This function is called by rx interrupt,
- * in API mode.
- *
- */
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
- /* Check for full */
- fr_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
-
- if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){
- ++card->wandev.stats.rx_dropped;
- dev_kfree_skb_any(skb);
- return 1;
- }
-
- ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
- if (chan->bh_write == (MAX_BH_BUFF-1)){
- chan->bh_write=0;
- }else{
- ++chan->bh_write;
- }
-
- atomic_inc(&chan->bh_buff_used);
-
- return 0;
-}
-
-
-/*========================================================
- * trigger_fr_bh
- *
- * Description:
- * Kick the fr_bh() handler
- *
- * Usage:
- * rx interrupt calls this function during
- * the API mode.
- */
-
-static void trigger_fr_bh (fr_channel_t *chan)
-{
- if (!test_and_set_bit(0,&chan->tq_working)){
- wanpipe_queue_work(&chan->common.wanpipe_work);
- }
-}
-
-
-/*========================================================
- * fr_bh
- *
- * Description:
- * Frame relay receive BH handler.
- * Dequeue data from the BH circular
- * buffer and pass it up the API sock.
- *
- * Rationale:
- * This fuction is used to offload the
- * rx_interrupt during API operation mode.
- * The fr_bh() function executes for each
- * dlci/interface.
- *
- * Once receive interrupt copies data from the
- * card into an skb buffer, the skb buffer
- * is appended to a circular BH buffer.
- * Then the interrupt kicks fr_bh() to finish the
- * job at a later time (not within the interrupt).
- *
- * Usage:
- * Interrupts use this to defer a task to
- * a polling routine.
- *
- */
-
-static void fr_bh(struct net_device * dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
- struct sk_buff *skb;
-
- if (atomic_read(&chan->bh_buff_used) == 0){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- while (atomic_read(&chan->bh_buff_used)){
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
- if (skb != NULL){
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- ++card->wandev.stats.rx_dropped;
- ++chan->ifstats.rx_dropped;
- dev_kfree_skb_any(skb);
- fr_bh_cleanup(dev);
- continue;
- }
-
- if (chan->common.func(skb,dev,chan->common.sk) != 0){
- /* Sock full cannot send, queue us for
- * another try */
- atomic_set(&chan->common.receive_block,1);
- return;
- }else{
- fr_bh_cleanup(dev);
- }
- }else{
- fr_bh_cleanup(dev);
- }
- }
- clear_bit(0, &chan->tq_working);
-
- return;
-}
-
-static int fr_bh_cleanup(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
-
- ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
- if (chan->bh_read == (MAX_BH_BUFF-1)){
- chan->bh_read=0;
- }else{
- ++chan->bh_read;
- }
-
- atomic_dec(&chan->bh_buff_used);
- return 0;
-}
-
-
-/*----------------------------------------------------------------------
- POLL BH HANDLERS AND KICK ROUTINES
- ----------------------------------------------------------------------*/
-
-/*============================================================
- * trigger_fr_poll
- *
- * Description:
- * Add a fr_poll() task into a tq_scheduler bh handler
- * for a specific dlci/interface. This will kick
- * the fr_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
-static void trigger_fr_poll(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
- schedule_work(&chan->fr_poll_work);
- return;
-}
-
-
-/*============================================================
- * fr_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * Frame relay polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each frame relay
- * dlci/interface through a tq_schedule bottom half.
- *
- * trigger_fr_poll() function is used to kick
- * the fr_poll routine.
- */
-
-static void fr_poll(struct net_device *dev)
-{
-
- fr_channel_t* chan;
- sdla_t *card;
- u8 check_gateway=0;
-
- if (!dev || (chan = dev->priv) == NULL)
- return;
-
- card = chan->card;
-
- /* (Re)Configuraiton is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
-
- switch (chan->common.state){
-
- case WAN_DISCONNECTED:
-
- if (test_bit(DYN_OPT_ON,&chan->interface_down) &&
- !test_bit(DEV_DOWN, &chan->interface_down) &&
- dev->flags&IFF_UP){
-
- printk(KERN_INFO "%s: Interface %s is Down.\n",
- card->devname,dev->name);
- change_dev_flags(dev,dev->flags&~IFF_UP);
- set_bit(DEV_DOWN, &chan->interface_down);
- chan->route_flag = NO_ROUTE;
-
- }else{
- if (chan->inarp != INARP_NONE)
- process_route(dev);
- }
- break;
-
- case WAN_CONNECTED:
-
- if (test_bit(DYN_OPT_ON,&chan->interface_down) &&
- test_bit(DEV_DOWN, &chan->interface_down) &&
- !(dev->flags&IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s is Up.\n",
- card->devname,dev->name);
-
- change_dev_flags(dev,dev->flags|IFF_UP);
- clear_bit(DEV_DOWN, &chan->interface_down);
- check_gateway=1;
- }
-
- if (chan->inarp != INARP_NONE){
- process_route(dev);
- check_gateway=1;
- }
-
- if (chan->gateway && check_gateway)
- add_gateway(card,dev);
-
- break;
-
- }
-
- return;
-}
-
-/*==============================================================
- * check_tx_status
- *
- * Rationale:
- * We cannot transmit from an interrupt while
- * the if_send is transmitting data. Therefore,
- * we must check whether the tx buffers are
- * begin used, before we transmit from an
- * interrupt.
- *
- * Description:
- * Checks whether it's safe to use the transmit
- * buffers.
- *
- * Usage:
- * ARP and UDP handling routines use this function
- * because, they need to transmit data during
- * an interrupt.
- */
-
-static int check_tx_status(sdla_t *card, struct net_device *dev)
-{
-
- if (card->hw.type == SDLA_S514){
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical) ||
- test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) {
- return 1;
- }
- }
-
- if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
- return 1;
-
- return 0;
-}
-
-/*===============================================================
- * move_dev_to_next
- *
- * Description:
- * Move the dev pointer to the next location in the
- * link list. Check if we are at the end of the
- * list, if so start from the begining.
- *
- * Usage:
- * Timer interrupt uses this function to efficiently
- * step through the devices that need to send ARP data.
- *
- */
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev)
-{
- if (card->wandev.new_if_cnt != 1){
- if (!*((struct net_device **)dev->priv))
- return card->wandev.dev;
- else
- return *((struct net_device **)dev->priv);
- }
- return dev;
-}
-
-/*==============================================================
- * trigger_config_fr
- *
- * Rationale:
- * All commands must be performed inside of a
- * interrupt.
- *
- * Description:
- * Kick the config_fr() routine throught the
- * timer interrupt.
- */
-
-
-static void trigger_config_fr (sdla_t *card)
-{
- fr508_flags_t* flags = card->flags;
-
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->imask |= FR_INTR_TIMER;
-}
-
-
-/*==============================================================
- * config_fr
- *
- * Rationale:
- * All commands must be performed inside of a
- * interrupt.
- &
- * Description:
- * Configure a DLCI. This function is executed
- * by a timer_interrupt. The if_open() function
- * triggers it.
- *
- * Usage:
- * new_if() collects all data necessary to
- * configure the DLCI. It sets the chan->dlci_ready
- * bit. When the if_open() function is executed
- * it checks this bit, and if its set it triggers
- * the timer interrupt to execute the config_fr()
- * function.
- */
-
-static void config_fr (sdla_t *card)
-{
- struct net_device *dev;
- fr_channel_t *chan;
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
-
- if ((chan=dev->priv) == NULL)
- continue;
-
- if (!test_bit(0,&chan->config_dlci))
- continue;
-
- clear_bit(0,&chan->config_dlci);
-
- /* If signalling is set to NO, then setup
- * DLCI addresses right away. Don't have to wait for
- * link to connect.
- */
- if (card->wandev.signalling == WANOPT_NO){
- printk(KERN_INFO "%s: Signalling set to NO: Mapping DLCI's\n",
- card->wandev.name);
- if (fr_init_dlci(card,chan)){
- printk(KERN_INFO "%s: ERROR: Failed to configure DLCI %i !\n",
- card->devname, chan->dlci);
- return;
- }
- }
-
- if (card->wandev.station == WANOPT_CPE) {
-
- update_chan_state(dev);
-
- /* CPE: issue full status enquiry */
- fr_issue_isf(card, FR_ISF_FSE);
-
- } else {
- /* FR switch: activate DLCI(s) */
-
- /* For Switch emulation we have to ADD and ACTIVATE
- * the DLCI(s) that were configured with the SET_DLCI_
- * CONFIGURATION command. Add and Activate will fail if
- * DLCI specified is not included in the list.
- *
- * Also If_open is called once for each interface. But
- * it does not get in here for all the interface. So
- * we have to pass the entire list of DLCI(s) to add
- * activate routines.
- */
-
- if (!check_dlci_config (card, chan)){
- fr_add_dlci(card, chan->dlci);
- fr_activate_dlci(card, chan->dlci);
- }
- }
-
- card->u.f.dlci_to_dev_map[chan->dlci] = dev;
- }
- return;
-}
-
-
-/*==============================================================
- * config_fr
- *
- * Rationale:
- * All commands must be executed during an interrupt.
- *
- * Description:
- * Trigger uncofig_fr() function through
- * the timer interrupt.
- *
- */
-
-static void trigger_unconfig_fr(struct net_device *dev)
-{
- fr_channel_t *chan = dev->priv;
- volatile sdla_t *card = chan->card;
- unsigned long timeout;
- fr508_flags_t* flags = card->flags;
- int reset_critical=0;
-
- if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){
- clear_bit(PERI_CRIT,(void*)&card->wandev.critical);
- reset_critical=1;
- }
-
- /* run unconfig_dlci() function
- * throught the timer interrupt */
- set_bit(0,(void*)&chan->unconfig_dlci);
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UNCONFIG;
- flags->imask |= FR_INTR_TIMER;
-
- /* Wait for the command to complete */
- timeout = jiffies;
- for(;;) {
-
- if(!(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG))
- break;
-
- if (time_after(jiffies, timeout + 1 * HZ)){
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG;
- printk(KERN_INFO "%s: Failed to delete DLCI %i\n",
- card->devname,chan->dlci);
- break;
- }
- }
-
- if (reset_critical){
- set_bit(PERI_CRIT,(void*)&card->wandev.critical);
- }
-}
-
-/*==============================================================
- * unconfig_fr
- *
- * Rationale:
- * All commands must be executed during an interrupt.
- *
- * Description:
- * Remove the dlci from firmware.
- * This funciton is used in NODE shutdown.
- */
-
-static void unconfig_fr (sdla_t *card)
-{
- struct net_device *dev;
- fr_channel_t *chan;
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)){
-
- if ((chan=dev->priv) == NULL)
- continue;
-
- if (!test_bit(0,&chan->unconfig_dlci))
- continue;
-
- clear_bit(0,&chan->unconfig_dlci);
-
- if (card->wandev.station == WANOPT_NODE){
- printk(KERN_INFO "%s: Unconfiguring DLCI %i\n",
- card->devname,chan->dlci);
- fr_delete_dlci(card,chan->dlci);
- }
- card->u.f.dlci_to_dev_map[chan->dlci] = NULL;
- }
-}
-
-static int setup_fr_header(struct sk_buff *skb, struct net_device* dev,
- char op_mode)
-{
- fr_channel_t *chan=dev->priv;
-
- if (op_mode == WANPIPE) {
- chan->fr_header[0]=Q922_UI;
-
- switch (htons(skb->protocol)){
- case ETH_P_IP:
- chan->fr_header[1]=NLPID_IP;
- break;
- default:
- return -EINVAL;
- }
-
- return 2;
- }
-
- /* If we are in bridging mode, we must apply
- * an Ethernet header
- */
- if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) {
- /* Encapsulate the packet as a bridged Ethernet frame. */
-#ifdef DEBUG
- printk(KERN_INFO "%s: encapsulating skb for frame relay\n",
- dev->name);
-#endif
- chan->fr_header[0] = 0x03;
- chan->fr_header[1] = 0x00;
- chan->fr_header[2] = 0x80;
- chan->fr_header[3] = 0x00;
- chan->fr_header[4] = 0x80;
- chan->fr_header[5] = 0xC2;
- chan->fr_header[6] = 0x00;
- chan->fr_header[7] = 0x07;
-
- /* Yuck. */
- skb->protocol = ETH_P_802_3;
- return 8;
- }
-
- return 0;
-}
-
-
-static int check_dlci_config (sdla_t *card, fr_channel_t *chan)
-{
- fr_mbox_t* mbox = card->mbox;
- int err=0;
- fr_conf_t *conf=NULL;
- unsigned short dlci_num = chan->dlci;
- int dlci_offset=0;
- struct net_device *dev = NULL;
-
- mbox->cmd.command = FR_READ_CONFIG;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = dlci_num;
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err == CMD_OK){
- return 0;
- }
-
- for (dev = card->wandev.dev; dev;
- dev=*((struct net_device **)dev->priv))
- set_chan_state(dev,WAN_DISCONNECTED);
-
- printk(KERN_INFO "DLCI %i Not configured, configuring\n",dlci_num);
-
- mbox->cmd.command = FR_COMM_DISABLE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK){
- fr_event(card, err, mbox);
- return 2;
- }
-
- printk(KERN_INFO "Disabled Communications \n");
-
- mbox->cmd.command = FR_READ_CONFIG;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = 0;
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK){
- fr_event(card, err, mbox);
- return 2;
- }
-
- conf = (fr_conf_t *)mbox->data;
-
- dlci_offset=0;
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
- fr_channel_t *chan_tmp = dev->priv;
- conf->dlci[dlci_offset] = chan_tmp->dlci;
- dlci_offset++;
- }
-
- printk(KERN_INFO "Got Fr configuration Buffer Length is %x Dlci %i Dlci Off %i\n",
- mbox->cmd.length,
- mbox->cmd.length > 0x20 ? conf->dlci[0] : -1,
- dlci_offset );
-
- mbox->cmd.length = 0x20 + dlci_offset*2;
-
- mbox->cmd.command = FR_SET_CONFIG;
- mbox->cmd.dlci = 0;
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK){
- fr_event(card, err, mbox);
- return 2;
- }
-
- initialize_rx_tx_buffers (card);
-
-
- printk(KERN_INFO "Configuraiton Succeded for new DLCI %i\n",dlci_num);
-
- if (fr_comm_enable (card)){
- return 2;
- }
-
- printk(KERN_INFO "Enabling Communications \n");
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
- fr_channel_t *chan_tmp = dev->priv;
- fr_init_dlci(card,chan_tmp);
- fr_add_dlci(card, chan_tmp->dlci);
- fr_activate_dlci(card, chan_tmp->dlci);
- }
-
- printk(KERN_INFO "END OF CONFIGURAITON %i\n",dlci_num);
-
- return 1;
-}
-
-static void initialize_rx_tx_buffers (sdla_t *card)
-{
- fr_buf_info_t* buf_info;
-
- if (card->hw.type == SDLA_S514) {
-
- buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR +
- FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) +
- card->hw.dpmbase);
- }else{
- buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) -
- FR_MB_VECTOR + card->hw.dpmbase);
- }
-
- card->u.f.rx_base = buf_info->buf_base;
- card->u.f.rx_top = buf_info->buf_top;
-
- card->u.f.tx_interrupts_pending = 0;
-
- return;
-}
-
-
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c
deleted file mode 100644
index 9d6528a50f7b..000000000000
--- a/drivers/net/wan/sdla_ft1.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*****************************************************************************
-* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-1999 Sangoma Technologies 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.
-* ============================================================================
-* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
-* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
-* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
-* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
-* Aug 07, 1998 David Fong Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <linux/jiffies.h> /* time_after() macro */
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-
-/****** Defines & Macros ****************************************************/
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x0001
-#define TMR_INT_ENABLED_UPDATE 0x0002
-
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define WANPIPE 0x00
-#define API 0x01
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- struct net_device *slave;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpft1_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_CHDLC) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Use primary port */
- card->u.c.comm_port = 0;
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if (time_after(jiffies, timeout + 1*HZ)) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n",
- card->devname, u.str);
-
- card->isr = NULL;
- card->poll = NULL;
- card->exec = &wpft1_exec;
- card->wandev.update = NULL;
- card->wandev.new_if = NULL;
- card->wandev.del_if = NULL;
- card->wandev.state = WAN_DUALPORT;
- card->wandev.udp_port = conf->udp_port;
-
- card->wandev.new_if_cnt = 0;
-
- /* This is for the ports link state */
- card->u.c.state = WAN_DISCONNECTED;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = 0x7F;
- card->wandev.interface = 0;
-
- card->wandev.clocking = 0;
-
- port_num = card->u.c.comm_port;
-
- /* Setup Port Bps */
-
- card->wandev.bps = 0;
-
- card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG;
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- card->wandev.state = WAN_FT1_READY;
- printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname);
-
- return 0;
-}
-
-static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data)
-{
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int len;
-
- if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
- return -EFAULT;
- }
-
- len = mbox->buffer_length;
-
- if (len) {
- if( copy_from_user((void*)&mbox->data, u_data, len)){
- return -EFAULT;
- }
- }
-
- /* execute command */
- if (!sdla_exec(mbox)){
- return -EIO;
- }
-
- /* return result */
- if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){
- return -EFAULT;
- }
-
- len = mbox->buffer_length;
-
- if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
- return -EFAULT;
- }
-
- return 0;
-
-}
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
- unsigned cmd = mb->command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- case S514_BOTH_PORTS_SAME_CLK_MODE:
- if(cmd == SET_CHDLC_CONFIGURATION) {
- printk(KERN_INFO
- "%s: Configure both ports for the same clock source\n",
- card->devname);
- break;
- }
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- }
-
- return 0;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
deleted file mode 100644
index a4b489cccbbf..000000000000
--- a/drivers/net/wan/sdla_ppp.c
+++ /dev/null
@@ -1,3430 +0,0 @@
-/*****************************************************************************
-* sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for
-* 2.4.X kernels.
-* Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support:
-* get_ip_address() function has moved
-* into the ppp_poll() routine. It cannot
-* be called from an interrupt.
-* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging:
-* Deny all and specify allowed requests.
-* May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown
-* option. When the link goes down, the
-* network interface IFF_UP flag is reset.
-* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.
-* Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem.
-* Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called
-* with NULL dev pointer: no check.
-* Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter.
-* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels
-* Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels
-* Moved dynamic route processing into
-* a polling routine.
-* Oct 07, 1999 Nenad Corbic o Support for S514 PCI card.
-* Gideon Hack o UPD and Updates executed using timer interrupt
-* Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics
-* Jul 20, 1999 Nenad Corbic o Remove the polling routines and use
-* interrupts instead.
-* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels.
-* Aug 13, 1998 Jaspreet Singh o Improved Line Tracing.
-* Jun 22, 1998 David Fong o Added remote IP address assignment
-* Mar 15, 1998 Alan Cox o 2.1.8x basic port.
-* Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol.
-* Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP.
-* o Implemented new routines like
-* ppp_set_inbnd_auth(), ppp_set_outbnd_auth(),
-* tokenize() and strstrip().
-* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs
-* while they have been disabled.
-* Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by
-* disabling and enabling of irqs.
-* o Added new counters for stats on disable/enable
-* IRQs.
-* Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data'
-* before every netif_rx().
-* o Free up the device structure in del_if().
-* Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing
-* command.
-* Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time.
-* Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow
-* control by avoiding RACE conditions. The
-* cli() and restore_flags() are taken out.
-* A new structure, "ppp_private_area", is added
-* to provide Driver Statistics.
-* Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding
-* save_flags(), cli() and restore_flags().
-* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets
-* o Added ability to discard mulitcast and
-* broacast source addressed packets.
-* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities
-* New case (0x25) statement in if_send routine.
-* Added a global variable rCount to keep track
-* of FT1 status enabled on the board.
-* May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for
-* 508 card to reflect changes in the new
-* ppp508.sfm for supporting:continous transmission
-* of Configure-Request packets without receiving a
-* reply
-* OR-ed 0x300 to conf_flags
-* o Changed connect_tmout from 900 to 0
-* May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards
-* Apr 25, 1997 Farhan Thawar o added UDP Management stuff
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o fixed (+1) bug in rx_intr()
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* Jan 06, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/jiffies.h> /* time_after() macro */
-
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <linux/if.h>
-#include <linux/sdla_ppp.h> /* PPP firmware API definitions */
-#include <linux/sdlasfm.h> /* S514 Type Definition */
-/****** Defines & Macros ****************************************************/
-
-#define PPP_DFLT_MTU 1500 /* default MTU */
-#define PPP_MAX_MTU 4000 /* maximum MTU */
-#define PPP_HDR_LEN 1
-
-#define MAX_IP_ERRORS 100
-
-#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */
-#define HOLD_DOWN_TIME (5*HZ) /* link hold down time : Changed from 30 to 5 */
-
-/* For handle_IPXWAN() */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-/* Macro for enabling/disabling debugging comments */
-//#define NEX_DEBUG
-#ifdef NEX_DEBUG
-#define NEX_PRINTK(format, a...) printk(format, ## a)
-#else
-#define NEX_PRINTK(format, a...)
-#endif /* NEX_DEBUG */
-
-#define DCD(a) ( a & 0x08 ? "HIGH" : "LOW" )
-#define CTS(a) ( a & 0x20 ? "HIGH" : "LOW" )
-#define LCP(a) ( a == 0x09 ? "OPEN" : "CLOSED" )
-#define IP(a) ( a == 0x09 ? "ENABLED" : "DISABLED" )
-
-#define TMR_INT_ENABLED_UPDATE 0x01
-#define TMR_INT_ENABLED_PPP_EVENT 0x02
-#define TMR_INT_ENABLED_UDP 0x04
-#define TMR_INT_ENABLED_CONFIG 0x20
-
-/* Set Configuraton Command Definitions */
-#define PERCENT_TX_BUFF 60
-#define TIME_BETWEEN_CONF_REQ 30
-#define TIME_BETWEEN_PAP_CHAP_REQ 30
-#define WAIT_PAP_CHAP_WITHOUT_REPLY 300
-#define WAIT_AFTER_DCD_CTS_LOW 5
-#define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10
-#define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900
-#define MAX_CONF_REQ_WITHOUT_REPLY 10
-#define MAX_TERM_REQ_WITHOUT_REPLY 2
-#define NUM_CONF_NAK_WITHOUT_REPLY 5
-#define NUM_AUTH_REQ_WITHOUT_REPLY 10
-
-#define END_OFFSET 0x1F0
-
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with PPP specific data
- */
-
-typedef struct ppp_private_area
-{
- struct net_device *slave;
- sdla_t* card;
- unsigned long router_start_time; /*router start time in sec */
- unsigned long tick_counter; /*used for 5 second counter*/
- unsigned mc; /*multicast support on or off*/
- unsigned char enable_IPX;
- unsigned long network_number;
- unsigned char pap;
- unsigned char chap;
- unsigned char sysname[31]; /* system name for in-bnd auth*/
- unsigned char userid[511]; /* list of user ids */
- unsigned char passwd[511]; /* list of passwords */
- unsigned protocol; /* SKB Protocol */
- u32 ip_local; /* Local IP Address */
- u32 ip_remote; /* remote IP Address */
-
- u32 ip_local_tmp;
- u32 ip_remote_tmp;
-
- unsigned char timer_int_enabled; /* Who enabled the timer inter*/
- unsigned char update_comms_stats; /* Used by update function */
- unsigned long curr_trace_addr; /* Trace information */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
-
- unsigned char interface_down; /* Brind down interface when channel
- goes down */
- unsigned long config_wait_timeout; /* After if_open() if in dynamic if mode,
- wait a few seconds before configuring */
-
- unsigned short udp_pkt_lgth;
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-
- /* PPP specific statistics */
-
- if_send_stat_t if_send_stat;
- rx_intr_stat_t rx_intr_stat;
- pipe_mgmt_stat_t pipe_mgmt_stat;
-
- unsigned long router_up_time;
-
- /* Polling work queue entry. Each interface
- * has its own work queue entry, which is used
- * to defer events from the interrupt */
- struct work_struct poll_work;
- struct timer_list poll_delay_timer;
-
- u8 gateway;
- u8 config_ppp;
- u8 ip_error;
-
-}ppp_private_area_t;
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev);
-static int new_if(struct wan_device *wandev, struct net_device *dev,
- wanif_conf_t *conf);
-static int del_if(struct wan_device *wandev, struct net_device *dev);
-
-/* WANPIPE-specific entry points */
-static int wpp_exec (struct sdla *card, void *u_cmd, void *u_data);
-
-/* Network device interface */
-static int if_init(struct net_device *dev);
-static int if_open(struct net_device *dev);
-static int if_close(struct net_device *dev);
-static int if_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type,
- void *daddr, void *saddr, unsigned len);
-
-static void if_tx_timeout(struct net_device *dev);
-
-static int if_rebuild_hdr(struct sk_buff *skb);
-static struct net_device_stats *if_stats(struct net_device *dev);
-static int if_send(struct sk_buff *skb, struct net_device *dev);
-
-
-/* PPP firmware interface functions */
-static int ppp_read_version(sdla_t *card, char *str);
-static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area);
-static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area);
-static int ppp_configure(sdla_t *card, void *data);
-static int ppp_set_intr_mode(sdla_t *card, unsigned char mode);
-static int ppp_comm_enable(sdla_t *card);
-static int ppp_comm_disable(sdla_t *card);
-static int ppp_comm_disable_shutdown(sdla_t *card);
-static int ppp_get_err_stats(sdla_t *card);
-static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto);
-static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb);
-
-static void wpp_isr(sdla_t *card);
-static void rx_intr(sdla_t *card);
-static void event_intr(sdla_t *card);
-static void timer_intr(sdla_t *card);
-
-/* Background polling routines */
-static void process_route(sdla_t *card);
-static void retrigger_comm(sdla_t *card);
-
-/* Miscellaneous functions */
-static int read_info( sdla_t *card );
-static int read_connection_info (sdla_t *card);
-static void remove_route( sdla_t *card );
-static int config508(struct net_device *dev, sdla_t *card);
-static void show_disc_cause(sdla_t * card, unsigned cause);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev,
- ppp_private_area_t *ppp_priv_area);
-static void init_ppp_tx_rx_buff( sdla_t *card );
-static int intr_test( sdla_t *card );
-static int udp_pkt_type( struct sk_buff *skb , sdla_t *card);
-static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area);
-static void init_global_statistics( sdla_t *card );
-static int tokenize(char *str, char **tokens);
-static char* strstrip(char *str, char *s);
-static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev,
- struct sk_buff *skb);
-
-static int config_ppp (sdla_t *);
-static void ppp_poll(struct net_device *dev);
-static void trigger_ppp_poll(struct net_device *dev);
-static void ppp_poll_delay (unsigned long dev_ptr);
-
-
-static int Read_connection_info;
-static int Intr_test_counter;
-static unsigned short available_buffer_space;
-
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number,
- unsigned char incoming);
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_PX,
- unsigned long network_number, unsigned short proto);
-
-/* Lock Functions */
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- ppp_private_area_t* ppp_priv_area );
-static unsigned short calc_checksum (char *data, int len);
-static void disable_comm (sdla_t *card);
-static int detect_and_fix_tx_bug (sdla_t *card);
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * PPP protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpp_init(sdla_t *card, wandev_conf_t *conf)
-{
- ppp_flags_t *flags;
- union
- {
- char str[80];
- } u;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_PPP) {
-
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
-
- }
-
- /* Initialize miscellaneous pointers to structures on the adapter */
- switch (card->hw.type) {
-
- case SDLA_S508:
- card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS);
- card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS);
- break;
-
- case SDLA_S514:
- card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS);
- card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS);
- break;
-
- default:
- return -EINVAL;
-
- }
- flags = card->flags;
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
- if (ppp_read_version(card, NULL) || ppp_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str);
- /* Adjust configuration and set defaults */
- card->wandev.mtu = (conf->mtu) ?
- min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU;
-
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->isr = &wpp_isr;
- card->poll = NULL;
- card->exec = &wpp_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.udp_port = conf->udp_port;
- card->wandev.ttl = conf->ttl;
- card->wandev.state = WAN_DISCONNECTED;
- card->disable_comm = &disable_comm;
- card->irq_dis_if_send_count = 0;
- card->irq_dis_poll_count = 0;
- card->u.p.authenticator = conf->u.ppp.authenticator;
- card->u.p.ip_mode = conf->u.ppp.ip_mode ?
- conf->u.ppp.ip_mode : WANOPT_PPP_STATIC;
- card->TracingEnabled = 0;
- Read_connection_info = 1;
-
- /* initialize global statistics */
- init_global_statistics( card );
-
-
-
- if (!card->configured){
- int err;
-
- Intr_test_counter = 0;
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk("%s: Interrupt Test Failed, Counter: %i\n",
- card->devname, Intr_test_counter);
- printk( "%s: Please choose another interrupt\n",card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n",
- card->devname, Intr_test_counter);
- card->configured = 1;
- }
-
- ppp_set_intr_mode(card, PPP_INTR_TIMER);
-
- /* Turn off the transmit and timer interrupt */
- flags->imask &= ~PPP_INTR_TIMER;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update(struct wan_device *wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile ppp_private_area_t *ppp_priv_area;
- ppp_flags_t *flags = card->flags;
- unsigned long timeout;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* Shutdown bug fix. This function can be
- * called with NULL dev pointer during
- * shutdown
- */
- if ((dev=card->wandev.dev) == NULL){
- return -ENODEV;
- }
-
- if ((ppp_priv_area=dev->priv) == NULL){
- return -ENODEV;
- }
-
- ppp_priv_area->update_comms_stats = 2;
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
- flags->imask |= PPP_INTR_TIMER;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies;
- for(;;) {
- if(ppp_priv_area->update_comms_stats == 0){
- break;
- }
- if (time_after(jiffies, timeout + 1 * HZ)){
- ppp_priv_area->update_comms_stats = 0;
- ppp_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device *wandev, struct net_device *dev,
- wanif_conf_t *conf)
-{
- sdla_t *card = wandev->private;
- ppp_private_area_t *ppp_priv_area;
-
- if (wandev->ndev)
- return -EEXIST;
-
-
- printk(KERN_INFO "%s: Configuring Interface: %s\n",
- card->devname, conf->name);
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-
- printk(KERN_INFO "%s: Invalid interface name!\n",
- card->devname);
- return -EINVAL;
-
- }
-
- /* allocate and initialize private data */
- ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL);
-
- if( ppp_priv_area == NULL )
- return -ENOMEM;
-
- memset(ppp_priv_area, 0, sizeof(ppp_private_area_t));
-
- ppp_priv_area->card = card;
-
- /* initialize data */
- strcpy(card->u.p.if_name, conf->name);
-
- /* initialize data in ppp_private_area structure */
-
- init_ppp_priv_struct( ppp_priv_area );
-
- ppp_priv_area->mc = conf->mc;
- ppp_priv_area->pap = conf->pap;
- ppp_priv_area->chap = conf->chap;
-
- /* Option to bring down the interface when
- * the link goes down */
- if (conf->if_down){
- set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down);
- printk("%s: Dynamic interface configuration enabled\n",
- card->devname);
- }
-
- /* If no user ids are specified */
- if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- /* If no passwords are specified */
- if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- if(strlen(conf->sysname) > 31){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- /* If no system name is specified */
- if(!strlen(conf->sysname) && (card->u.p.authenticator)){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- /* copy the data into the ppp private structure */
- memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid));
- memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd));
- memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname));
-
-
- ppp_priv_area->enable_IPX = conf->enable_IPX;
- if (conf->network_number){
- ppp_priv_area->network_number = conf->network_number;
- }else{
- ppp_priv_area->network_number = 0xDEADBEEF;
- }
-
- /* Tells us that if this interface is a
- * gateway or not */
- if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){
- printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
- card->devname,card->u.p.if_name);
- }
-
- /* prepare network device data space for registration */
- strcpy(dev->name,card->u.p.if_name);
-
- dev->init = &if_init;
- dev->priv = ppp_priv_area;
- dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu);
-
- /* Initialize the polling work routine */
- INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev);
-
- /* Initialize the polling delay timer */
- init_timer(&ppp_priv_area->poll_delay_timer);
- ppp_priv_area->poll_delay_timer.data = (unsigned long)dev;
- ppp_priv_area->poll_delay_timer.function = ppp_poll_delay;
-
-
- /* Since we start with dummy IP addresses we can say
- * that route exists */
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device *wandev, struct net_device *dev)
-{
- return 0;
-}
-
-static void disable_comm (sdla_t *card)
-{
- ppp_comm_disable_shutdown(card);
- return;
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-
-//FIXME: Why do we need this ????
-static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data)
-{
- ppp_mbox_t *mbox = card->mbox;
- int len;
-
- if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)))
- return -EFAULT;
-
- len = mbox->cmd.length;
-
- if (len) {
-
- if( copy_from_user((void*)&mbox->data, u_data, len))
- return -EFAULT;
-
- }
-
- /* execute command */
- if (!sdla_exec(mbox))
- return -EIO;
-
- /* return result */
- if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t)))
- return -EFAULT;
- len = mbox->cmd.length;
-
- if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))
- return -EFAULT;
-
- return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
- struct wan_device *wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* Initialize media-specific parameters */
- dev->type = ARPHRD_PPP; /* ARP h/w type */
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- /* Enable Mulitcasting if specified by user*/
- if (ppp_priv_area->mc == WANOPT_YES){
- dev->flags |= IFF_MULTICAST;
- }
-
- dev->mtu = wandev->mtu;
- dev->hard_header_len = PPP_HDR_LEN; /* media header length */
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 100;
- SET_MODULE_OWNER(dev);
-
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
- struct timeval tv;
- //unsigned long smp_flags;
-
- if (netif_running(dev))
- return -EBUSY;
-
- wanpipe_open(card);
-
- netif_start_queue(dev);
-
- do_gettimeofday( &tv );
- ppp_priv_area->router_start_time = tv.tv_sec;
-
- /* We cannot configure the card here because we don't
- * have access to the interface IP addresses.
- * Once the interface initilization is complete, we will be
- * able to access the IP addresses. Therefore,
- * configure the ppp link in the poll routine */
- set_bit(0,&ppp_priv_area->config_ppp);
- ppp_priv_area->config_wait_timeout=jiffies;
-
- /* Start the PPP configuration after 1sec delay.
- * This will give the interface initilization time
- * to finish its configuration */
- mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ);
- return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last open, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
-
- netif_stop_queue(dev);
- wanpipe_close(card);
-
- del_timer (&ppp_priv_area->poll_delay_timer);
- return 0;
-}
-
-/*============================================================================
- * Build media header.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it. If packet type is not
- * supported, set skb->protocol to 0 and discard packet later.
- *
- * Return: media header length.
- */
-static int if_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- switch (type)
- {
- case ETH_P_IP:
- case ETH_P_IPX:
- skb->protocol = htons(type);
- break;
-
- default:
- skb->protocol = 0;
- }
-
- return PPP_HDR_LEN;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- ppp_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++ chan->if_send_stat.if_send_tbusy;
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- ++chan->if_send_stat.if_send_tbusy_timeout;
- netif_wake_queue (dev);
-}
-
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send (struct sk_buff *skb, struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
- unsigned char *sendpacket;
- unsigned long smp_flags;
- ppp_flags_t *flags = card->flags;
- int udp_type;
- int err=0;
-
- ++ppp_priv_area->if_send_stat.if_send_entry;
-
- netif_stop_queue(dev);
-
- if (skb == NULL) {
-
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: interface %s got kicked!\n",
- card->devname, dev->name);
-
- ++ppp_priv_area->if_send_stat.if_send_skb_null;
-
- netif_wake_queue(dev);
- return 0;
- }
-
- sendpacket = skb->data;
-
- udp_type = udp_pkt_type( skb, card );
-
-
- if (udp_type == UDP_PTPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- ppp_priv_area)){
- flags->imask |= PPP_INTR_TIMER;
- }
- ++ppp_priv_area->if_send_stat.if_send_PIPE_request;
- netif_start_queue(dev);
- return 0;
- }
-
- /* Check for broadcast and multicast addresses
- * If found, drop (deallocate) a packet and return.
- */
- if(chk_bcast_mcast_addr(card, dev, skb)){
- ++card->wandev.stats.tx_dropped;
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
-
-
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
-
- ++card->wandev.stats.tx_dropped;
- ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
-
- if (card->wandev.state != WAN_CONNECTED) {
-
- ++ppp_priv_area->if_send_stat.if_send_wan_disconnected;
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
-
- } else if (!skb->protocol) {
- ++ppp_priv_area->if_send_stat.if_send_protocol_error;
- ++card->wandev.stats.tx_errors;
- netif_start_queue(dev);
-
- } else {
-
- /*If it's IPX change the network numbers to 0 if they're ours.*/
- if( skb->protocol == htons(ETH_P_IPX) ) {
- if(ppp_priv_area->enable_IPX) {
- switch_net_numbers( skb->data,
- ppp_priv_area->network_number, 0);
- } else {
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
- }
-
- if (ppp_send(card, skb->data, skb->len, skb->protocol)) {
- netif_stop_queue(dev);
- ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full;
- ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled;
- } else {
- ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr;
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += skb->len;
- netif_start_queue(dev);
- dev->trans_start = jiffies;
- }
- }
-
-if_send_exit_crit:
-
- if (!(err=netif_queue_stopped(dev))){
- dev_kfree_skb_any(skb);
- }else{
- ppp_priv_area->tick_counter = jiffies;
- flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */
- }
-
- clear_bit(SEND_CRIT,&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- ppp_private_area_t* ppp_priv_area )
-{
- int udp_pkt_stored = 0;
-
- if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){
- ppp_priv_area->udp_pkt_lgth = skb->len;
- ppp_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len);
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP;
- ppp_priv_area->protocol = skb->protocol;
- udp_pkt_stored = 1;
- }else{
- if (skb->len > MAX_LGTH_UDP_MGNT_PKT){
- printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n",
- card->devname, skb->len);
- }else{
- printk(KERN_INFO "%s: PIPEMON UPD request already pending\n",
- card->devname);
- }
- ppp_priv_area->udp_pkt_lgth = 0;
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
- /* fill in UDP reply */
- p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound=1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- p_udp_pkt->udp_pkt.udp_length = temp;
-
-
- /* swap UDP ports */
- temp = p_udp_pkt->udp_pkt.udp_src_port;
- p_udp_pkt->udp_pkt.udp_src_port =
- p_udp_pkt->udp_pkt.udp_dst_port;
- p_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
- /* calculate UDP checksum */
- p_udp_pkt->udp_pkt.udp_checksum = 0;
- p_udp_pkt->udp_pkt.udp_checksum =
- calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = udp_length + sizeof(ip_pkt_t);
- temp = (ip_length<<8)|(ip_length>>8);
- p_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = p_udp_pkt->ip_pkt.ip_src_address;
- p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address;
- p_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- p_udp_pkt->ip_pkt.hdr_checksum = 0;
- p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-/*
- If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- if incoming is 1 - if the net number is 0 make it ours
-
-*/
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[6] << 24) +
- (sendpacket[7] << 16) + (sendpacket[8] << 8) +
- sendpacket[9]);
-
- if (!incoming) {
- //If the destination network number is ours, make it 0
- if( pnetwork_number == network_number) {
- sendpacket[6] = sendpacket[7] = sendpacket[8] =
- sendpacket[9] = 0x00;
- }
- } else {
- //If the incoming network is 0, make it ours
- if( pnetwork_number == 0) {
- sendpacket[6] = (unsigned char)(network_number >> 24);
- sendpacket[7] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[8] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[9] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[18] << 24) +
- (sendpacket[19] << 16) + (sendpacket[20] << 8) +
- sendpacket[21]);
-
- if( !incoming ) {
- //If the source network is ours, make it 0
- if( pnetwork_number == network_number) {
- sendpacket[18] = sendpacket[19] = sendpacket[20] =
- sendpacket[21] = 0x00;
- }
- } else {
- //If the source network is 0, make it ours
- if( pnetwork_number == 0 ) {
- sendpacket[18] = (unsigned char)(network_number >> 24);
- sendpacket[19] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[20] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[21] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct net_device_stats.
- */
-static struct net_device_stats *if_stats(struct net_device *dev)
-{
-
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t* card;
-
- if( ppp_priv_area == NULL )
- return NULL;
-
- card = ppp_priv_area->card;
- return &card->wandev.stats;
-}
-
-/****** PPP Firmware Interface Functions ************************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int ppp_read_version(sdla_t *card, char *str)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_READ_CODE_VERSION;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
-
- ppp_error(card, err, mb);
-
- else if (str) {
-
- int len = mb->cmd.length;
-
- memcpy(str, mb->data, len);
- str[len] = '\0';
-
- }
-
- return err;
-}
-/*===========================================================================
- * Set Out-Bound Authentication.
-*/
-static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- memset(&mb->data, 0, (strlen(ppp_priv_area->userid) +
- strlen(ppp_priv_area->passwd) + 2 ) );
- memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid));
- memcpy((mb->data + strlen(ppp_priv_area->userid) + 1),
- ppp_priv_area->passwd, strlen(ppp_priv_area->passwd));
-
- mb->cmd.length = strlen(ppp_priv_area->userid) +
- strlen(ppp_priv_area->passwd) + 2 ;
-
- mb->cmd.command = PPP_SET_OUTBOUND_AUTH;
-
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
- return err;
-}
-
-/*===========================================================================
- * Set In-Bound Authentication.
-*/
-static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area)
-{
- ppp_mbox_t *mb = card->mbox;
- int err, i;
- char* user_tokens[32];
- char* pass_tokens[32];
- int userids, passwds;
- int add_ptr;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- memset(&mb->data, 0, 1008);
- memcpy(mb->data, ppp_priv_area->sysname,
- strlen(ppp_priv_area->sysname));
-
- /* Parse the userid string and the password string and build a string
- to copy it to the data area of the command structure. The string
- will look like "SYS_NAME<NULL>USER1<NULL>PASS1<NULL>USER2<NULL>PASS2
- ....<NULL> "
- */
- userids = tokenize( ppp_priv_area->userid, user_tokens);
- passwds = tokenize( ppp_priv_area->passwd, pass_tokens);
-
- if (userids != passwds){
- printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname);
- return 1;
- }
-
- add_ptr = strlen(ppp_priv_area->sysname) + 1;
- for (i=0; i<userids; i++){
- memcpy((mb->data + add_ptr), user_tokens[i],
- strlen(user_tokens[i]));
- memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1),
- pass_tokens[i], strlen(pass_tokens[i]));
- add_ptr = add_ptr + strlen(user_tokens[i]) + 1 +
- strlen(pass_tokens[i]) + 1;
- }
-
- mb->cmd.length = add_ptr + 1;
- mb->cmd.command = PPP_SET_INBOUND_AUTH;
-
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
- return err;
-}
-
-
-/*============================================================================
- * Tokenize string.
- * Parse a string of the following syntax:
- * <arg1>,<arg2>,...
- * and fill array of tokens with pointers to string elements.
- *
- */
-static int tokenize (char *str, char **tokens)
-{
- int cnt = 0;
-
- tokens[0] = strsep(&str, "/");
- while (tokens[cnt] && (cnt < 32 - 1))
- {
- tokens[cnt] = strstrip(tokens[cnt], " \t");
- tokens[++cnt] = strsep(&str, "/");
- }
- return cnt;
-}
-
-/*============================================================================
- * Strip leading and trailing spaces off the string str.
- */
-static char* strstrip (char *str, char* s)
-{
- char *eos = str + strlen(str); /* -> end of string */
-
- while (*str && strchr(s, *str))
- ++str /* strip leading spaces */
- ;
- while ((eos > str) && strchr(s, *(eos - 1)))
- --eos /* strip trailing spaces */
- ;
- *eos = '\0';
- return str;
-}
-/*============================================================================
- * Configure PPP firmware.
- */
-static int ppp_configure(sdla_t *card, void *data)
-{
- ppp_mbox_t *mb = card->mbox;
- int data_len = sizeof(ppp508_conf_t);
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- memcpy(mb->data, data, data_len);
- mb->cmd.length = data_len;
- mb->cmd.command = PPP_SET_CONFIG;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
- return err;
-}
-
-/*============================================================================
- * Set interrupt mode.
- */
-static int ppp_set_intr_mode(sdla_t *card, unsigned char mode)
-{
- ppp_mbox_t *mb = card->mbox;
- ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0];
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- ppp_intr_data->i_enable = mode;
-
- ppp_intr_data->irq = card->hw.irq;
- mb->cmd.length = 2;
-
- /* If timer has been enabled, set the timer delay to 1sec */
- if (mode & 0x80){
- ppp_intr_data->timer_len = 250; //5;//100; //250;
- mb->cmd.length = 4;
- }
-
- mb->cmd.command = PPP_SET_INTR_FLAGS;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
-
- return err;
-}
-
-/*============================================================================
- * Enable communications.
- */
-static int ppp_comm_enable(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_COMM_ENABLE;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
- else
- card->u.p.comm_enabled = 1;
-
- return err;
-}
-
-/*============================================================================
- * Disable communications.
- */
-static int ppp_comm_disable(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_COMM_DISABLE;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK)
- ppp_error(card, err, mb);
- else
- card->u.p.comm_enabled = 0;
-
- return err;
-}
-
-static int ppp_comm_disable_shutdown(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- ppp_intr_info_t *ppp_intr_data;
- int err;
-
- if (!mb){
- return 1;
- }
-
- ppp_intr_data = (ppp_intr_info_t *) &mb->data[0];
-
- /* Disable all interrupts */
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- ppp_intr_data->i_enable = 0;
-
- ppp_intr_data->irq = card->hw.irq;
- mb->cmd.length = 2;
-
- mb->cmd.command = PPP_SET_INTR_FLAGS;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- /* Disable communicatinons */
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_COMM_DISABLE;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- card->u.p.comm_enabled = 0;
-
- return 0;
-}
-
-
-
-/*============================================================================
- * Get communications error statistics.
- */
-static int ppp_get_err_stats(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_READ_ERROR_STATS;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err == CMD_OK) {
-
- ppp_err_stats_t* stats = (void*)mb->data;
- card->wandev.stats.rx_over_errors = stats->rx_overrun;
- card->wandev.stats.rx_crc_errors = stats->rx_bad_crc;
- card->wandev.stats.rx_missed_errors = stats->rx_abort;
- card->wandev.stats.rx_length_errors = stats->rx_lost;
- card->wandev.stats.tx_aborted_errors = stats->tx_abort;
-
- } else
- ppp_error(card, err, mb);
-
- return err;
-}
-
-/*============================================================================
- * Send packet.
- * Return: 0 - o.k.
- * 1 - no transmit buffers available
- */
-static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto)
-{
- ppp_buf_ctl_t *txbuf = card->u.p.txbuf;
-
- if (txbuf->flag)
- return 1;
-
- sdla_poke(&card->hw, txbuf->buf.ptr, data, len);
-
- txbuf->length = len; /* frame length */
-
- if (proto == htons(ETH_P_IPX))
- txbuf->proto = 0x01; /* protocol ID */
- else
- txbuf->proto = 0x00; /* protocol ID */
-
- txbuf->flag = 1; /* start transmission */
-
- /* Update transmit buffer control fields */
- card->u.p.txbuf = ++txbuf;
-
- if ((void*)txbuf > card->u.p.txbuf_last)
- card->u.p.txbuf = card->u.p.txbuf_base;
-
- return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb)
-{
- unsigned cmd = mb->cmd.command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n"
- , card->devname, cmd, err);
- }
-
- return 0;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * PPP interrupt service routine.
- */
-static void wpp_isr (sdla_t *card)
-{
- ppp_flags_t *flags = card->flags;
- char *ptr = &flags->iflag;
- struct net_device *dev = card->wandev.dev;
- int i;
-
- card->in_isr = 1;
- ++card->statistics.isr_entry;
-
- if (!dev && flags->iflag != PPP_INTR_CMD){
- card->in_isr = 0;
- flags->iflag = 0;
- return;
- }
-
- if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- card->in_isr = 0;
- flags->iflag = 0;
- return;
- }
-
-
- if(card->hw.type != SDLA_S514){
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
- ++card->statistics.isr_already_critical;
- printk (KERN_INFO "%s: Critical while in ISR!\n",
- card->devname);
- card->in_isr = 0;
- flags->iflag = 0;
- return;
- }
- }
-
- switch (flags->iflag) {
-
- case PPP_INTR_RXRDY: /* receive interrupt 0x01 (bit 0)*/
- ++card->statistics.isr_rx;
- rx_intr(card);
- break;
-
- case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/
- ++card->statistics.isr_tx;
- flags->imask &= ~PPP_INTR_TXRDY;
- netif_wake_queue(dev);
- break;
-
- case PPP_INTR_CMD: /* interface command completed */
- ++Intr_test_counter;
- ++card->statistics.isr_intr_test;
- break;
-
- case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/
- case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/
- case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/
- case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */
- event_intr(card);
- break;
-
- case PPP_INTR_TIMER:
- timer_intr(card);
- break;
-
- default: /* unexpected interrupt */
- ++card->statistics.isr_spurious;
- printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
- card->devname, flags->iflag);
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
- }
-
- card->in_isr = 0;
- flags->iflag = 0;
- return;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr(sdla_t *card)
-{
- ppp_buf_ctl_t *rxbuf = card->rxmb;
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area;
- struct sk_buff *skb;
- unsigned len;
- void *buf;
- int i;
- ppp_flags_t *flags = card->flags;
- char *ptr = &flags->iflag;
- int udp_type;
-
-
- if (rxbuf->flag != 0x01) {
-
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)rxbuf, rxbuf->flag);
-
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
-
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
-
- ++card->statistics.rx_intr_corrupt_rx_bfr;
-
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it means that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- ppp_set_intr_mode(card,0);
- return;
- }
-
- if (dev && netif_running(dev) && dev->priv){
-
- len = rxbuf->length;
- ppp_priv_area = dev->priv;
-
- /* Allocate socket buffer */
- skb = dev_alloc_skb(len);
-
- if (skb != NULL) {
-
- /* Copy data to the socket buffer */
- unsigned addr = rxbuf->buf.ptr;
-
- if ((addr + len) > card->u.p.rx_top + 1) {
-
- unsigned tmp = card->u.p.rx_top - addr + 1;
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, addr, buf, tmp);
- addr = card->u.p.rx_base;
- len -= tmp;
- }
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, addr, buf, len);
-
- /* Decapsulate packet */
- switch (rxbuf->proto) {
-
- case 0x00:
- skb->protocol = htons(ETH_P_IP);
- break;
-
- case 0x01:
- skb->protocol = htons(ETH_P_IPX);
- break;
- }
-
- udp_type = udp_pkt_type( skb, card );
-
- if (udp_type == UDP_PTPIPE_TYPE){
-
- /* Handle a UDP Request in Timer Interrupt */
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev,
- ppp_priv_area)){
- flags->imask |= PPP_INTR_TIMER;
- }
- ++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request;
-
-
- } else if (handle_IPXWAN(skb->data,card->devname,
- ppp_priv_area->enable_IPX,
- ppp_priv_area->network_number,
- skb->protocol)) {
-
- /* Handle an IPXWAN packet */
- if( ppp_priv_area->enable_IPX) {
-
- /* Make sure we are not already sending */
- if (!test_bit(SEND_CRIT, &card->wandev.critical)){
- ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX));
- }
- dev_kfree_skb_any(skb);
-
- } else {
- ++card->wandev.stats.rx_dropped;
- }
- } else {
- /* Pass data up the protocol stack */
- skb->dev = dev;
- skb->mac.raw = skb->data;
-
- ++card->wandev.stats.rx_packets;
- card->wandev.stats.rx_bytes += skb->len;
- ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack;
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
-
- } else {
-
- if (net_ratelimit()){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- ++card->wandev.stats.rx_dropped;
- ++ppp_priv_area->rx_intr_stat.rx_intr_no_socket;
- }
-
- } else {
- ++card->statistics.rx_intr_dev_not_started;
- }
-
- /* Release buffer element and calculate a pointer to the next one */
- rxbuf->flag = 0x00;
- card->rxmb = ++rxbuf;
- if ((void*)rxbuf > card->u.p.rxbuf_last)
- card->rxmb = card->u.p.rxbuf_base;
-}
-
-
-void event_intr (sdla_t *card)
-{
-
- struct net_device* dev = card->wandev.dev;
- ppp_private_area_t* ppp_priv_area = dev->priv;
- volatile ppp_flags_t *flags = card->flags;
-
- switch (flags->iflag){
-
- case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/
-
- if (net_ratelimit()){
- printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n",
- card->devname, DCD(flags->mstatus), CTS(flags->mstatus));
- }
- break;
-
- case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/
-
- NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n",
- flags->disc_cause);
-
- if (flags->disc_cause &
- (PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP |
- PPP_REMOTE_TERMINATION)) {
-
- if (card->u.p.ip_mode == WANOPT_PPP_PEER) {
- set_bit(0,&Read_connection_info);
- }
- wanpipe_set_state(card, WAN_DISCONNECTED);
-
- show_disc_cause(card, flags->disc_cause);
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
- trigger_ppp_poll(dev);
- }
- break;
-
- case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/
-
- NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n",
- card->devname,LCP(flags->lcp_state),
- IP(flags->ip_state));
-
- if (flags->lcp_state == 0x09 &&
- (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){
-
- /* Initialize the polling timer and set the state
- * to WAN_CONNNECTED */
-
-
- /* BUG FIX: When the protocol restarts, during heavy
- * traffic, board tx buffers and driver tx buffers
- * can go out of sync. This checks the condition
- * and if the tx buffers are out of sync, the
- * protocols are restarted.
- * I don't know why the board tx buffer is out
- * of sync. It could be that a packets is tx
- * while the link is down, but that is not
- * possible. The other possiblility is that the
- * firmware doesn't reinitialize properly.
- * FIXME: A better fix should be found.
- */
- if (detect_and_fix_tx_bug(card)){
-
- ppp_comm_disable(card);
-
- wanpipe_set_state(card, WAN_DISCONNECTED);
-
- ppp_priv_area->timer_int_enabled |=
- TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
- break;
- }
-
- card->state_tick = jiffies;
- wanpipe_set_state(card, WAN_CONNECTED);
-
- NEX_PRINTK(KERN_INFO "CON: L Tx: %lx B Tx: %lx || L Rx %lx B Rx %lx\n",
- (unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next,
- (unsigned long)card->rxmb, *card->u.p.rxbuf_next);
-
- /* Tell timer interrupt that PPP event occurred */
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
-
- /* If we are in PEER mode, we must first obtain the
- * IP information and then go into the poll routine */
- if (card->u.p.ip_mode != WANOPT_PPP_PEER){
- trigger_ppp_poll(dev);
- }
- }
- break;
-
- case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */
-
- NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n");
-
- if (card->u.p.ip_mode == WANOPT_PPP_PEER) {
- set_bit(0,&Read_connection_info);
- }
-
- wanpipe_set_state(card, WAN_DISCONNECTED);
-
- show_disc_cause(card, flags->disc_cause);
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
- trigger_ppp_poll(dev);
- break;
-
- default:
- printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname);
- }
-}
-
-
-
-/* TIMER INTERRUPT */
-
-void timer_intr (sdla_t *card)
-{
-
- struct net_device* dev = card->wandev.dev;
- ppp_private_area_t* ppp_priv_area = dev->priv;
- ppp_flags_t *flags = card->flags;
-
-
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){
- if (!config_ppp(card)){
- ppp_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_CONFIG;
- }
- }
-
- /* Update statistics */
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){
- ppp_get_err_stats(card);
- if(!(--ppp_priv_area->update_comms_stats)){
- ppp_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- /* PPIPEMON UDP request */
-
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){
- process_udp_mgmt_pkt(card,dev, ppp_priv_area);
- ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
- }
-
- /* PPP Event */
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){
-
- if (card->wandev.state == WAN_DISCONNECTED){
- retrigger_comm(card);
- }
-
- /* If the state is CONNECTING, it means that communicatins were
- * enabled. When the remote side enables its comminication we
- * should get an interrupt PPP_INTR_OPEN, thus turn off polling
- */
-
- else if (card->wandev.state == WAN_CONNECTING){
- /* Turn off the timer interrupt */
- ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT;
- }
-
- /* If state is connected and we are in PEER mode
- * poll for an IP address which will be provided by remote end.
- */
- else if ((card->wandev.state == WAN_CONNECTED &&
- card->u.p.ip_mode == WANOPT_PPP_PEER) &&
- test_bit(0,&Read_connection_info)){
-
- card->state_tick = jiffies;
- if (read_connection_info (card)){
- printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n",
- card->devname);
- }else{
- clear_bit(0,&Read_connection_info);
- set_bit(1,&Read_connection_info);
- trigger_ppp_poll(dev);
- }
- }else{
- //FIXME Put the comment back int
- ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT;
- }
-
- }/* End of PPP_EVENT */
-
-
- /* Only disable the timer interrupt if there are no udp, statistic */
- /* updates or events pending */
- if(!ppp_priv_area->timer_int_enabled) {
- flags->imask &= ~PPP_INTR_TIMER;
- }
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
- int i;
-
- if( proto == htons(ETH_P_IPX) ) {
- //It's an IPX packet
- if(!enable_IPX) {
- //Return 1 so we don't pass it up the stack.
- return 1;
- }
- } else {
- //It's not IPX so pass it up the stack.
- return 0;
- }
-
- if( sendpacket[16] == 0x90 &&
- sendpacket[17] == 0x04)
- {
- //It's IPXWAN
-
- if( sendpacket[2] == 0x02 &&
- sendpacket[34] == 0x00)
- {
- //It's a timer request packet
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
- //Go through the routing options and answer no to every
- //option except Unnumbered RIP/SAP
- for(i = 41; sendpacket[i] == 0x00; i += 5)
- {
- //0x02 is the option for Unnumbered RIP/SAP
- if( sendpacket[i + 4] != 0x02)
- {
- sendpacket[i + 1] = 0;
- }
- }
-
- //Skip over the extended Node ID option
- if( sendpacket[i] == 0x04 )
- {
- i += 8;
- }
-
- //We also want to turn off all header compression opt.
- for(; sendpacket[i] == 0x80 ;)
- {
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- //Set the packet type to timer response
- sendpacket[34] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
- }
- else if( sendpacket[34] == 0x02 )
- {
- //This is an information request packet
- printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
- //Set the packet type to information response
- sendpacket[34] = 0x03;
-
- //Set the router name
- sendpacket[51] = 'P';
- sendpacket[52] = 'T';
- sendpacket[53] = 'P';
- sendpacket[54] = 'I';
- sendpacket[55] = 'P';
- sendpacket[56] = 'E';
- sendpacket[57] = '-';
- sendpacket[58] = CVHexToAscii(network_number >> 28);
- sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 66; i < 99; i+= 1)
- {
- sendpacket[i] = 0;
- }
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
- }
- else
- {
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- //Set the WNodeID to our network address
- sendpacket[35] = (unsigned char)(network_number >> 24);
- sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- } else {
- //If we get here it's an IPX-data packet, so it'll get passed up the stack.
-
- //switch the network numbers
- switch_net_numbers(sendpacket, network_number, 1);
- return 0;
- }
-}
-
-/****** Background Polling Routines ****************************************/
-
-/* All polling functions are invoked by the TIMER interrupt in the wpp_isr
- * routine.
- */
-
-/*============================================================================
- * Monitor active link phase.
- */
-static void process_route (sdla_t *card)
-{
- ppp_flags_t *flags = card->flags;
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
-
- if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
- (flags->ip_state == 0x09)){
-
- /* We get ip_local from the firmware in PEER mode.
- * Therefore, if ip_local is 0, we failed to obtain
- * the remote IP address. */
- if (ppp_priv_area->ip_local == 0)
- return;
-
- printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname);
- if (read_info( card )) {
- printk(KERN_INFO
- "%s: An error occurred in IP assignment.\n",
- card->devname);
- } else {
- struct in_device *in_dev = dev->ip_ptr;
- if (in_dev != NULL ) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
-
- printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(ifa->ifa_local));
- printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(ifa->ifa_address));
- }else{
- printk(KERN_INFO
- "%s: Error: Failed to add a route for PPP interface %s\n",
- card->devname,dev->name);
- }
- }
- }
-}
-
-/*============================================================================
- * Monitor physical link disconnected phase.
- * o if interface is up and the hold-down timeout has expired, then retry
- * connection.
- */
-static void retrigger_comm(sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
-
- if (dev && ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) {
-
- wanpipe_set_state(card, WAN_CONNECTING);
-
- if(ppp_comm_enable(card) == CMD_OK){
- init_ppp_tx_rx_buff( card );
- }
- }
-}
-
-/****** Miscellaneous Functions *********************************************/
-
-/*============================================================================
- * Configure S508 adapter.
- */
-static int config508(struct net_device *dev, sdla_t *card)
-{
- ppp508_conf_t cfg;
- struct in_device *in_dev = dev->ip_ptr;
- ppp_private_area_t *ppp_priv_area = dev->priv;
-
- /* Prepare PPP configuration structure */
- memset(&cfg, 0, sizeof(ppp508_conf_t));
-
- if (card->wandev.clocking)
- cfg.line_speed = card->wandev.bps;
-
- if (card->wandev.interface == WANOPT_RS232)
- cfg.conf_flags |= INTERFACE_LEVEL_RS232;
-
-
- cfg.conf_flags |= DONT_TERMINATE_LNK_MAX_CONFIG; /*send Configure-Request packets forever*/
- cfg.txbuf_percent = PERCENT_TX_BUFF; /* % of Tx bufs */
- cfg.mtu_local = card->wandev.mtu;
- cfg.mtu_remote = card->wandev.mtu; /* Default */
- cfg.restart_tmr = TIME_BETWEEN_CONF_REQ; /* 30 = 3sec */
- cfg.auth_rsrt_tmr = TIME_BETWEEN_PAP_CHAP_REQ; /* 30 = 3sec */
- cfg.auth_wait_tmr = WAIT_PAP_CHAP_WITHOUT_REPLY; /* 300 = 30s */
- cfg.mdm_fail_tmr = WAIT_AFTER_DCD_CTS_LOW; /* 5 = 0.5s */
- cfg.dtr_drop_tmr = TIME_DCD_CTS_LOW_AFTER_LNK_DOWN; /* 10 = 1s */
- cfg.connect_tmout = WAIT_DCD_HIGH_AFTER_ENABLE_COMM; /* 900 = 90s */
- cfg.conf_retry = MAX_CONF_REQ_WITHOUT_REPLY; /* 10 = 1s */
- cfg.term_retry = MAX_TERM_REQ_WITHOUT_REPLY; /* 2 times */
- cfg.fail_retry = NUM_CONF_NAK_WITHOUT_REPLY; /* 5 times */
- cfg.auth_retry = NUM_AUTH_REQ_WITHOUT_REPLY; /* 10 times */
-
-
- if( !card->u.p.authenticator ) {
- printk(KERN_INFO "%s: Device is not configured as an authenticator\n",
- card->devname);
- cfg.auth_options = NO_AUTHENTICATION;
- }else{
- printk(KERN_INFO "%s: Device is configured as an authenticator\n",
- card->devname);
- cfg.auth_options = INBOUND_AUTH;
- }
-
- if( ppp_priv_area->pap == WANOPT_YES){
- cfg.auth_options |=PAP_AUTH;
- printk(KERN_INFO "%s: Pap enabled\n", card->devname);
- }
- if( ppp_priv_area->chap == WANOPT_YES){
- cfg.auth_options |= CHAP_AUTH;
- printk(KERN_INFO "%s: Chap enabled\n", card->devname);
- }
-
-
- if (ppp_priv_area->enable_IPX == WANOPT_YES){
- printk(KERN_INFO "%s: Enabling IPX Protocol\n",card->devname);
- cfg.ipx_options = ENABLE_IPX | ROUTING_PROT_DEFAULT;
- }else{
- cfg.ipx_options = DISABLE_IPX;
- }
-
- switch (card->u.p.ip_mode) {
-
- case WANOPT_PPP_STATIC:
-
- printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname);
- cfg.ip_options = L_AND_R_IP_NO_ASSIG |
- ENABLE_IP;
- cfg.ip_local = in_dev->ifa_list->ifa_local;
- cfg.ip_remote = in_dev->ifa_list->ifa_address;
- /* Debugging code used to check that IP addresses
- * obtained from the kernel are correct */
-
- NEX_PRINTK(KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
- NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name);
- break;
-
- case WANOPT_PPP_HOST:
-
- printk(KERN_INFO "%s: PPP IP Mode: HOST\n",card->devname);
- cfg.ip_options = L_IP_LOCAL_ASSIG |
- R_IP_LOCAL_ASSIG |
- ENABLE_IP;
- cfg.ip_local = in_dev->ifa_list->ifa_local;
- cfg.ip_remote = in_dev->ifa_list->ifa_address;
- /* Debugging code used to check that IP addresses
- * obtained from the kernel are correct */
- NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
- NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name);
-
- break;
-
- case WANOPT_PPP_PEER:
-
- printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname);
- cfg.ip_options = L_IP_REMOTE_ASSIG |
- R_IP_REMOTE_ASSIG |
- ENABLE_IP;
- cfg.ip_local = 0x00;
- cfg.ip_remote = 0x00;
- break;
-
- default:
- printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n",
- card->devname);
- printk(KERN_INFO "%s: PPP IP Modes: STATIC, PEER or HOST\n",
- card->devname);
- return 1;
- }
-
- return ppp_configure(card, &cfg);
-}
-
-/*============================================================================
- * Show disconnection cause.
- */
-static void show_disc_cause(sdla_t *card, unsigned cause)
-{
- if (cause & 0x0802)
-
- printk(KERN_INFO "%s: link terminated by peer\n",
- card->devname);
-
- else if (cause & 0x0004)
-
- printk(KERN_INFO "%s: link terminated by user\n",
- card->devname);
-
- else if (cause & 0x0008)
-
- printk(KERN_INFO "%s: authentication failed\n", card->devname);
-
- else if (cause & 0x0010)
-
- printk(KERN_INFO
- "%s: authentication protocol negotiation failed\n",
- card->devname);
-
- else if (cause & 0x0020)
-
- printk(KERN_INFO
- "%s: peer's request for authentication rejected\n",
- card->devname);
-
- else if (cause & 0x0040)
-
- printk(KERN_INFO "%s: MRU option rejected by peer\n",
- card->devname);
-
- else if (cause & 0x0080)
-
- printk(KERN_INFO "%s: peer's MRU was too small\n",
- card->devname);
-
- else if (cause & 0x0100)
-
- printk(KERN_INFO "%s: failed to negotiate peer's LCP options\n",
- card->devname);
-
- else if (cause & 0x0200)
-
- printk(KERN_INFO "%s: failed to negotiate peer's IPCP options\n"
- , card->devname);
-
- else if (cause & 0x0400)
-
- printk(KERN_INFO
- "%s: failed to negotiate peer's IPXCP options\n",
- card->devname);
-}
-
-/*=============================================================================
- * Process UDP call of type PTPIPEAB.
- */
-static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev,
- ppp_private_area_t *ppp_priv_area )
-{
- unsigned char buf2[5];
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short data_length, buffer_length, real_len;
- unsigned long data_ptr;
- int udp_mgmt_req_valid = 1;
- ppp_mbox_t *mbox = card->mbox;
- struct timeval tv;
- int err;
- ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t*)&ppp_priv_area->udp_pkt_data;
-
- memcpy(&buf2, &card->wandev.udp_port, 2 );
-
-
- if(ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- switch(ppp_udp_pkt->cblock.command) {
-
- case PPIPE_GET_IBA_DATA:
- case PPP_READ_CONFIG:
- case PPP_GET_CONNECTION_INFO:
- case PPIPE_ROUTER_UP_TIME:
- case PPP_READ_STATISTICS:
- case PPP_READ_ERROR_STATS:
- case PPP_READ_PACKET_STATS:
- case PPP_READ_LCP_STATS:
- case PPP_READ_IPCP_STATS:
- case PPP_READ_IPXCP_STATS:
- case PPP_READ_PAP_STATS:
- case PPP_READ_CHAP_STATS:
- case PPP_READ_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
-
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
-
- /* set length to 0 */
- ppp_udp_pkt->cblock.length = 0x00;
-
- /* set return code */
- ppp_udp_pkt->cblock.result = 0xCD;
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,ppp_udp_pkt->cblock.command);
- }
- } else {
- /* Initialize the trace element */
- trace_element_t trace_element;
-
- switch (ppp_udp_pkt->cblock.command){
-
- /* PPIPE_ENABLE_TRACING */
- case PPIPE_ENABLE_TRACING:
- if (!card->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mbox->cmd.command = PPP_DATALINE_MONITOR;
- mbox->cmd.length = 0x01;
- mbox->data[0] = ppp_udp_pkt->data[0];
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK) {
-
- ppp_error(card, err, mbox);
- card->TracingEnabled = 0;
-
- /* set the return code */
-
- ppp_udp_pkt->cblock.result = mbox->cmd.result;
- mbox->cmd.length = 0;
- break;
- }
-
- sdla_peek(&card->hw, 0xC000, &buf2, 2);
-
- ppp_priv_area->curr_trace_addr = 0;
- memcpy(&ppp_priv_area->curr_trace_addr, &buf2, 2);
- ppp_priv_area->start_trace_addr =
- ppp_priv_area->curr_trace_addr;
- ppp_priv_area->end_trace_addr =
- ppp_priv_area->start_trace_addr + END_OFFSET;
-
- /* MAX_SEND_BUFFER_SIZE - 28 (IP header)
- - 32 (ppipemon CBLOCK) */
- available_buffer_space = MAX_LGTH_UDP_MGNT_PKT -
- sizeof(ip_pkt_t)-
- sizeof(udp_pkt_t)-
- sizeof(wp_mgmt_t)-
- sizeof(cblock_t);
- }
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 0;
- card->TracingEnabled = 1;
- break;
-
- /* PPIPE_DISABLE_TRACING */
- case PPIPE_DISABLE_TRACING:
-
- if(card->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mbox->cmd.command = 0x33;
- mbox->cmd.length = 1;
- mbox->data[0] = 0x00;
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
-
- }
-
- /*set return code*/
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 0;
- card->TracingEnabled = 0;
- break;
-
- /* PPIPE_GET_TRACE_INFO */
- case PPIPE_GET_TRACE_INFO:
-
- if(!card->TracingEnabled) {
- /* set return code */
- ppp_udp_pkt->cblock.result = 1;
- mbox->cmd.length = 0;
- }
-
- buffer_length = 0;
-
- /* frames < 62, where 62 is the number of trace
- information elements. There is in total 496
- bytes of space and each trace information
- element is 8 bytes.
- */
- for ( frames=0; frames<62; frames++) {
-
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &ppp_udp_pkt->data[buffer_length];
-
- /* Read the whole trace packet */
- sdla_peek(&card->hw, ppp_priv_area->curr_trace_addr,
- &trace_element, sizeof(trace_element_t));
-
- /* no data on board so exit */
- if( trace_element.opp_flag == 0x00 )
- break;
-
- data_ptr = trace_element.trace_data_ptr;
-
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element.trace_length;
- }else{
- data_length = 0;
- ppp_udp_pkt->data[0] |= 0x02;
- }
-
- //FIXME: Do we need this check
- if ((available_buffer_space - buffer_length)
- < (sizeof(trace_element_t)+1)){
-
- /*indicate we have more frames
- * on board and exit
- */
- ppp_udp_pkt->data[0] |= 0x02;
- break;
- }
-
- trace_pkt->status = trace_element.trace_type;
- trace_pkt->time_stamp = trace_element.trace_time_stamp;
- trace_pkt->real_length = trace_element.trace_length;
-
- real_len = trace_element.trace_length;
-
- if(data_ptr == 0){
- trace_pkt->data_avail = 0x00;
- }else{
- /* we can take it next time */
- if ((available_buffer_space - buffer_length)<
- (real_len + sizeof(trace_pkt_t))){
-
- ppp_udp_pkt->data[0] |= 0x02;
- break;
- }
- trace_pkt->data_avail = 0x01;
-
- /* get the data */
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data,
- real_len);
- }
- /* zero the opp flag to
- show we got the frame */
- buf2[0] = 0x00;
- sdla_poke(&card->hw, ppp_priv_area->curr_trace_addr,
- &buf2, 1);
-
- /* now move onto the next
- frame */
- ppp_priv_area->curr_trace_addr += 8;
-
- /* check if we passed the last address */
- if ( ppp_priv_area->curr_trace_addr >=
- ppp_priv_area->end_trace_addr){
-
- ppp_priv_area->curr_trace_addr =
- ppp_priv_area->start_trace_addr;
- }
-
- /* update buffer length and make sure its even */
-
- if ( trace_pkt->data_avail == 0x01 ) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += 8;
-
- if( buffer_length & 0x0001 )
- buffer_length += 1;
- }
-
- /* ok now set the total number of frames passed
- in the high 5 bits */
- ppp_udp_pkt->data[0] |= (frames << 2);
-
- /* set the data length */
- mbox->cmd.length = buffer_length;
- ppp_udp_pkt->cblock.length = buffer_length;
-
- /* set return code */
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- /* PPIPE_GET_IBA_DATA */
- case PPIPE_GET_IBA_DATA:
-
- mbox->cmd.length = 0x09;
-
- sdla_peek(&card->hw, 0xF003, &ppp_udp_pkt->data,
- mbox->cmd.length);
-
- /* set the length of the data */
- ppp_udp_pkt->cblock.length = 0x09;
-
- /* set return code */
- ppp_udp_pkt->cblock.result = 0x00;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- /* PPIPE_FT1_READ_STATUS */
- case PPIPE_FT1_READ_STATUS:
- sdla_peek(&card->hw, 0xF020, &ppp_udp_pkt->data[0], 2);
- ppp_udp_pkt->cblock.length = mbox->cmd.length = 2;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- case PPIPE_FLUSH_DRIVER_STATS:
- init_ppp_priv_struct( ppp_priv_area );
- init_global_statistics( card );
- mbox->cmd.length = 0;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
-
- case PPIPE_ROUTER_UP_TIME:
-
- do_gettimeofday( &tv );
- ppp_priv_area->router_up_time = tv.tv_sec -
- ppp_priv_area->router_start_time;
- *(unsigned long *)&ppp_udp_pkt->data = ppp_priv_area->router_up_time;
- mbox->cmd.length = 4;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- /* PPIPE_DRIVER_STATISTICS */
- case PPIPE_DRIVER_STAT_IFSEND:
- memcpy(&ppp_udp_pkt->data, &ppp_priv_area->if_send_stat,
- sizeof(if_send_stat_t));
-
-
- ppp_udp_pkt->cblock.result = 0;
- ppp_udp_pkt->cblock.length = sizeof(if_send_stat_t);
- mbox->cmd.length = sizeof(if_send_stat_t);
- break;
-
- case PPIPE_DRIVER_STAT_INTR:
- memcpy(&ppp_udp_pkt->data, &card->statistics,
- sizeof(global_stats_t));
-
- memcpy(&ppp_udp_pkt->data+sizeof(global_stats_t),
- &ppp_priv_area->rx_intr_stat,
- sizeof(rx_intr_stat_t));
-
- ppp_udp_pkt->cblock.result = 0;
- ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- mbox->cmd.length = ppp_udp_pkt->cblock.length;
- break;
-
- case PPIPE_DRIVER_STAT_GEN:
- memcpy( &ppp_udp_pkt->data,
- &ppp_priv_area->pipe_mgmt_stat,
- sizeof(pipe_mgmt_stat_t));
-
- memcpy(&ppp_udp_pkt->data+sizeof(pipe_mgmt_stat_t),
- &card->statistics, sizeof(global_stats_t));
-
- ppp_udp_pkt->cblock.result = 0;
- ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- mbox->cmd.length = ppp_udp_pkt->cblock.length;
- break;
-
-
- /* FT1 MONITOR STATUS */
- case FT1_MONITOR_STATUS_CTRL:
-
- /* Enable FT1 MONITOR STATUS */
- if( ppp_udp_pkt->data[0] == 1) {
-
- if( rCount++ != 0 ) {
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if( ppp_udp_pkt->data[0] == 0) {
-
- if( --rCount != 0) {
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
- goto udp_dflt_cmd;
-
- /* WARNING: FIXME: This should be fixed.
- * The FT1 Status Ctrl doesn't have a break
- * statment. Thus, no code must be inserted
- * HERE: between default and above case statement */
-
- default:
-udp_dflt_cmd:
-
- /* it's a board command */
- mbox->cmd.command = ppp_udp_pkt->cblock.command;
- mbox->cmd.length = ppp_udp_pkt->cblock.length;
-
- if(mbox->cmd.length) {
- memcpy(&mbox->data,(unsigned char *)ppp_udp_pkt->data,
- mbox->cmd.length);
- }
-
- /* run the command on the board */
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK) {
-
- ppp_error(card, err, mbox);
- ++ppp_priv_area->pipe_mgmt_stat.
- UDP_PIPE_mgmt_adptr_cmnd_timeout;
- break;
- }
-
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK;
-
- /* copy the result back to our buffer */
- memcpy(&ppp_udp_pkt->cblock,mbox, sizeof(cblock_t));
-
- if(mbox->cmd.length) {
- memcpy(&ppp_udp_pkt->data,&mbox->data,mbox->cmd.length);
- }
-
- } /* end of switch */
- } /* end of else */
-
- /* Fill UDP TTL */
- ppp_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(ppp_priv_area->udp_pkt_data, mbox->cmd.length);
-
- if (ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- /* Make sure we are not already sending */
- if (!test_bit(SEND_CRIT,&card->wandev.critical)){
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_adptr;
- ppp_send(card,ppp_priv_area->udp_pkt_data,len,ppp_priv_area->protocol);
- }
-
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
-
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, len);
- memcpy(buf,ppp_priv_area->udp_pkt_data, len);
-
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack;
-
- /* Decapsulate packet and pass it up the protocol
- stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
- netif_rx(new_skb);
- dev->last_rx = jiffies;
-
- } else {
-
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket;
- printk(KERN_INFO "no socket buffers available!\n");
- }
- }
-
- ppp_priv_area->udp_pkt_lgth = 0;
-
- return;
-}
-
-/*=============================================================================
- * Initial the ppp_private_area structure.
- */
-static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area )
-{
-
- memset(&ppp_priv_area->if_send_stat, 0, sizeof(if_send_stat_t));
- memset(&ppp_priv_area->rx_intr_stat, 0, sizeof(rx_intr_stat_t));
- memset(&ppp_priv_area->pipe_mgmt_stat, 0, sizeof(pipe_mgmt_stat_t));
-}
-
-/*============================================================================
- * Initialize Global Statistics
- */
-static void init_global_statistics( sdla_t *card )
-{
- memset(&card->statistics, 0, sizeof(global_stats_t));
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-static void init_ppp_tx_rx_buff( sdla_t *card )
-{
- ppp508_buf_info_t* info;
-
- if (card->hw.type == SDLA_S514) {
-
- info = (void*)(card->hw.dpmbase + PPP514_BUF_OFFS);
-
- card->u.p.txbuf_base = (void*)(card->hw.dpmbase +
- info->txb_ptr);
-
- card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base +
- (info->txb_num - 1);
-
- card->u.p.rxbuf_base = (void*)(card->hw.dpmbase +
- info->rxb_ptr);
-
- card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base +
- (info->rxb_num - 1);
-
- } else {
-
- info = (void*)(card->hw.dpmbase + PPP508_BUF_OFFS);
-
- card->u.p.txbuf_base = (void*)(card->hw.dpmbase +
- (info->txb_ptr - PPP508_MB_VECT));
-
- card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base +
- (info->txb_num - 1);
-
- card->u.p.rxbuf_base = (void*)(card->hw.dpmbase +
- (info->rxb_ptr - PPP508_MB_VECT));
-
- card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base +
- (info->rxb_num - 1);
- }
-
- card->u.p.txbuf_next = (unsigned long*)&info->txb_nxt;
- card->u.p.rxbuf_next = (unsigned long*)&info->rxb1_ptr;
-
- card->u.p.rx_base = info->rxb_base;
- card->u.p.rx_top = info->rxb_end;
-
- card->u.p.txbuf = card->u.p.txbuf_base;
- card->rxmb = card->u.p.rxbuf_base;
-
-}
-
-/*=============================================================================
- * Read Connection Information (ie for Remote IP address assginment).
- * Called when ppp interface connected.
- */
-static int read_info( sdla_t *card )
-{
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
- int err;
-
- struct ifreq if_info;
- struct sockaddr_in *if_data1, *if_data2;
- mm_segment_t fs;
-
- /* Set Local and remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
-
- fs = get_fs();
- set_fs(get_ds()); /* get user space block */
-
- /* Change the local and remote ip address of the interface.
- * This will also add in the destination route.
- */
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = ppp_priv_area->ip_local;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFADDR, &if_info );
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = ppp_priv_area->ip_remote;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
- set_fs(fs); /* restore old block */
-
- if (err) {
- printk (KERN_INFO "%s: Adding of route failed: %i\n",
- card->devname,err);
- printk (KERN_INFO "%s: Local : %u.%u.%u.%u\n",
- card->devname,NIPQUAD(ppp_priv_area->ip_local));
- printk (KERN_INFO "%s: Remote: %u.%u.%u.%u\n",
- card->devname,NIPQUAD(ppp_priv_area->ip_remote));
- }
- return err;
-}
-
-/*=============================================================================
- * Remove Dynamic Route.
- * Called when ppp interface disconnected.
- */
-
-static void remove_route( sdla_t *card )
-{
-
- struct net_device *dev = card->wandev.dev;
- long ip_addr;
- int err;
-
- mm_segment_t fs;
- struct ifreq if_info;
- struct sockaddr_in *if_data1;
- struct in_device *in_dev = dev->ip_ptr;
- struct in_ifaddr *ifa = in_dev->ifa_list;
-
- ip_addr = ifa->ifa_local;
-
- /* Set Local and remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- fs = get_fs();
- set_fs(get_ds()); /* get user space block */
-
- /* Change the local ip address of the interface to 0.
- * This will also delete the destination route.
- */
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = 0;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFADDR, &if_info );
-
- set_fs(fs); /* restore old block */
-
-
- if (err) {
- printk (KERN_INFO "%s: Deleting dynamic route failed %d!\n",
- card->devname, err);
- return;
- }else{
- printk (KERN_INFO "%s: PPP Deleting dynamic route %u.%u.%u.%u successfuly\n",
- card->devname, NIPQUAD(ip_addr));
- }
- return;
-}
-
-/*=============================================================================
- * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t *card )
-{
- ppp_mbox_t *mb = card->mbox;
- int err,i;
-
- err = ppp_set_intr_mode( card, 0x08 );
-
- if (err == CMD_OK) {
-
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- /* Run command READ_CODE_VERSION */
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.length = 0;
- mb->cmd.command = PPP_READ_CODE_VERSION;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK)
- ppp_error(card, err, mb);
- }
- }
- else return err;
-
- err = ppp_set_intr_mode( card, 0 );
- if (err != CMD_OK)
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. DRVSTATS or PTPIPEAB ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t *card )
-{
- unsigned char *sendpacket;
- unsigned char buf2[5];
- ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t *)skb->data;
-
- sendpacket = skb->data;
- memcpy(&buf2, &card->wandev.udp_port, 2);
-
- if( ppp_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45 && /* IP packet */
- sendpacket[9] == 0x11 && /* UDP packet */
- sendpacket[22] == buf2[1] && /* UDP Port */
- sendpacket[23] == buf2[0] &&
- sendpacket[36] == 0x01 ) {
-
- if ( sendpacket[28] == 0x50 && /* PTPIPEAB: Signature */
- sendpacket[29] == 0x54 &&
- sendpacket[30] == 0x50 &&
- sendpacket[31] == 0x49 &&
- sendpacket[32] == 0x50 &&
- sendpacket[33] == 0x45 &&
- sendpacket[34] == 0x41 &&
- sendpacket[35] == 0x42 ){
-
- return UDP_PTPIPE_TYPE;
-
- } else if(sendpacket[28] == 0x44 && /* DRVSTATS: Signature */
- sendpacket[29] == 0x52 &&
- sendpacket[30] == 0x56 &&
- sendpacket[31] == 0x53 &&
- sendpacket[32] == 0x54 &&
- sendpacket[33] == 0x41 &&
- sendpacket[34] == 0x54 &&
- sendpacket[35] == 0x53 ){
-
- return UDP_DRVSTATS_TYPE;
-
- } else
- return UDP_INVALID_TYPE;
-
- } else
- return UDP_INVALID_TYPE;
-
-}
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb)
-{
- u32 src_ip_addr;
- u32 broadcast_ip_addr = 0;
- struct in_device *in_dev;
-
- /* read the IP source address from the outgoing packet */
- src_ip_addr = *(u32 *)(skb->data + 12);
-
- /* read the IP broadcast address for the device */
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa= in_dev->ifa_list;
- if(ifa != NULL)
- broadcast_ip_addr = ifa->ifa_broadcast;
- else
- return 0;
- }
-
- /* check if the IP Source Address is a Broadcast address */
- if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
- printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- /* check if the IP Source Address is a Multicast address */
- if((ntohl(src_ip_addr) >= 0xE0000001) &&
- (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
- printk(KERN_INFO "%s: Multicast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- return 0;
-}
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-static int read_connection_info (sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
- ppp508_connect_info_t *ppp508_connect_info;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.length = 0;
- mb->cmd.command = PPP_GET_CONNECTION_INFO;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK) {
- ppp_error(card, err, mb);
- ppp_priv_area->ip_remote = 0;
- ppp_priv_area->ip_local = 0;
- }
- else {
- ppp508_connect_info = (ppp508_connect_info_t *)mb->data;
- ppp_priv_area->ip_remote = ppp508_connect_info->ip_remote;
- ppp_priv_area->ip_local = ppp508_connect_info->ip_local;
-
- NEX_PRINTK(KERN_INFO "READ CONNECTION GOT IP ADDRESS %x, %x\n",
- ppp_priv_area->ip_remote,
- ppp_priv_area->ip_local);
- }
-
- return err;
-}
-
-/*===============================================================================
- * config_ppp
- *
- * Configure the ppp protocol and enable communications.
- *
- * The if_open function binds this function to the poll routine.
- * Therefore, this function will run every time the ppp interface
- * is brought up.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- */
-static int config_ppp (sdla_t *card)
-{
-
- struct net_device *dev = card->wandev.dev;
- ppp_flags_t *flags = card->flags;
- ppp_private_area_t *ppp_priv_area = dev->priv;
-
- if (card->u.p.comm_enabled){
-
- if (ppp_priv_area->ip_local_tmp != ppp_priv_area->ip_local ||
- ppp_priv_area->ip_remote_tmp != ppp_priv_area->ip_remote){
-
- /* The IP addersses have changed, we must
- * stop the communications and reconfigure
- * the card. Reason: the firmware must know
- * the local and remote IP addresses. */
- disable_comm(card);
- wanpipe_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO
- "%s: IP addresses changed!\n",
- card->devname);
- printk(KERN_INFO "%s: Restarting communications ...\n",
- card->devname);
- }else{
- /* IP addresses are the same and the link is up,
- * we don't have to do anything here. Therefore, exit */
- return 0;
- }
- }
-
- /* Record the new IP addreses */
- ppp_priv_area->ip_local = ppp_priv_area->ip_local_tmp;
- ppp_priv_area->ip_remote = ppp_priv_area->ip_remote_tmp;
-
- if (config508(dev, card)){
- printk(KERN_INFO "%s: Failed to configure PPP device\n",
- card->devname);
- return 0;
- }
-
- if (ppp_set_intr_mode(card, PPP_INTR_RXRDY|
- PPP_INTR_TXRDY|
- PPP_INTR_MODEM|
- PPP_INTR_DISC |
- PPP_INTR_OPEN |
- PPP_INTR_DROP_DTR |
- PPP_INTR_TIMER)) {
-
- printk(KERN_INFO "%s: Failed to configure board interrupts !\n",
- card->devname);
- return 0;
- }
-
- /* Turn off the transmit and timer interrupt */
- flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ;
-
-
- /* If you are not the authenticator and any one of the protocol is
- * enabled then we call the set_out_bound_authentication.
- */
- if ( !card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) {
- if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){
- printk(KERN_INFO "%s: Outbound authentication failed !\n",
- card->devname);
- return 0;
- }
- }
-
- /* If you are the authenticator and any one of the protocol is enabled
- * then we call the set_in_bound_authentication.
- */
- if (card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)){
- if (ppp_set_inbnd_auth(card, ppp_priv_area)){
- printk(KERN_INFO "%s: Inbound authentication failed !\n",
- card->devname);
- return 0;
- }
- }
-
- /* If we fail to enable communications here it's OK,
- * since the DTR timer will cause a disconnected, which
- * will retrigger communication in timer_intr() */
- if (ppp_comm_enable(card) == CMD_OK) {
- wanpipe_set_state(card, WAN_CONNECTING);
- init_ppp_tx_rx_buff(card);
- }
-
- return 0;
-}
-
-/*============================================================
- * ppp_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * PPP polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each ppp
- * interface through a tq_schedule bottom half.
- *
- * trigger_ppp_poll() function is used to kick
- * the ppp_poll routine.
- */
-static void ppp_poll(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area;
- sdla_t *card;
- u8 check_gateway=0;
- ppp_flags_t *flags;
-
- if (!dev || (ppp_priv_area = dev->priv) == NULL)
- return;
-
- card = ppp_priv_area->card;
- flags = card->flags;
-
- /* Shutdown is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* if_open() function has triggered the polling routine
- * to determine the configured IP addresses. Once the
- * addresses are found, trigger the chdlc configuration */
- if (test_bit(0,&ppp_priv_area->config_ppp)){
-
- ppp_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP);
- ppp_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- if (ppp_priv_area->ip_local_tmp == ppp_priv_area->ip_remote_tmp &&
- card->u.p.ip_mode == WANOPT_PPP_HOST){
-
- if (++ppp_priv_area->ip_error > MAX_IP_ERRORS){
- printk(KERN_INFO "\n%s: --- WARNING ---\n",
- card->devname);
- printk(KERN_INFO "%s: The local IP address is the same as the\n",
- card->devname);
- printk(KERN_INFO "%s: Point-to-Point IP address.\n",
- card->devname);
- printk(KERN_INFO "%s: --- WARNING ---\n\n",
- card->devname);
- }else{
- clear_bit(POLL_CRIT,&card->wandev.critical);
- ppp_priv_area->poll_delay_timer.expires = jiffies+HZ;
- add_timer(&ppp_priv_area->poll_delay_timer);
- return;
- }
- }
-
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->imask |= PPP_INTR_TIMER;
- ppp_priv_area->ip_error=0;
-
- clear_bit(0,&ppp_priv_area->config_ppp);
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* Dynamic interface implementation, as well as dynamic
- * routing. */
-
- switch (card->wandev.state) {
-
- case WAN_DISCONNECTED:
-
- /* If the dynamic interface configuration is on, and interface
- * is up, then bring down the netowrk interface */
-
- if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) &&
- !test_bit(DEV_DOWN,&ppp_priv_area->interface_down) &&
- card->wandev.dev->flags & IFF_UP){
-
- printk(KERN_INFO "%s: Interface %s down.\n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,
- (card->wandev.dev->flags&~IFF_UP));
- set_bit(DEV_DOWN,&ppp_priv_area->interface_down);
- }else{
- /* We need to check if the local IP address is
- * zero. If it is, we shouldn't try to remove it.
- * For some reason the kernel crashes badly if
- * we try to remove the route twice */
-
- if (card->wandev.dev->flags & IFF_UP &&
- get_ip_address(card->wandev.dev,WAN_LOCAL_IP) &&
- card->u.p.ip_mode == WANOPT_PPP_PEER){
-
- remove_route(card);
- }
- }
- break;
-
- case WAN_CONNECTED:
-
- /* In SMP machine this code can execute before the interface
- * comes up. In this case, we must make sure that we do not
- * try to bring up the interface before dev_open() is finished */
-
-
- /* DEV_DOWN will be set only when we bring down the interface
- * for the very first time. This way we know that it was us
- * that brought the interface down */
-
- if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) &&
- test_bit(DEV_DOWN, &ppp_priv_area->interface_down) &&
- !(card->wandev.dev->flags & IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s up.\n",
- card->devname,card->wandev.dev->name);
-
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
- clear_bit(DEV_DOWN,&ppp_priv_area->interface_down);
- check_gateway=1;
- }
-
- if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
- test_bit(1,&Read_connection_info)) {
-
- process_route(card);
- clear_bit(1,&Read_connection_info);
- check_gateway=1;
- }
-
- if (ppp_priv_area->gateway && check_gateway)
- add_gateway(card,dev);
-
- break;
- }
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
-}
-
-/*============================================================
- * trigger_ppp_poll
- *
- * Description:
- * Add a ppp_poll() task into a tq_scheduler bh handler
- * for a specific interface. This will kick
- * the ppp_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
-
-static void trigger_ppp_poll(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area;
- if ((ppp_priv_area=dev->priv) != NULL){
-
- sdla_t *card = ppp_priv_area->card;
-
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
-
- if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- return;
- }
-
- schedule_work(&ppp_priv_area->poll_work);
- }
- return;
-}
-
-static void ppp_poll_delay (unsigned long dev_ptr)
-{
- struct net_device *dev = (struct net_device *)dev_ptr;
- trigger_ppp_poll(dev);
-}
-
-/*============================================================
- * detect_and_fix_tx_bug
- *
- * Description:
- * On connect, if the board tx buffer ptr is not the same
- * as the driver tx buffer ptr, we found a firmware bug.
- * Report the bug to the above layer. To fix the
- * error restart communications again.
- *
- * Usage:
- *
- */
-
-static int detect_and_fix_tx_bug (sdla_t *card)
-{
- if (((unsigned long)card->u.p.txbuf_base&0xFFF) != ((*card->u.p.txbuf_next)&0xFFF)){
- NEX_PRINTK(KERN_INFO "Major Error, Fix the bug\n");
- return 1;
- }
- return 0;
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
deleted file mode 100644
index 63f846d6f3a6..000000000000
--- a/drivers/net/wan/sdla_x25.c
+++ /dev/null
@@ -1,5497 +0,0 @@
-/*****************************************************************************
-* sdla_x25.c WANPIPE(tm) Multiprotocol WAN Link Driver. X.25 module.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Apr 03, 2001 Nenad Corbic o Fixed the rx_skb=NULL bug in x25 in rx_intr().
-* Dec 26, 2000 Nenad Corbic o Added a new polling routine, that uses
-* a kernel timer (more efficient).
-* Dec 25, 2000 Nenad Corbic o Updated for 2.4.X kernel
-* Jul 26, 2000 Nenad Corbic o Increased the local packet buffering
-* for API to 4096+header_size.
-* Jul 17, 2000 Nenad Corbic o Fixed the x25 startup bug. Enable
-* communications only after all interfaces
-* come up. HIGH SVC/PVC is used to calculate
-* the number of channels.
-* Enable protocol only after all interfaces
-* are enabled.
-* Jul 10, 2000 Nenad Corbic o Fixed the M_BIT bug.
-* Apr 25, 2000 Nenad Corbic o Pass Modem messages to the API.
-* Disable idle timeout in X25 API.
-* Apr 14, 2000 Nenad Corbic o Fixed: Large LCN number support.
-* Maximum LCN number is 4095.
-* Maximum number of X25 channels is 255.
-* Apr 06, 2000 Nenad Corbic o Added SMP Support.
-* Mar 29, 2000 Nenad Corbic o Added support for S514 PCI Card
-* Mar 23, 2000 Nenad Corbic o Improved task queue, BH handling.
-* Mar 14, 2000 Nenad Corbic o Updated Protocol Violation handling
-* routines. Bug Fix.
-* Mar 10, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.
-* Mar 09, 2000 Nenad Corbic o Fixed the auto HDLC bug.
-* Mar 08, 2000 Nenad Corbic o Fixed LAPB HDLC startup problems.
-* Application must bring the link up
-* before tx/rx, and bring the
-* link down on close().
-* Mar 06, 2000 Nenad Corbic o Added an option for logging call setup
-* information.
-* Feb 29, 2000 Nenad Corbic o Added support for LAPB HDLC API
-* Feb 25, 2000 Nenad Corbic o Fixed the modem failure handling.
-* No Modem OOB message will be passed
-* to the user.
-* Feb 21, 2000 Nenad Corbic o Added Xpipemon Debug Support
-* Dec 30, 1999 Nenad Corbic o Socket based X25API
-* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X kernel
-* Mar 15, 1998 Alan Cox o 2.1.x porting
-* Dec 19, 1997 Jaspreet Singh o Added multi-channel IPX support
-* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs
-* when they are disabled.
-* Nov 17, 1997 Farhan Thawar o Added IPX support
-* o Changed if_send() to now buffer packets when
-* the board is busy
-* o Removed queueing of packets via the polling
-* routing
-* o Changed if_send() critical flags to properly
-* handle race conditions
-* Nov 06, 1997 Farhan Thawar o Added support for SVC timeouts
-* o Changed PVC encapsulation to ETH_P_IP
-* Jul 21, 1997 Jaspreet Singh o Fixed freeing up of buffers using kfree()
-* when packets are received.
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o added support for V35
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* o added support for single '@' address to
-* accept all incoming calls
-* o fixed bug in set_chan_state() to disconnect
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* Jan 07, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-/*======================================================
- * Includes
- *=====================================================*/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/ctype.h>
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/workqueue.h>
-#include <linux/jiffies.h> /* time_after() macro */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <asm/atomic.h>
-#include <linux/delay.h> /* Experimental delay */
-
-#include <asm/uaccess.h>
-
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/sdla_x25.h> /* X.25 firmware API definitions */
-#include <linux/if_wanpipe_common.h>
-#include <linux/if_wanpipe.h>
-
-
-/*======================================================
- * Defines & Macros
- *=====================================================*/
-
-
-#define CMD_OK 0 /* normal firmware return code */
-#define CMD_TIMEOUT 0xFF /* firmware command timed out */
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-
-#define X25_CHAN_MTU 4096 /* unfragmented logical channel MTU */
-#define X25_HRDHDR_SZ 7 /* max encapsulation header size */
-#define X25_CONCT_TMOUT (90*HZ) /* link connection timeout */
-#define X25_RECON_TMOUT (10*HZ) /* link connection timeout */
-#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */
-#define HOLD_DOWN_TIME (30*HZ) /* link hold down time */
-#define MAX_BH_BUFF 10
-#define M_BIT 0x01
-
-//#define PRINT_DEBUG 1
-#ifdef PRINT_DEBUG
-#define DBG_PRINTK(format, a...) printk(format, ## a)
-#else
-#define DBG_PRINTK(format, a...)
-#endif
-
-#define TMR_INT_ENABLED_POLL_ACTIVE 0x01
-#define TMR_INT_ENABLED_POLL_CONNECT_ON 0x02
-#define TMR_INT_ENABLED_POLL_CONNECT_OFF 0x04
-#define TMR_INT_ENABLED_POLL_DISCONNECT 0x08
-#define TMR_INT_ENABLED_CMD_EXEC 0x10
-#define TMR_INT_ENABLED_UPDATE 0x20
-#define TMR_INT_ENABLED_UDP_PKT 0x40
-
-#define MAX_X25_ADDR_SIZE 16
-#define MAX_X25_DATA_SIZE 129
-#define MAX_X25_FACL_SIZE 110
-
-#define TRY_CMD_AGAIN 2
-#define DELAY_RESULT 1
-#define RETURN_RESULT 0
-
-#define DCD(x) (x & 0x03 ? "HIGH" : "LOW")
-#define CTS(x) (x & 0x05 ? "HIGH" : "LOW")
-
-
-/* Driver will not write log messages about
- * modem status if defined.*/
-#define MODEM_NOT_LOG 1
-
-/*====================================================
- * For IPXWAN
- *===================================================*/
-
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-
-/*====================================================
- * MEMORY DEBUGGING FUNCTION
- *====================================================
-
-#define KMEM_SAFETYZONE 8
-
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
- int i = 0;
- void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
- char * c1 = v;
- c1 += sizeof(unsigned int);
- *((unsigned int *)v) = size;
-
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
- c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
- c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
- c1 += 8;
- }
- v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
- printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v);
- return v;
-}
-static void dbg_kfree(void * v, int line) {
- unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
- unsigned int size = *sp;
- char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
- int i = 0;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
- || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
- || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
- ) {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- printk(KERN_INFO "line %d kfree(%p)\n",line,v);
- v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
- kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-
-==============================================================*/
-
-
-
-/*===============================================
- * Data Structures
- *===============================================*/
-
-
-/*========================================================
- * Name: x25_channel
- *
- * Purpose: To hold private informaton for each
- * logical channel.
- *
- * Rationale: Per-channel debugging is possible if each
- * channel has its own private area.
- *
- * Assumptions:
- *
- * Description: This is an extention of the struct net_device
- * we create for each network interface to keep
- * the rest of X.25 channel-specific data.
- *
- * Construct: Typedef
- */
-typedef struct x25_channel
-{
- wanpipe_common_t common; /* common area for x25api and socket */
- char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
- char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
- unsigned tx_pkt_size;
- unsigned short protocol; /* ethertype, 0 - multiplexed */
- char drop_sequence; /* mark sequence for dropping */
- unsigned long state_tick; /* time of the last state change */
- unsigned idle_timeout; /* sec, before disconnecting */
- unsigned long i_timeout_sofar; /* # of sec's we've been idle */
- unsigned hold_timeout; /* sec, before re-connecting */
- unsigned long tick_counter; /* counter for transmit time out */
- char devtint; /* Weather we should dev_tint() */
- struct sk_buff* rx_skb; /* receive socket buffer */
- struct sk_buff* tx_skb; /* transmit socket buffer */
-
- bh_data_t *bh_head; /* Circular buffer for x25api_bh */
- unsigned long tq_working;
- volatile int bh_write;
- volatile int bh_read;
- atomic_t bh_buff_used;
-
- sdla_t* card; /* -> owner */
- struct net_device *dev; /* -> bound devce */
-
- int ch_idx;
- unsigned char enable_IPX;
- unsigned long network_number;
- struct net_device_stats ifstats; /* interface statistics */
- unsigned short transmit_length;
- unsigned short tx_offset;
- char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)];
-
- if_send_stat_t if_send_stat;
- rx_intr_stat_t rx_intr_stat;
- pipe_mgmt_stat_t pipe_mgmt_stat;
-
- unsigned long router_start_time; /* Router start time in seconds */
- unsigned long router_up_time;
-
-} x25_channel_t;
-
-/* FIXME Take this out */
-
-#ifdef NEX_OLD_CALL_INFO
-typedef struct x25_call_info
-{
- char dest[17]; PACKED;/* ASCIIZ destination address */
- char src[17]; PACKED;/* ASCIIZ source address */
- char nuser; PACKED;/* number of user data bytes */
- unsigned char user[127]; PACKED;/* user data */
- char nfacil; PACKED;/* number of facilities */
- struct
- {
- unsigned char code; PACKED;
- unsigned char parm; PACKED;
- } facil[64]; /* facilities */
-} x25_call_info_t;
-#else
-typedef struct x25_call_info
-{
- char dest[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ destination address */
- char src[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ source address */
- unsigned char nuser PACKED;
- unsigned char user[MAX_X25_DATA_SIZE] PACKED;/* user data */
- unsigned char nfacil PACKED;
- unsigned char facil[MAX_X25_FACL_SIZE] PACKED;
- unsigned short lcn PACKED;
-} x25_call_info_t;
-#endif
-
-
-
-/*===============================================
- * Private Function Prototypes
- *==============================================*/
-
-
-/*=================================================
- * WAN link driver entry points. These are
- * called by the WAN router module.
- */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-static void disable_comm (sdla_t* card);
-static void disable_comm_shutdown(sdla_t *card);
-
-
-
-/*=================================================
- * WANPIPE-specific entry points
- */
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data);
-static void x25api_bh(struct net_device *dev);
-static int x25api_bh_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-
-/*=================================================
- * Network device interface
- */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr, unsigned len);
-static int if_rebuild_hdr (struct sk_buff* skb);
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats *if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/*=================================================
- * Interrupt handlers
- */
-static void wpx_isr (sdla_t *);
-static void rx_intr (sdla_t *);
-static void tx_intr (sdla_t *);
-static void status_intr (sdla_t *);
-static void event_intr (sdla_t *);
-static void spur_intr (sdla_t *);
-static void timer_intr (sdla_t *);
-
-static int tx_intr_send(sdla_t *card, struct net_device *dev);
-static struct net_device *move_dev_to_next(sdla_t *card,
- struct net_device *dev);
-
-/*=================================================
- * Background polling routines
- */
-static void wpx_poll (sdla_t* card);
-static void poll_disconnected (sdla_t* card);
-static void poll_connecting (sdla_t* card);
-static void poll_active (sdla_t* card);
-static void trigger_x25_poll(sdla_t *card);
-static void x25_timer_routine(unsigned long data);
-
-
-
-/*=================================================
- * X.25 firmware interface functions
- */
-static int x25_get_version (sdla_t* card, char* str);
-static int x25_configure (sdla_t* card, TX25Config* conf);
-static int hdlc_configure (sdla_t* card, TX25Config* conf);
-static int set_hdlc_level (sdla_t* card);
-static int x25_get_err_stats (sdla_t* card);
-static int x25_get_stats (sdla_t* card);
-static int x25_set_intr_mode (sdla_t* card, int mode);
-static int x25_close_hdlc (sdla_t* card);
-static int x25_open_hdlc (sdla_t* card);
-static int x25_setup_hdlc (sdla_t* card);
-static int x25_set_dtr (sdla_t* card, int dtr);
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan);
-static int x25_place_call (sdla_t* card, x25_channel_t* chan);
-static int x25_accept_call (sdla_t* card, int lcn, int qdm);
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn);
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf);
-static int x25_fetch_events (sdla_t* card);
-static int x25_error (sdla_t* card, int err, int cmd, int lcn);
-
-/*=================================================
- * X.25 asynchronous event handlers
- */
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-
-
-/*=================================================
- * Miscellaneous functions
- */
-static int connect (sdla_t* card);
-static int disconnect (sdla_t* card);
-static struct net_device* get_dev_by_lcn(struct wan_device* wandev,
- unsigned lcn);
-static int chan_connect(struct net_device* dev);
-static int chan_disc(struct net_device* dev);
-static void set_chan_state(struct net_device* dev, int state);
-static int chan_send(struct net_device *dev, void* buff, unsigned data_len,
- unsigned char tx_intr);
-static unsigned char bps_to_speed_code (unsigned long bps);
-static unsigned int dec_to_uint (unsigned char* str, int len);
-static unsigned int hex_to_uint (unsigned char*, int);
-static void parse_call_info (unsigned char*, x25_call_info_t*);
-static struct net_device *find_channel(sdla_t *card, unsigned lcn);
-static void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn);
-static void setup_for_delayed_transmit(struct net_device *dev,
- void *buf, unsigned len);
-
-
-/*=================================================
- * X25 API Functions
- */
-static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev,
- struct sk_buff **);
-static void timer_intr_exec(sdla_t *, unsigned char);
-static int execute_delayed_cmd(sdla_t *card, struct net_device *dev,
- mbox_cmd_t *usr_cmd, char bad_cmd);
-static int api_incoming_call (sdla_t*, TX25Mbox *, int);
-static int alloc_and_init_skb_buf (sdla_t *,struct sk_buff **, int);
-static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev,
- TX25Mbox* mbox);
-static int clear_confirm_event (sdla_t *, TX25Mbox*);
-static void send_oob_msg (sdla_t *card, struct net_device *dev, TX25Mbox *mbox);
-static int timer_intr_cmd_exec(sdla_t *card);
-static void api_oob_event (sdla_t *card,TX25Mbox *mbox);
-static int check_bad_command(sdla_t *card, struct net_device *dev);
-static int channel_disconnect(sdla_t* card, struct net_device *dev);
-static void hdlc_link_down (sdla_t*);
-
-/*=================================================
- * XPIPEMON Functions
- */
-static int process_udp_mgmt_pkt(sdla_t *);
-static int udp_pkt_type( struct sk_buff *, sdla_t*);
-static int reply_udp( unsigned char *, unsigned int);
-static void init_x25_channel_struct( x25_channel_t *);
-static void init_global_statistics( sdla_t *);
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t *card,
- struct net_device *dev,
- struct sk_buff *skb, int lcn);
-static unsigned short calc_checksum (char *, int);
-
-
-
-/*=================================================
- * IPX functions
- */
-static void switch_net_numbers(unsigned char *, unsigned long, unsigned char);
-static int handle_IPXWAN(unsigned char *, char *, unsigned char ,
- unsigned long , unsigned short );
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-static void S508_S514_lock(sdla_t *, unsigned long *);
-static void S508_S514_unlock(sdla_t *, unsigned long *);
-
-
-/*=================================================
- * Global Variables
- *=================================================*/
-
-
-
-/*=================================================
- * Public Functions
- *=================================================*/
-
-
-
-
-/*===================================================================
- * wpx_init: X.25 Protocol Initialization routine.
- *
- * Purpose: To initialize the protocol/firmware.
- *
- * Rationale: This function is called by setup() function, in
- * sdlamain.c, to dynamically setup the x25 protocol.
- * This is the first protocol specific function, which
- * executes once on startup.
- *
- * Description: This procedure initializes the x25 firmware and
- * sets up the mailbox, transmit and receive buffer
- * pointers. It also initializes all debugging structures
- * and sets up the X25 environment.
- *
- * Sets up hardware options defined by user in [wanpipe#]
- * section of wanpipe#.conf configuration file.
- *
- * At this point adapter is completely initialized
- * and X.25 firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the
- * adapter data space.
- *
- * Called by: setup() function in sdlamain.c
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-
-int wpx_init (sdla_t* card, wandev_conf_t* conf)
-{
- union{
- char str[80];
- TX25Config cfg;
- } u;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_X25){
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id)
- ;
- return -EINVAL;
- }
-
- /* Initialize protocol-specific fields */
- card->mbox = (void*)(card->hw.dpmbase + X25_MBOX_OFFS);
- card->rxmb = (void*)(card->hw.dpmbase + X25_RXMBOX_OFFS);
- card->flags = (void*)(card->hw.dpmbase + X25_STATUS_OFFS);
-
- /* Initialize for S514 Card */
- if(card->hw.type == SDLA_S514) {
- card->mbox += X25_MB_VECTOR;
- card->flags += X25_MB_VECTOR;
- card->rxmb += X25_MB_VECTOR;
- }
-
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
- if (x25_get_version(card, NULL) || x25_get_version(card, u.str))
- return -EIO;
-
-
- /* X25 firmware can run ether in X25 or LAPB HDLC mode.
- * Check the user defined option and configure accordingly */
- if (conf->u.x25.LAPB_hdlc_only == WANOPT_YES){
- if (set_hdlc_level(card) != CMD_OK){
- return -EIO;
- }else{
- printk(KERN_INFO "%s: running LAP_B HDLC firmware v%s\n",
- card->devname, u.str);
- }
- card->u.x.LAPB_hdlc = 1;
- }else{
- printk(KERN_INFO "%s: running X.25 firmware v%s\n",
- card->devname, u.str);
- card->u.x.LAPB_hdlc = 0;
- }
-
- /* Configure adapter. Here we set resonable defaults, then parse
- * device configuration structure and set configuration options.
- * Most configuration options are verified and corrected (if
- * necessary) since we can't rely on the adapter to do so.
- */
- memset(&u.cfg, 0, sizeof(u.cfg));
- u.cfg.t1 = 3;
- u.cfg.n2 = 10;
- u.cfg.autoHdlc = 1; /* automatic HDLC connection */
- u.cfg.hdlcWindow = 7;
- u.cfg.pktWindow = 2;
- u.cfg.station = 1; /* DTE */
- u.cfg.options = 0x0090; /* disable D-bit pragmatics */
- u.cfg.ccittCompat = 1988;
- u.cfg.t10t20 = 30;
- u.cfg.t11t21 = 30;
- u.cfg.t12t22 = 30;
- u.cfg.t13t23 = 30;
- u.cfg.t16t26 = 30;
- u.cfg.t28 = 30;
- u.cfg.r10r20 = 5;
- u.cfg.r12r22 = 5;
- u.cfg.r13r23 = 5;
- u.cfg.responseOpt = 1; /* RR's after every packet */
-
- if (card->u.x.LAPB_hdlc){
- u.cfg.hdlcMTU = 1027;
- }
-
- if (conf->u.x25.x25_conf_opt){
- u.cfg.options = conf->u.x25.x25_conf_opt;
- }
-
- if (conf->clocking != WANOPT_EXTERNAL)
- u.cfg.baudRate = bps_to_speed_code(conf->bps);
-
- if (conf->station != WANOPT_DTE){
- u.cfg.station = 0; /* DCE mode */
- }
-
- if (conf->interface != WANOPT_RS232 ){
- u.cfg.hdlcOptions |= 0x80; /* V35 mode */
- }
-
- /* adjust MTU */
- if (!conf->mtu || (conf->mtu >= 1024))
- card->wandev.mtu = 1024;
- else if (conf->mtu >= 512)
- card->wandev.mtu = 512;
- else if (conf->mtu >= 256)
- card->wandev.mtu = 256;
- else if (conf->mtu >= 128)
- card->wandev.mtu = 128;
- else
- card->wandev.mtu = 64;
-
- u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu;
-
- if (conf->u.x25.hi_pvc){
- card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM);
- card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc);
- }
-
- if (conf->u.x25.hi_svc){
- card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM);
- card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc);
- }
-
- /* Figure out the total number of channels to configure */
- card->u.x.num_of_ch = 0;
- if (card->u.x.hi_svc != 0){
- card->u.x.num_of_ch = (card->u.x.hi_svc - card->u.x.lo_svc) + 1;
- }
- if (card->u.x.hi_pvc != 0){
- card->u.x.num_of_ch += (card->u.x.hi_pvc - card->u.x.lo_pvc) + 1;
- }
-
- if (card->u.x.num_of_ch == 0){
- printk(KERN_INFO "%s: ERROR, Minimum number of PVC/SVC channels is 1 !\n"
- "%s: Please set the Lowest/Highest PVC/SVC values !\n",
- card->devname,card->devname);
- return -ECHRNG;
- }
-
- u.cfg.loPVC = card->u.x.lo_pvc;
- u.cfg.hiPVC = card->u.x.hi_pvc;
- u.cfg.loTwoWaySVC = card->u.x.lo_svc;
- u.cfg.hiTwoWaySVC = card->u.x.hi_svc;
-
- if (conf->u.x25.hdlc_window)
- u.cfg.hdlcWindow = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
- if (conf->u.x25.pkt_window)
- u.cfg.pktWindow = min_t(unsigned int, conf->u.x25.pkt_window, 7);
-
- if (conf->u.x25.t1)
- u.cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
- if (conf->u.x25.t2)
- u.cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 29);
- if (conf->u.x25.t4)
- u.cfg.t4 = min_t(unsigned int, conf->u.x25.t4, 240);
- if (conf->u.x25.n2)
- u.cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
-
- if (conf->u.x25.t10_t20)
- u.cfg.t10t20 = min_t(unsigned int, conf->u.x25.t10_t20,255);
- if (conf->u.x25.t11_t21)
- u.cfg.t11t21 = min_t(unsigned int, conf->u.x25.t11_t21,255);
- if (conf->u.x25.t12_t22)
- u.cfg.t12t22 = min_t(unsigned int, conf->u.x25.t12_t22,255);
- if (conf->u.x25.t13_t23)
- u.cfg.t13t23 = min_t(unsigned int, conf->u.x25.t13_t23,255);
- if (conf->u.x25.t16_t26)
- u.cfg.t16t26 = min_t(unsigned int, conf->u.x25.t16_t26, 255);
- if (conf->u.x25.t28)
- u.cfg.t28 = min_t(unsigned int, conf->u.x25.t28, 255);
-
- if (conf->u.x25.r10_r20)
- u.cfg.r10r20 = min_t(unsigned int, conf->u.x25.r10_r20,250);
- if (conf->u.x25.r12_r22)
- u.cfg.r12r22 = min_t(unsigned int, conf->u.x25.r12_r22,250);
- if (conf->u.x25.r13_r23)
- u.cfg.r13r23 = min_t(unsigned int, conf->u.x25.r13_r23,250);
-
-
- if (conf->u.x25.ccitt_compat)
- u.cfg.ccittCompat = conf->u.x25.ccitt_compat;
-
- /* initialize adapter */
- if (card->u.x.LAPB_hdlc){
- if (hdlc_configure(card, &u.cfg) != CMD_OK)
- return -EIO;
- }else{
- if (x25_configure(card, &u.cfg) != CMD_OK)
- return -EIO;
- }
-
- if ((x25_close_hdlc(card) != CMD_OK) || /* close HDLC link */
- (x25_set_dtr(card, 0) != CMD_OK)) /* drop DTR */
- return -EIO;
-
- /* Initialize protocol-specific fields of adapter data space */
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->isr = &wpx_isr;
- card->poll = NULL; //&wpx_poll;
- card->disable_comm = &disable_comm;
- card->exec = &wpx_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
-
- /* WARNING: This function cannot exit with an error
- * after the change of state */
- card->wandev.state = WAN_DISCONNECTED;
-
- card->wandev.enable_tx_int = 0;
- card->irq_dis_if_send_count = 0;
- card->irq_dis_poll_count = 0;
- card->u.x.tx_dev = NULL;
- card->u.x.no_dev = 0;
-
-
- /* Configure for S514 PCI Card */
- if (card->hw.type == SDLA_S514) {
- card->u.x.hdlc_buf_status =
- (volatile unsigned char *)
- (card->hw.dpmbase + X25_MB_VECTOR+ X25_MISC_HDLC_BITS);
- }else{
- card->u.x.hdlc_buf_status =
- (volatile unsigned char *)(card->hw.dpmbase + X25_MISC_HDLC_BITS);
- }
-
- card->u.x.poll_device=NULL;
- card->wandev.udp_port = conf->udp_port;
-
- /* Enable or disable call setup logging */
- if (conf->u.x25.logging == WANOPT_YES){
- printk(KERN_INFO "%s: Enabling Call Logging.\n",
- card->devname);
- card->u.x.logging = 1;
- }else{
- card->u.x.logging = 0;
- }
-
- /* Enable or disable modem status reporting */
- if (conf->u.x25.oob_on_modem == WANOPT_YES){
- printk(KERN_INFO "%s: Enabling OOB on Modem change.\n",
- card->devname);
- card->u.x.oob_on_modem = 1;
- }else{
- card->u.x.oob_on_modem = 0;
- }
-
- init_global_statistics(card);
-
- INIT_WORK(&card->u.x.x25_poll_work, (void *)wpx_poll, card);
-
- init_timer(&card->u.x.x25_timer);
- card->u.x.x25_timer.data = (unsigned long)card;
- card->u.x.x25_timer.function = x25_timer_routine;
-
- return 0;
-}
-
-/*=========================================================
- * WAN Device Driver Entry Points
- *========================================================*/
-
-/*============================================================
- * Name: update(), Update device status & statistics.
- *
- * Purpose: To provide debugging and statitical
- * information to the /proc file system.
- * /proc/net/wanrouter/wanpipe#
- *
- * Rationale: The /proc file system is used to collect
- * information about the kernel and drivers.
- * Using the /proc file system the user
- * can see exactly what the sangoma drivers are
- * doing. And in what state they are in.
- *
- * Description: Collect all driver statistical information
- * and pass it to the top laywer.
- *
- * Since we have to execute a debugging command,
- * to obtain firmware statitics, we trigger a
- * UPDATE function within the timer interrtup.
- * We wait until the timer update is complete.
- * Once complete return the appropriate return
- * code to indicate that the update was successful.
- *
- * Called by: device_stat() in wanmain.c
- *
- * Assumptions:
- *
- * Warnings: This function will degrade the performance
- * of the router, since it uses the mailbox.
- *
- * Return: 0 OK
- * <0 Failed (or busy).
- */
-
-static int update(struct wan_device* wandev)
-{
- volatile sdla_t* card;
- TX25Status* status;
- unsigned long timeout;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- if (test_bit(SEND_CRIT, (void*)&wandev->critical))
- return -EAGAIN;
-
- if (!wandev->dev)
- return -ENODEV;
-
- card = wandev->private;
- status = card->flags;
-
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
- status->imask |= INTR_ON_TIMER;
- timeout = jiffies;
-
- for (;;){
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE)){
- break;
- }
- if (time_after(jiffies, timeout + 1*HZ)){
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
- return 0;
-}
-
-
-/*===================================================================
- * Name: new_if
- *
- * Purpose: To allocate and initialize resources for a
- * new logical channel.
- *
- * Rationale: A new channel can be added dynamically via
- * ioctl call.
- *
- * Description: Allocate a private channel structure, x25_channel_t.
- * Parse the user interface options from wanpipe#.conf
- * configuration file.
- * Bind the private are into the network device private
- * area pointer (dev->priv).
- * Prepare the network device structure for registration.
- *
- * Called by: ROUTER_IFNEW Ioctl call, from wanrouter_ioctl()
- * (wanmain.c)
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok
- * <0 Failed (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- x25_channel_t* chan;
- int err = 0;
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)){
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- if(card->wandev.new_if_cnt++ > 0 && card->u.x.LAPB_hdlc) {
- printk(KERN_INFO "%s: Error: Running LAPB HDLC Mode !\n",
- card->devname);
- printk(KERN_INFO
- "%s: Maximum number of network interfaces must be one !\n",
- card->devname);
- return -EEXIST;
- }
-
- /* allocate and initialize private data */
- chan = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC);
- if (chan == NULL){
- return -ENOMEM;
- }
-
- memset(chan, 0, sizeof(x25_channel_t));
-
- /* Bug Fix: Seg Err on PVC startup
- * It must be here since bind_lcn_to_dev expects
- * it bellow */
- dev->priv = chan;
-
- strcpy(chan->name, conf->name);
- chan->card = card;
- chan->dev = dev;
- chan->common.sk = NULL;
- chan->common.func = NULL;
- chan->common.rw_bind = 0;
- chan->tx_skb = chan->rx_skb = NULL;
-
- /* verify media address */
- if (conf->addr[0] == '@'){ /* SVC */
- chan->common.svc = 1;
- strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
-
- /* Set channel timeouts (default if not specified) */
- chan->idle_timeout = (conf->idle_timeout) ?
- conf->idle_timeout : 90;
- chan->hold_timeout = (conf->hold_timeout) ?
- conf->hold_timeout : 10;
-
- }else if (isdigit(conf->addr[0])){ /* PVC */
- int lcn = dec_to_uint(conf->addr, 0);
-
- if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
- bind_lcn_to_dev (card, dev, lcn);
- }else{
- printk(KERN_ERR
- "%s: PVC %u is out of range on interface %s!\n",
- wandev->name, lcn, chan->name);
- err = -EINVAL;
- }
- }else{
- printk(KERN_ERR
- "%s: invalid media address on interface %s!\n",
- wandev->name, chan->name);
- err = -EINVAL;
- }
-
- if(strcmp(conf->usedby, "WANPIPE") == 0){
- printk(KERN_INFO "%s: Running in WANPIPE mode %s\n",
- wandev->name, chan->name);
- chan->common.usedby = WANPIPE;
- chan->protocol = htons(ETH_P_IP);
-
- }else if(strcmp(conf->usedby, "API") == 0){
- chan->common.usedby = API;
- printk(KERN_INFO "%s: Running in API mode %s\n",
- wandev->name, chan->name);
- chan->protocol = htons(X25_PROT);
- }
-
-
- if (err){
- kfree(chan);
- dev->priv = NULL;
- return err;
- }
-
- chan->enable_IPX = conf->enable_IPX;
-
- if (chan->enable_IPX)
- chan->protocol = htons(ETH_P_IPX);
-
- if (conf->network_number)
- chan->network_number = conf->network_number;
- else
- chan->network_number = 0xDEADBEEF;
-
- /* prepare network device data space for registration */
- strcpy(dev->name,chan->name);
-
- dev->init = &if_init;
-
- init_x25_channel_struct(chan);
-
- return 0;
-}
-
-/*===================================================================
- * Name: del_if(), Remove a logical channel.
- *
- * Purpose: To dynamically remove a logical channel.
- *
- * Rationale: Each logical channel should be dynamically
- * removable. This functin is called by an
- * IOCTL_IFDEL ioctl call or shutdown().
- *
- * Description: Do nothing.
- *
- * Called by: IOCTL_IFDEL : wanrouter_ioctl() from wanmain.c
- * shutdown() from sdlamain.c
- *
- * Assumptions:
- *
- * Warnings:
- *
- * Return: 0 Ok. Void function.
- */
-
-//FIXME Del IF Should be taken out now.
-
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- return 0;
-}
-
-
-/*============================================================
- * Name: wpx_exec
- *
- * Description: Execute adapter interface command.
- * This option is currently dissabled.
- *===========================================================*/
-
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
- return 0;
-}
-
-/*============================================================
- * Name: disable_comm
- *
- * Description: Disable communications during shutdown.
- * Dont check return code because there is
- * nothing we can do about it.
- *
- * Warning: Dev and private areas are gone at this point.
- *===========================================================*/
-
-static void disable_comm(sdla_t* card)
-{
- disable_comm_shutdown(card);
- del_timer(&card->u.x.x25_timer);
- return;
-}
-
-
-/*============================================================
- * Network Device Interface
- *===========================================================*/
-
-/*===================================================================
- * Name: if_init(), Netowrk Interface Initialization
- *
- * Purpose: To initialize a network interface device structure.
- *
- * Rationale: During network interface startup, the if_init
- * is called by the kernel to initialize the
- * netowrk device structure. Thus a driver
- * can customze a network device.
- *
- * Description: Initialize the netowrk device call back
- * routines. This is where we tell the kernel
- * which function to use when it wants to send
- * via our interface.
- * Furthermore, we initialize the device flags,
- * MTU and physical address of the board.
- *
- * Called by: Kernel (/usr/src/linux/net/core/dev.c)
- * (dev->init())
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok : Void function.
- */
-static int if_init(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct wan_device* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* Initialize media-specific parameters */
- dev->type = ARPHRD_PPP; /* ARP h/w type */
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- if (chan->common.usedby == API){
- dev->mtu = X25_CHAN_MTU+sizeof(x25api_hdr_t);
- }else{
- dev->mtu = card->wandev.mtu;
- }
-
- dev->hard_header_len = X25_HRDHDR_SZ; /* media header length */
- dev->addr_len = 2; /* hardware address length */
-
- if (!chan->common.svc){
- *(unsigned short*)dev->dev_addr = htons(chan->common.lcn);
- }
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = (unsigned long)wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 100;
- SET_MODULE_OWNER(dev);
-
- /* FIXME Why are we doing this */
- set_chan_state(dev, WAN_DISCONNECTED);
- return 0;
-}
-
-
-/*===================================================================
- * Name: if_open(), Open/Bring up the Netowrk Interface
- *
- * Purpose: To bring up a network interface.
- *
- * Rationale:
- *
- * Description: Open network interface.
- * o prevent module from unloading by incrementing use count
- * o if link is disconnected then initiate connection
- *
- * Called by: Kernel (/usr/src/linux/net/core/dev.c)
- * (dev->open())
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok
- * <0 Failure: Interface will not come up.
- */
-
-static int if_open(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct timeval tv;
- unsigned long smp_flags;
-
- if (netif_running(dev))
- return -EBUSY;
-
- chan->tq_working = 0;
-
- /* Initialize the workqueue */
- INIT_WORK(&chan->common.wanpipe_work, (void *)x25api_bh, dev);
-
- /* Allocate and initialize BH circular buffer */
- /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
- chan->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
-
- if (chan->bh_head == NULL){
- printk(KERN_INFO "%s: ERROR, failed to allocate memory ! BH_BUFFERS !\n",
- card->devname);
-
- return -ENOBUFS;
- }
- memset(chan->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
- atomic_set(&chan->bh_buff_used, 0);
-
- /* Increment the number of interfaces */
- ++card->u.x.no_dev;
-
- wanpipe_open(card);
-
- /* LAPB protocol only uses one interface, thus
- * start the protocol after it comes up. */
- if (card->u.x.LAPB_hdlc){
- if (card->open_cnt == 1){
- TX25Status* status = card->flags;
- S508_S514_lock(card, &smp_flags);
- x25_set_intr_mode(card, INTR_ON_TIMER);
- status->imask &= ~INTR_ON_TIMER;
- S508_S514_unlock(card, &smp_flags);
- }
- }else{
- /* X25 can have multiple interfaces thus, start the
- * protocol once all interfaces are up */
-
- //FIXME: There is a bug here. If interface is
- //brought down and up, it will try to enable comm.
- if (card->open_cnt == card->u.x.num_of_ch){
-
- S508_S514_lock(card, &smp_flags);
- connect(card);
- S508_S514_unlock(card, &smp_flags);
-
- mod_timer(&card->u.x.x25_timer, jiffies + HZ);
- }
- }
- /* Device is not up until the we are in connected state */
- do_gettimeofday( &tv );
- chan->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-/*===================================================================
- * Name: if_close(), Close/Bring down the Netowrk Interface
- *
- * Purpose: To bring down a network interface.
- *
- * Rationale:
- *
- * Description: Close network interface.
- * o decrement use module use count
- *
- * Called by: Kernel (/usr/src/linux/net/core/dev.c)
- * (dev->close())
- * ifconfig <name> down: will trigger the kernel
- * which will call this function.
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok
- * <0 Failure: Interface will not exit properly.
- */
-static int if_close(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- unsigned long smp_flags;
-
- netif_stop_queue(dev);
-
- if ((chan->common.state == WAN_CONNECTED) ||
- (chan->common.state == WAN_CONNECTING)){
- S508_S514_lock(card, &smp_flags);
- chan_disc(dev);
- S508_S514_unlock(card, &smp_flags);
- }
-
- wanpipe_close(card);
-
- S508_S514_lock(card, &smp_flags);
- if (chan->bh_head){
- int i;
- struct sk_buff *skb;
-
- for (i=0; i<(MAX_BH_BUFF+1); i++){
- skb = ((bh_data_t *)&chan->bh_head[i])->skb;
- if (skb != NULL){
- dev_kfree_skb_any(skb);
- }
- }
- kfree(chan->bh_head);
- chan->bh_head=NULL;
- }
- S508_S514_unlock(card, &smp_flags);
-
- /* If this is the last close, disconnect physical link */
- if (!card->open_cnt){
- S508_S514_lock(card, &smp_flags);
- disconnect(card);
- x25_set_intr_mode(card, 0);
- S508_S514_unlock(card, &smp_flags);
- }
-
- /* Decrement the number of interfaces */
- --card->u.x.no_dev;
- return 0;
-}
-
-/*======================================================================
- * Build media header.
- * o encapsulate packet according to encapsulation type.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol'
- * field of the socket buffer, so that we don't forget it.
- * If encapsulation fails, set skb->protocol to 0 and discard
- * packet later.
- *
- * Return: media header length.
- *======================================================================*/
-
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr,
- unsigned len)
-{
- x25_channel_t* chan = dev->priv;
- int hdr_len = dev->hard_header_len;
-
- skb->protocol = htons(type);
- if (!chan->protocol){
- hdr_len = wanrouter_encapsulate(skb, dev, type);
- if (hdr_len < 0){
- hdr_len = 0;
- skb->protocol = htons(0);
- }
- }
- return hdr_len;
-}
-
-/*===============================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- *==============================================================*/
-
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
- struct net_device *dev = skb->dev;
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++chan->if_send_stat.if_send_tbusy_timeout;
- printk (KERN_INFO "%s: Transmit timed out on %s\n",
- card->devname, dev->name);
- netif_wake_queue (dev);
-}
-
-
-/*=========================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission).
- * o check link state. If link is not up, then drop the packet.
- * o check channel status. If it's down then initiate a call.
- * o pass a packet to corresponding WAN device.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- *
- *========================================================================*/
-
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
- int udp_type;
- unsigned long smp_flags=0;
-
- ++chan->if_send_stat.if_send_entry;
-
- netif_stop_queue(dev);
-
- /* No need to check frame length, since socket code
- * will perform the check for us */
-
- chan->tick_counter = jiffies;
-
- /* Critical region starts here */
- S508_S514_lock(card, &smp_flags);
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
- printk(KERN_INFO "Hit critical in if_send()! %lx\n",card->wandev.critical);
- goto if_send_crit_exit;
- }
-
- udp_type = udp_pkt_type(skb, card);
-
- if(udp_type != UDP_INVALID_TYPE) {
-
- if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, dev, skb,
- chan->common.lcn)) {
-
- status->imask |= INTR_ON_TIMER;
- if (udp_type == UDP_XPIPE_TYPE){
- chan->if_send_stat.if_send_PIPE_request++;
- }
- }
- netif_start_queue(dev);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
- S508_S514_unlock(card, &smp_flags);
- return 0;
- }
-
- if (chan->transmit_length){
- //FIXME: This check doesn't make sense any more
- if (chan->common.state != WAN_CONNECTED){
- chan->transmit_length=0;
- atomic_set(&chan->common.driver_busy,0);
- }else{
- netif_stop_queue(dev);
- ++card->u.x.tx_interrupts_pending;
- status->imask |= INTR_ON_TX_FRAME;
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
- S508_S514_unlock(card, &smp_flags);
- return 1;
- }
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_wan_disconnected;
-
- }else if ( chan->protocol && (chan->protocol != skb->protocol)){
- printk(KERN_INFO
- "%s: unsupported Ethertype 0x%04X on interface %s!\n",
- chan->name, htons(skb->protocol), dev->name);
-
- printk(KERN_INFO "PROTO %Xn", htons(chan->protocol));
- ++chan->ifstats.tx_errors;
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_protocol_error;
-
- }else switch (chan->common.state){
-
- case WAN_DISCONNECTED:
- /* Try to establish connection. If succeded, then start
- * transmission, else drop a packet.
- */
- if (chan->common.usedby == API){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }else{
- if (chan_connect(dev) != 0){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
- }
- /* fall through */
-
- case WAN_CONNECTED:
- if( skb->protocol == htons(ETH_P_IPX)) {
- if(chan->enable_IPX) {
- switch_net_numbers( skb->data,
- chan->network_number, 0);
- } else {
- ++card->wandev.stats.tx_dropped;
- ++chan->ifstats.tx_dropped;
- ++chan->if_send_stat.if_send_protocol_error;
- goto if_send_crit_exit;
- }
- }
- /* We never drop here, if cannot send than, copy
- * a packet into a transmit buffer
- */
- chan_send(dev, skb->data, skb->len, 0);
- break;
-
- default:
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
-
-
-if_send_crit_exit:
-
- dev_kfree_skb_any(skb);
-
- netif_start_queue(dev);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
- S508_S514_unlock(card, &smp_flags);
- return 0;
-}
-
-/*============================================================================
- * Setup so that a frame can be transmitted on the occurrence of a transmit
- * interrupt.
- *===========================================================================*/
-
-static void setup_for_delayed_transmit(struct net_device* dev, void* buf,
- unsigned len)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
-
- ++chan->if_send_stat.if_send_adptr_bfrs_full;
-
- if(chan->transmit_length) {
- printk(KERN_INFO "%s: Error, transmit length set in delayed transmit!\n",
- card->devname);
- return;
- }
-
- if (chan->common.usedby == API){
- if (len > X25_CHAN_MTU+sizeof(x25api_hdr_t)) {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- printk(KERN_INFO "%s: Length is too big for delayed transmit\n",
- card->devname);
- return;
- }
- }else{
- if (len > X25_MAX_DATA) {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- printk(KERN_INFO "%s: Length is too big for delayed transmit\n",
- card->devname);
- return;
- }
- }
-
- chan->transmit_length = len;
- atomic_set(&chan->common.driver_busy,1);
- memcpy(chan->transmit_buffer, buf, len);
-
- ++chan->if_send_stat.if_send_tx_int_enabled;
-
- /* Enable Transmit Interrupt */
- ++card->u.x.tx_interrupts_pending;
- status->imask |= INTR_ON_TX_FRAME;
-}
-
-
-/*===============================================================
- * net_device_stats
- *
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- *
- *==============================================================*/
-static struct net_device_stats *if_stats(struct net_device* dev)
-{
- x25_channel_t *chan = dev->priv;
-
- if(chan == NULL)
- return NULL;
-
- return &chan->ifstats;
-}
-
-
-/*
- * Interrupt Handlers
- */
-
-/*
- * X.25 Interrupt Service Routine.
- */
-
-static void wpx_isr (sdla_t* card)
-{
- TX25Status* status = card->flags;
-
- card->in_isr = 1;
- ++card->statistics.isr_entry;
-
- if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){
- card->in_isr=0;
- status->iflags = 0;
- return;
- }
-
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-
- printk(KERN_INFO "%s: wpx_isr: wandev.critical set to 0x%02lx, int type = 0x%02x\n",
- card->devname, card->wandev.critical, status->iflags);
- card->in_isr = 0;
- status->iflags = 0;
- return;
- }
-
- /* For all interrupts set the critical flag to CRITICAL_RX_INTR.
- * If the if_send routine is called with this flag set it will set
- * the enable transmit flag to 1. (for a delayed interrupt)
- */
- switch (status->iflags){
-
- case RX_INTR_PENDING: /* receive interrupt */
- rx_intr(card);
- break;
-
- case TX_INTR_PENDING: /* transmit interrupt */
- tx_intr(card);
- break;
-
- case MODEM_INTR_PENDING: /* modem status interrupt */
- status_intr(card);
- break;
-
- case X25_ASY_TRANS_INTR_PENDING: /* network event interrupt */
- event_intr(card);
- break;
-
- case TIMER_INTR_PENDING:
- timer_intr(card);
- break;
-
- default: /* unwanted interrupt */
- spur_intr(card);
- }
-
- card->in_isr = 0;
- status->iflags = 0; /* clear interrupt condition */
-}
-
-/*
- * Receive interrupt handler.
- * This routine handles fragmented IP packets using M-bit according to the
- * RFC1356.
- * o map ligical channel number to network interface.
- * o allocate socket buffer or append received packet to the existing one.
- * o if M-bit is reset (i.e. it's the last packet in a sequence) then
- * decapsulate packet and pass socket buffer to the protocol stack.
- *
- * Notes:
- * 1. When allocating a socket buffer, if M-bit is set then more data is
- * coming and we have to allocate buffer for the maximum IP packet size
- * expected on this channel.
- * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
- * socket buffers available) the whole packet sequence must be discarded.
- */
-
-static void rx_intr (sdla_t* card)
-{
- TX25Mbox* rxmb = card->rxmb;
- unsigned lcn = rxmb->cmd.lcn;
- struct net_device* dev = find_channel(card,lcn);
- x25_channel_t* chan;
- struct sk_buff* skb=NULL;
-
- if (dev == NULL){
- /* Invalid channel, discard packet */
- printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
- card->devname, lcn);
- return;
- }
-
- chan = dev->priv;
- chan->i_timeout_sofar = jiffies;
-
-
- /* Copy the data from the board, into an
- * skb buffer
- */
- if (wanpipe_pull_data_in_skb(card,dev,&skb)){
- ++chan->ifstats.rx_dropped;
- ++card->wandev.stats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_no_socket;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- return;
- }
-
- dev->last_rx = jiffies; /* timestamp */
-
-
- /* ------------ API ----------------*/
-
- if (chan->common.usedby == API){
-
- if (bh_enqueue(dev, skb)){
- ++chan->ifstats.rx_dropped;
- ++card->wandev.stats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- dev_kfree_skb_any(skb);
- return;
- }
-
- ++chan->ifstats.rx_packets;
- chan->ifstats.rx_bytes += skb->len;
-
-
- chan->rx_skb = NULL;
- if (!test_and_set_bit(0, &chan->tq_working)){
- wanpipe_queue_work(&chan->common.wanpipe_work);
- }
- return;
- }
-
-
- /* ------------- WANPIPE -------------------*/
-
- /* set rx_skb to NULL so we won't access it later when kernel already owns it */
- chan->rx_skb=NULL;
-
- /* Decapsulate packet, if necessary */
- if (!skb->protocol && !wanrouter_type_trans(skb, dev)){
- /* can't decapsulate packet */
- dev_kfree_skb_any(skb);
- ++chan->ifstats.rx_errors;
- ++chan->ifstats.rx_dropped;
- ++card->wandev.stats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-
- }else{
- if( handle_IPXWAN(skb->data, chan->name,
- chan->enable_IPX, chan->network_number,
- skb->protocol)){
-
- if( chan->enable_IPX ){
- if(chan_send(dev, skb->data, skb->len,0)){
- chan->tx_skb = skb;
- }else{
- dev_kfree_skb_any(skb);
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- }
- }else{
- /* increment IPX packet dropped statistic */
- ++chan->ifstats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- }
- }else{
- skb->mac.raw = skb->data;
- chan->ifstats.rx_bytes += skb->len;
- ++chan->ifstats.rx_packets;
- ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
- netif_rx(skb);
- }
- }
-
- return;
-}
-
-
-static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev,
- struct sk_buff **skb)
-{
- void *bufptr;
- TX25Mbox* rxmb = card->rxmb;
- unsigned len = rxmb->cmd.length; /* packet length */
- unsigned qdm = rxmb->cmd.qdm; /* Q,D and M bits */
- x25_channel_t *chan = dev->priv;
- struct sk_buff *new_skb = *skb;
-
- if (chan->common.usedby == WANPIPE){
- if (chan->drop_sequence){
- if (!(qdm & 0x01)){
- chan->drop_sequence = 0;
- }
- return 1;
- }
- new_skb = chan->rx_skb;
- }else{
- /* Add on the API header to the received
- * data
- */
- len += sizeof(x25api_hdr_t);
- }
-
- if (new_skb == NULL){
- int bufsize;
-
- if (chan->common.usedby == WANPIPE){
- bufsize = (qdm & 0x01) ? dev->mtu : len;
- }else{
- bufsize = len;
- }
-
- /* Allocate new socket buffer */
- new_skb = dev_alloc_skb(bufsize + dev->hard_header_len);
- if (new_skb == NULL){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- chan->drop_sequence = 1; /* set flag */
- ++chan->ifstats.rx_dropped;
- return 1;
- }
- }
-
- if (skb_tailroom(new_skb) < len){
- /* No room for the packet. Call off the whole thing! */
- dev_kfree_skb_any(new_skb);
- if (chan->common.usedby == WANPIPE){
- chan->rx_skb = NULL;
- if (qdm & 0x01){
- chan->drop_sequence = 1;
- }
- }
-
- printk(KERN_INFO "%s: unexpectedly long packet sequence "
- "on interface %s!\n", card->devname, dev->name);
- ++chan->ifstats.rx_length_errors;
- return 1;
- }
-
- bufptr = skb_put(new_skb,len);
-
-
- if (chan->common.usedby == API){
- /* Fill in the x25api header
- */
- x25api_t * api_data = (x25api_t*)bufptr;
- api_data->hdr.qdm = rxmb->cmd.qdm;
- api_data->hdr.cause = rxmb->cmd.cause;
- api_data->hdr.diagn = rxmb->cmd.diagn;
- api_data->hdr.length = rxmb->cmd.length;
- memcpy(api_data->data, rxmb->data, rxmb->cmd.length);
- }else{
- memcpy(bufptr, rxmb->data, len);
- }
-
- new_skb->dev = dev;
-
- if (chan->common.usedby == API){
- new_skb->mac.raw = new_skb->data;
- new_skb->protocol = htons(X25_PROT);
- new_skb->pkt_type = WAN_PACKET_DATA;
- }else{
- new_skb->protocol = chan->protocol;
- chan->rx_skb = new_skb;
- }
-
- /* If qdm bit is set, more data is coming
- * thus, exit and wait for more data before
- * sending the packet up. (Used by router only)
- */
- if ((qdm & 0x01) && (chan->common.usedby == WANPIPE))
- return 1;
-
- *skb = new_skb;
-
- return 0;
-}
-
-/*===============================================================
- * tx_intr
- *
- * Transmit interrupt handler.
- * For each dev, check that there is something to send.
- * If data available, transmit.
- *
- *===============================================================*/
-
-static void tx_intr (sdla_t* card)
-{
- struct net_device *dev;
- TX25Status* status = card->flags;
- unsigned char more_to_tx=0;
- x25_channel_t *chan=NULL;
- int i=0;
-
- if (card->u.x.tx_dev == NULL){
- card->u.x.tx_dev = card->wandev.dev;
- }
-
- dev = card->u.x.tx_dev;
-
- for (;;){
-
- chan = dev->priv;
- if (chan->transmit_length){
- /* Device was set to transmit, check if the TX
- * buffers are available
- */
- if (chan->common.state != WAN_CONNECTED){
- chan->transmit_length = 0;
- atomic_set(&chan->common.driver_busy,0);
- chan->tx_offset=0;
- if (netif_queue_stopped(dev)){
- if (chan->common.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- dev = move_dev_to_next(card,dev);
- break;
- }
-
- if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) &&
- (*card->u.x.hdlc_buf_status & 0x40) ){
- /* Tx buffer available, we can send */
-
- if (tx_intr_send(card, dev)){
- more_to_tx=1;
- }
-
- /* If more than one interface present, move the
- * device pointer to the next interface, so on the
- * next TX interrupt we will try sending from it.
- */
- dev = move_dev_to_next(card,dev);
- break;
- }else{
- /* Tx buffers not available, but device set
- * the TX interrupt. Set more_to_tx and try
- * to transmit for other devices.
- */
- more_to_tx=1;
- dev = move_dev_to_next(card,dev);
- }
-
- }else{
- /* This device was not set to transmit,
- * go to next
- */
- dev = move_dev_to_next(card,dev);
- }
-
- if (++i == card->u.x.no_dev){
- if (!more_to_tx){
- DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n",
- card->devname);
- }
- break;
- }
-
- } //End of FOR
-
- card->u.x.tx_dev = dev;
-
- if (!more_to_tx){
- /* if any other interfaces have transmit interrupts pending, */
- /* do not disable the global transmit interrupt */
- if (!(--card->u.x.tx_interrupts_pending)){
- status->imask &= ~INTR_ON_TX_FRAME;
- }
- }
- return;
-}
-
-/*===============================================================
- * move_dev_to_next
- *
- *
- *===============================================================*/
-
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev)
-{
- if (card->u.x.no_dev != 1){
- if (!*((struct net_device **)dev->priv))
- return card->wandev.dev;
- else
- return *((struct net_device **)dev->priv);
- }
- return dev;
-}
-
-/*===============================================================
- * tx_intr_send
- *
- *
- *===============================================================*/
-
-static int tx_intr_send(sdla_t *card, struct net_device *dev)
-{
- x25_channel_t* chan = dev->priv;
-
- if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){
-
- /* Packet was split up due to its size, do not disable
- * tx_intr
- */
- return 1;
- }
-
- chan->transmit_length=0;
- atomic_set(&chan->common.driver_busy,0);
- chan->tx_offset=0;
-
- /* If we are in API mode, wakeup the
- * sock BH handler, not the NET_BH */
- if (netif_queue_stopped(dev)){
- if (chan->common.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- return 0;
-}
-
-
-/*===============================================================
- * timer_intr
- *
- * Timer interrupt handler.
- * Check who called the timer interrupt and perform
- * action accordingly.
- *
- *===============================================================*/
-
-static void timer_intr (sdla_t *card)
-{
- TX25Status* status = card->flags;
-
- if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){
-
- if (timer_intr_cmd_exec(card) == 0){
- card->u.x.timer_int_enabled &=
- ~TMR_INT_ENABLED_CMD_EXEC;
- }
-
- }else if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) {
-
- if ((*card->u.x.hdlc_buf_status & 0x40) &&
- card->u.x.udp_type == UDP_XPIPE_TYPE){
-
- if(process_udp_mgmt_pkt(card)) {
- card->u.x.timer_int_enabled &=
- ~TMR_INT_ENABLED_UDP_PKT;
- }
- }
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) {
-
- struct net_device *dev = card->u.x.poll_device;
- x25_channel_t *chan = NULL;
-
- if (!dev){
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;
- return;
- }
- chan = dev->priv;
-
- printk(KERN_INFO
- "%s: Closing down Idle link %s on LCN %d\n",
- card->devname,chan->name,chan->common.lcn);
- chan->i_timeout_sofar = jiffies;
- chan_disc(dev);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;
- card->u.x.poll_device=NULL;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) {
-
- wanpipe_set_state(card, WAN_CONNECTED);
- if (card->u.x.LAPB_hdlc){
- struct net_device *dev = card->wandev.dev;
- set_chan_state(dev,WAN_CONNECTED);
- send_delayed_cmd_result(card,dev,card->mbox);
- }
-
- /* 0x8F enable all interrupts */
- x25_set_intr_mode(card, INTR_ON_RX_FRAME|
- INTR_ON_TX_FRAME|
- INTR_ON_MODEM_STATUS_CHANGE|
- //INTR_ON_COMMAND_COMPLETE|
- X25_ASY_TRANS_INTR_PENDING |
- INTR_ON_TIMER |
- DIRECT_RX_INTR_USAGE
- );
-
- status->imask &= ~INTR_ON_TX_FRAME; /* mask Tx interrupts */
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) {
-
- //printk(KERN_INFO "Poll connect, Turning OFF\n");
- disconnect(card);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) {
-
- //printk(KERN_INFO "POll disconnect, trying to connect\n");
- connect(card);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){
-
- if (*card->u.x.hdlc_buf_status & 0x40){
- x25_get_err_stats(card);
- x25_get_stats(card);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- if(!card->u.x.timer_int_enabled){
- //printk(KERN_INFO "Turning Timer Off \n");
- status->imask &= ~INTR_ON_TIMER;
- }
-}
-
-/*====================================================================
- * Modem status interrupt handler.
- *===================================================================*/
-static void status_intr (sdla_t* card)
-{
-
- /* Added to avoid Modem status message flooding */
- static TX25ModemStatus last_stat;
-
- TX25Mbox* mbox = card->mbox;
- TX25ModemStatus *modem_status;
- struct net_device *dev;
- x25_channel_t *chan;
- int err;
-
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_MODEM_STATUS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err){
- x25_error(card, err, X25_READ_MODEM_STATUS, 0);
- }else{
-
- modem_status = (TX25ModemStatus*)mbox->data;
-
- /* Check if the last status was the same
- * if it was, do NOT print message again */
-
- if (last_stat.status != modem_status->status){
-
- printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n",
- card->devname,DCD(modem_status->status),CTS(modem_status->status));
-
- last_stat.status = modem_status->status;
-
- if (card->u.x.oob_on_modem){
-
- mbox->cmd.pktType = mbox->cmd.command;
- mbox->cmd.result = 0x08;
-
- /* Send a OOB to all connected sockets */
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device**)dev->priv)) {
- chan=dev->priv;
- if (chan->common.usedby == API){
- send_oob_msg(card,dev,mbox);
- }
- }
-
- /* The modem OOB message will probably kill the
- * the link. If we don't clear the flag here,
- * a deadlock could occur */
- if (atomic_read(&card->u.x.command_busy)){
- atomic_set(&card->u.x.command_busy,0);
- }
- }
- }
- }
-
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_STATUS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err){
- x25_error(card, err, X25_HDLC_LINK_STATUS, 0);
- }
-
-}
-
-/*====================================================================
- * Network event interrupt handler.
- *===================================================================*/
-static void event_intr (sdla_t* card)
-{
- x25_fetch_events(card);
-}
-
-/*====================================================================
- * Spurious interrupt handler.
- * o print a warning
- * o
- *====================================================================*/
-
-static void spur_intr (sdla_t* card)
-{
- printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
-}
-
-
-/*
- * Background Polling Routines
- */
-
-/*====================================================================
- * Main polling routine.
- * This routine is repeatedly called by the WANPIPE 'thread' to allow for
- * time-dependent housekeeping work.
- *
- * Notes:
- * 1. This routine may be called on interrupt context with all interrupts
- * enabled. Beware!
- *====================================================================*/
-
-static void wpx_poll (sdla_t *card)
-{
- if (!card->wandev.dev){
- goto wpx_poll_exit;
- }
-
- if (card->open_cnt != card->u.x.num_of_ch){
- goto wpx_poll_exit;
- }
-
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- goto wpx_poll_exit;
- }
-
- if (test_bit(SEND_CRIT,&card->wandev.critical)){
- goto wpx_poll_exit;
- }
-
- switch(card->wandev.state){
- case WAN_CONNECTED:
- poll_active(card);
- break;
-
- case WAN_CONNECTING:
- poll_connecting(card);
- break;
-
- case WAN_DISCONNECTED:
- poll_disconnected(card);
- break;
- }
-
-wpx_poll_exit:
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
-}
-
-static void trigger_x25_poll(sdla_t *card)
-{
- schedule_work(&card->u.x.x25_poll_work);
-}
-
-/*====================================================================
- * Handle physical link establishment phase.
- * o if connection timed out, disconnect the link.
- *===================================================================*/
-
-static void poll_connecting (sdla_t* card)
-{
- volatile TX25Status* status = card->flags;
-
- if (status->gflags & X25_HDLC_ABM){
-
- timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_ON);
-
- }else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT){
-
- timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_OFF);
-
- }
-}
-
-/*====================================================================
- * Handle physical link disconnected phase.
- * o if hold-down timeout has expired and there are open interfaces,
- * connect link.
- *===================================================================*/
-
-static void poll_disconnected (sdla_t* card)
-{
- struct net_device *dev;
- x25_channel_t *chan;
- TX25Status* status = card->flags;
-
- if (!card->u.x.LAPB_hdlc && card->open_cnt &&
- ((jiffies - card->state_tick) > HOLD_DOWN_TIME)){
- timer_intr_exec(card, TMR_INT_ENABLED_POLL_DISCONNECT);
- }
-
-
- if ((dev=card->wandev.dev) == NULL)
- return;
-
- if ((chan=dev->priv) == NULL)
- return;
-
- if (chan->common.usedby == API &&
- atomic_read(&chan->common.command) &&
- card->u.x.LAPB_hdlc){
-
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC))
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
- }
-
-}
-
-/*====================================================================
- * Handle active link phase.
- * o fetch X.25 asynchronous events.
- * o kick off transmission on all interfaces.
- *===================================================================*/
-
-static void poll_active (sdla_t* card)
-{
- struct net_device* dev;
- TX25Status* status = card->flags;
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)){
- x25_channel_t* chan = dev->priv;
-
- /* If SVC has been idle long enough, close virtual circuit */
- if ( chan->common.svc &&
- chan->common.state == WAN_CONNECTED &&
- chan->common.usedby == WANPIPE ){
-
- if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout ){
- /* Close svc */
- card->u.x.poll_device=dev;
- timer_intr_exec (card, TMR_INT_ENABLED_POLL_ACTIVE);
- }
- }
-
-#ifdef PRINT_DEBUG
- chan->ifstats.tx_compressed = atomic_read(&chan->common.command);
- chan->ifstats.tx_errors = chan->common.state;
- chan->ifstats.rx_fifo_errors = atomic_read(&card->u.x.command_busy);
- ++chan->ifstats.tx_bytes;
-
- chan->ifstats.rx_fifo_errors=atomic_read(&chan->common.disconnect);
- chan->ifstats.multicast=atomic_read(&chan->bh_buff_used);
- chan->ifstats.rx_length_errors=*card->u.x.hdlc_buf_status;
-#endif
-
- if (chan->common.usedby == API &&
- atomic_read(&chan->common.command) &&
- !card->u.x.LAPB_hdlc){
-
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC))
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
- }
-
- if ((chan->common.usedby == API) &&
- atomic_read(&chan->common.disconnect)){
-
- if (chan->common.state == WAN_DISCONNECTED){
- atomic_set(&chan->common.disconnect,0);
- return;
- }
-
- atomic_set(&chan->common.command,X25_CLEAR_CALL);
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC))
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
- }
- }
-}
-
-static void timer_intr_exec(sdla_t *card, unsigned char TYPE)
-{
- TX25Status* status = card->flags;
- card->u.x.timer_int_enabled |= TYPE;
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
-}
-
-
-/*====================================================================
- * SDLA Firmware-Specific Functions
- *
- * Almost all X.25 commands can unexpetedly fail due to so called 'X.25
- * asynchronous events' such as restart, interrupt, incoming call request,
- * call clear request, etc. They can't be ignored and have to be delt with
- * immediately. To tackle with this problem we execute each interface
- * command in a loop until good return code is received or maximum number
- * of retries is reached. Each interface command returns non-zero return
- * code, an asynchronous event/error handler x25_error() is called.
- *====================================================================*/
-
-/*====================================================================
- * Read X.25 firmware version.
- * Put code version as ASCII string in str.
- *===================================================================*/
-
-static int x25_get_version (sdla_t* card, char* str)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_CODE_VERSION;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- &&
- x25_error(card, err, X25_READ_CODE_VERSION, 0));
-
- if (!err && str)
- {
- int len = mbox->cmd.length;
-
- memcpy(str, mbox->data, len);
- str[len] = '\0';
- }
- return err;
-}
-
-/*====================================================================
- * Configure adapter.
- *===================================================================*/
-
-static int x25_configure (sdla_t* card, TX25Config* conf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
- mbox->cmd.length = sizeof(TX25Config);
- mbox->cmd.command = X25_SET_CONFIGURATION;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
- return err;
-}
-
-/*====================================================================
- * Configure adapter for HDLC only.
- *===================================================================*/
-
-static int hdlc_configure (sdla_t* card, TX25Config* conf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
- mbox->cmd.length = sizeof(TX25Config);
- mbox->cmd.command = X25_HDLC_SET_CONFIG;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
-
- return err;
-}
-
-static int set_hdlc_level (sdla_t* card)
-{
-
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = SET_PROTOCOL_LEVEL;
- mbox->cmd.length = 1;
- mbox->data[0] = HDLC_LEVEL; //| DO_HDLC_LEVEL_ERROR_CHECKING;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, SET_PROTOCOL_LEVEL, 0));
-
- return err;
-}
-
-
-
-/*====================================================================
- * Get communications error statistics.
- *====================================================================*/
-
-static int x25_get_err_stats (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_READ_COMM_ERR;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0));
-
- if (!err)
- {
- THdlcCommErr* stats = (void*)mbox->data;
-
- card->wandev.stats.rx_over_errors = stats->rxOverrun;
- card->wandev.stats.rx_crc_errors = stats->rxBadCrc;
- card->wandev.stats.rx_missed_errors = stats->rxAborted;
- card->wandev.stats.tx_aborted_errors = stats->txAborted;
- }
- return err;
-}
-
-/*====================================================================
- * Get protocol statistics.
- *===================================================================*/
-
-static int x25_get_stats (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_STATISTICS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0)) ;
-
- if (!err)
- {
- TX25Stats* stats = (void*)mbox->data;
-
- card->wandev.stats.rx_packets = stats->rxData;
- card->wandev.stats.tx_packets = stats->txData;
- }
- return err;
-}
-
-/*====================================================================
- * Close HDLC link.
- *===================================================================*/
-
-static int x25_close_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_CLOSE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0));
-
- return err;
-}
-
-
-/*====================================================================
- * Open HDLC link.
- *===================================================================*/
-
-static int x25_open_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_OPEN;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0));
-
- return err;
-}
-
-/*=====================================================================
- * Setup HDLC link.
- *====================================================================*/
-static int x25_setup_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_SETUP;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0));
-
- return err;
-}
-
-/*====================================================================
- * Set (raise/drop) DTR.
- *===================================================================*/
-
-static int x25_set_dtr (sdla_t* card, int dtr)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->data[0] = 0;
- mbox->data[2] = 0;
- mbox->data[1] = dtr ? 0x02 : 0x01;
- mbox->cmd.length = 3;
- mbox->cmd.command = X25_SET_GLOBAL_VARS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0));
-
- return err;
-}
-
-/*====================================================================
- * Set interrupt mode.
- *===================================================================*/
-
-static int x25_set_intr_mode (sdla_t* card, int mode)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->data[0] = mode;
- if (card->hw.fwid == SFID_X25_508){
- mbox->data[1] = card->hw.irq;
- mbox->data[2] = 2;
- mbox->cmd.length = 3;
- }else {
- mbox->cmd.length = 1;
- }
- mbox->cmd.command = X25_SET_INTERRUPT_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0));
-
- return err;
-}
-
-/*====================================================================
- * Read X.25 channel configuration.
- *===================================================================*/
-
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int lcn = chan->common.lcn;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.command = X25_READ_CHANNEL_CONFIG;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn));
-
- if (!err)
- {
- TX25Status* status = card->flags;
-
- /* calculate an offset into the array of status bytes */
- if (card->u.x.hi_svc <= X25_MAX_CHAN){
-
- chan->ch_idx = lcn - 1;
-
- }else{
- int offset;
-
- /* FIX: Apr 14 2000 : Nenad Corbic
- * The data field was being compared to 0x1F using
- * '&&' instead of '&'.
- * This caused X25API to fail for LCNs greater than 255.
- */
- switch (mbox->data[0] & 0x1F)
- {
- case 0x01:
- offset = status->pvc_map; break;
- case 0x03:
- offset = status->icc_map; break;
- case 0x07:
- offset = status->twc_map; break;
- case 0x0B:
- offset = status->ogc_map; break;
- default:
- offset = 0;
- }
- chan->ch_idx = lcn - 1 - offset;
- }
-
- /* get actual transmit packet size on this channel */
- switch(mbox->data[1] & 0x38)
- {
- case 0x00:
- chan->tx_pkt_size = 16;
- break;
- case 0x08:
- chan->tx_pkt_size = 32;
- break;
- case 0x10:
- chan->tx_pkt_size = 64;
- break;
- case 0x18:
- chan->tx_pkt_size = 128;
- break;
- case 0x20:
- chan->tx_pkt_size = 256;
- break;
- case 0x28:
- chan->tx_pkt_size = 512;
- break;
- case 0x30:
- chan->tx_pkt_size = 1024;
- break;
- }
- if (card->u.x.logging)
- printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n",
- card->devname, lcn, chan->tx_pkt_size);
- }
- return err;
-}
-
-/*====================================================================
- * Place X.25 call.
- *====================================================================*/
-
-static int x25_place_call (sdla_t* card, x25_channel_t* chan)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
- char str[64];
-
-
- if (chan->protocol == htons(ETH_P_IP)){
- sprintf(str, "-d%s -uCC", chan->addr);
-
- }else if (chan->protocol == htons(ETH_P_IPX)){
- sprintf(str, "-d%s -u800000008137", chan->addr);
-
- }
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- strcpy(mbox->data, str);
- mbox->cmd.length = strlen(str);
- mbox->cmd.command = X25_PLACE_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0));
-
- if (!err){
- bind_lcn_to_dev (card, chan->dev, mbox->cmd.lcn);
- }
- return err;
-}
-
-/*====================================================================
- * Accept X.25 call.
- *====================================================================*/
-
-static int x25_accept_call (sdla_t* card, int lcn, int qdm)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.qdm = qdm;
- mbox->cmd.command = X25_ACCEPT_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn));
-
- return err;
-}
-
-/*====================================================================
- * Clear X.25 call.
- *====================================================================*/
-
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.cause = cause;
- mbox->cmd.diagn = diagn;
- mbox->cmd.command = X25_CLEAR_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn));
-
- return err;
-}
-
-/*====================================================================
- * Send X.25 data packet.
- *====================================================================*/
-
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
- unsigned char cmd;
-
- if (card->u.x.LAPB_hdlc)
- cmd = X25_HDLC_WRITE;
- else
- cmd = X25_WRITE;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, buf, len);
- mbox->cmd.length = len;
- mbox->cmd.lcn = lcn;
-
- if (card->u.x.LAPB_hdlc){
- mbox->cmd.pf = qdm;
- }else{
- mbox->cmd.qdm = qdm;
- }
-
- mbox->cmd.command = cmd;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, cmd , lcn));
-
-
- /* If buffers are busy the return code for LAPB HDLC is
- * 1. The above functions are looking for return code
- * of X25RES_NOT_READY if busy. */
-
- if (card->u.x.LAPB_hdlc && err == 1){
- err = X25RES_NOT_READY;
- }
-
- return err;
-}
-
-/*====================================================================
- * Fetch X.25 asynchronous events.
- *===================================================================*/
-
-static int x25_fetch_events (sdla_t* card)
-{
- TX25Status* status = card->flags;
- TX25Mbox* mbox = card->mbox;
- int err = 0;
-
- if (status->gflags & 0x20)
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_IS_DATA_AVAILABLE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err) x25_error(card, err, X25_IS_DATA_AVAILABLE, 0);
- }
- return err;
-}
-
-/*====================================================================
- * X.25 asynchronous event/error handler.
- * This routine is called each time interface command returns
- * non-zero return code to handle X.25 asynchronous events and
- * common errors. Return non-zero to repeat command or zero to
- * cancel it.
- *
- * Notes:
- * 1. This function may be called recursively, as handling some of the
- * asynchronous events (e.g. call request) requires execution of the
- * interface command(s) that, in turn, may also return asynchronous
- * events. To avoid re-entrancy problems we copy mailbox to dynamically
- * allocated memory before processing events.
- *====================================================================*/
-
-static int x25_error (sdla_t* card, int err, int cmd, int lcn)
-{
- int retry = 1;
- unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length;
- TX25Mbox* mb;
-
- mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC);
- if (mb == NULL)
- {
- printk(KERN_ERR "%s: x25_error() out of memory!\n",
- card->devname);
- return 0;
- }
- memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen);
- switch (err){
-
- case X25RES_ASYNC_PACKET: /* X.25 asynchronous packet was received */
-
- mb->data[dlen] = '\0';
-
- switch (mb->cmd.pktType & 0x7F){
-
- case ASE_CALL_RQST: /* incoming call */
- retry = incoming_call(card, cmd, lcn, mb);
- break;
-
- case ASE_CALL_ACCEPTED: /* connected */
- retry = call_accepted(card, cmd, lcn, mb);
- break;
-
- case ASE_CLEAR_RQST: /* call clear request */
- retry = call_cleared(card, cmd, lcn, mb);
- break;
-
- case ASE_RESET_RQST: /* reset request */
- printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn, mb->cmd.cause,
- mb->cmd.diagn);
- api_oob_event (card,mb);
- break;
-
- case ASE_RESTART_RQST: /* restart request */
- retry = restart_event(card, cmd, lcn, mb);
- break;
-
- case ASE_CLEAR_CONFRM:
- if (clear_confirm_event (card,mb))
- break;
-
- /* I use the goto statement here so if
- * somebody inserts code between the
- * case and default, we will not have
- * ghost problems */
-
- goto dflt_1;
-
- default:
-dflt_1:
- printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.pktType,
- mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn);
- }
- break;
-
- case X25RES_PROTO_VIOLATION: /* X.25 protocol violation indication */
-
- /* Bug Fix: Mar 14 2000
- * The Protocol violation error conditions were
- * not handled previously */
-
- switch (mb->cmd.pktType & 0x7F){
-
- case PVE_CLEAR_RQST: /* Clear request */
- retry = call_cleared(card, cmd, lcn, mb);
- break;
-
- case PVE_RESET_RQST: /* Reset request */
- printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn, mb->cmd.cause,
- mb->cmd.diagn);
- api_oob_event (card,mb);
- break;
-
- case PVE_RESTART_RQST: /* Restart request */
- retry = restart_event(card, cmd, lcn, mb);
- break;
-
- default :
- printk(KERN_INFO
- "%s: X.25 protocol violation on LCN %d! "
- "Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn,
- mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn);
- api_oob_event(card,mb);
- }
- break;
-
- case 0x42: /* X.25 timeout */
- retry = timeout_event(card, cmd, lcn, mb);
- break;
-
- case 0x43: /* X.25 retry limit exceeded */
- printk(KERN_INFO
- "%s: exceeded X.25 retry limit on LCN %d! "
- "Packet:0x%02X Diagn:0x%02X\n", card->devname,
- mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn)
- ;
- break;
-
- case 0x08: /* modem failure */
-#ifndef MODEM_NOT_LOG
- printk(KERN_INFO "%s: modem failure!\n", card->devname);
-#endif /* MODEM_NOT_LOG */
- api_oob_event(card,mb);
- break;
-
- case 0x09: /* N2 retry limit */
- printk(KERN_INFO "%s: exceeded HDLC retry limit!\n",
- card->devname);
- api_oob_event(card,mb);
- break;
-
- case 0x06: /* unnumbered frame was received while in ABM */
- printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n",
- card->devname, mb->data[0]);
- api_oob_event(card,mb);
- break;
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd)
- ;
- retry = 0; /* abort command */
- break;
-
- case X25RES_NOT_READY:
- retry = 1;
- break;
-
- case 0x01:
- if (card->u.x.LAPB_hdlc)
- break;
-
- if (mb->cmd.command == 0x16)
- break;
- /* I use the goto statement here so if
- * somebody inserts code between the
- * case and default, we will not have
- * ghost problems */
- goto dflt_2;
-
- default:
-dflt_2:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X! Lcn %i\n",
- card->devname, cmd, err, mb->cmd.lcn)
- ;
- retry = 0; /* abort command */
- }
- kfree(mb);
- return retry;
-}
-
-/*====================================================================
- * X.25 Asynchronous Event Handlers
- * These functions are called by the x25_error() and should return 0, if
- * the command resulting in the asynchronous event must be aborted.
- *====================================================================*/
-
-
-
-/*====================================================================
- *Handle X.25 incoming call request.
- * RFC 1356 establishes the following rules:
- * 1. The first octet in the Call User Data (CUD) field of the call
- * request packet contains NLPID identifying protocol encapsulation
- * 2. Calls MUST NOT be accepted unless router supports requested
- * protocol encapsulation.
- * 3. A diagnostic code 249 defined by ISO/IEC 8208 may be used
- * when clearing a call because protocol encapsulation is not
- * supported.
- * 4. If an incoming call is received while a call request is
- * pending (i.e. call collision has occurred), the incoming call
- * shall be rejected and call request shall be retried.
- *====================================================================*/
-
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- struct wan_device* wandev = &card->wandev;
- int new_lcn = mb->cmd.lcn;
- struct net_device* dev = get_dev_by_lcn(wandev, new_lcn);
- x25_channel_t* chan = NULL;
- int accept = 0; /* set to '1' if o.k. to accept call */
- unsigned int user_data;
- x25_call_info_t* info;
-
- /* Make sure there is no call collision */
- if (dev != NULL)
- {
- printk(KERN_INFO
- "%s: X.25 incoming call collision on LCN %d!\n",
- card->devname, new_lcn);
-
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- /* Make sure D bit is not set in call request */
-//FIXME: THIS IS NOT TURE !!!! TAKE IT OUT
-// if (mb->cmd.qdm & 0x02)
-// {
-// printk(KERN_INFO
-// "%s: X.25 incoming call on LCN %d with D-bit set!\n",
-// card->devname, new_lcn);
-//
-// x25_clear_call(card, new_lcn, 0, 0);
-// return 1;
-// }
-
- /* Parse call request data */
- info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC);
- if (info == NULL)
- {
- printk(KERN_ERR
- "%s: not enough memory to parse X.25 incoming call "
- "on LCN %d!\n", card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- parse_call_info(mb->data, info);
-
- if (card->u.x.logging)
- printk(KERN_INFO "\n%s: X.25 incoming call on LCN %d!\n",
- card->devname, new_lcn);
-
- /* Conver the first two ASCII characters into an
- * interger. Used to check the incoming protocol
- */
- user_data = hex_to_uint(info->user,2);
-
- /* Find available channel */
- for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) {
- chan = dev->priv;
-
- if (chan->common.usedby == API)
- continue;
-
- if (!chan->common.svc || (chan->common.state != WAN_DISCONNECTED))
- continue;
-
- if (user_data == NLPID_IP && chan->protocol != htons(ETH_P_IP)){
- printk(KERN_INFO "IP packet but configured for IPX : %x, %x\n",
- htons(chan->protocol), info->user[0]);
- continue;
- }
-
- if (user_data == NLPID_SNAP && chan->protocol != htons(ETH_P_IPX)){
- printk(KERN_INFO "IPX packet but configured for IP: %x\n",
- htons(chan->protocol));
- continue;
- }
- if (strcmp(info->src, chan->addr) == 0)
- break;
-
- /* If just an '@' is specified, accept all incoming calls */
- if (strcmp(chan->addr, "") == 0)
- break;
- }
-
- if (dev == NULL){
-
- /* If the call is not for any WANPIPE interfaces
- * check to see if there is an API listening queue
- * waiting for data. If there is send the packet
- * up the stack.
- */
- if (card->sk != NULL && card->func != NULL){
- if (api_incoming_call(card,mb,new_lcn)){
- x25_clear_call(card, new_lcn, 0, 0);
- }
- accept = 0;
- }else{
- printk(KERN_INFO "%s: no channels available!\n",
- card->devname);
-
- x25_clear_call(card, new_lcn, 0, 0);
- }
-
- }else if (info->nuser == 0){
-
- printk(KERN_INFO
- "%s: no user data in incoming call on LCN %d!\n",
- card->devname, new_lcn)
- ;
- x25_clear_call(card, new_lcn, 0, 0);
-
- }else switch (info->user[0]){
-
- case 0: /* multiplexed */
- chan->protocol = htons(0);
- accept = 1;
- break;
-
- case NLPID_IP: /* IP datagrams */
- accept = 1;
- break;
-
- case NLPID_SNAP: /* IPX datagrams */
- accept = 1;
- break;
-
- default:
- printk(KERN_INFO
- "%s: unsupported NLPID 0x%02X in incoming call "
- "on LCN %d!\n", card->devname, info->user[0], new_lcn);
- x25_clear_call(card, new_lcn, 0, 249);
- }
-
- if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK)){
-
- bind_lcn_to_dev (card, chan->dev, new_lcn);
-
- if (x25_get_chan_conf(card, chan) == CMD_OK)
- set_chan_state(dev, WAN_CONNECTED);
- else
- x25_clear_call(card, new_lcn, 0, 0);
- }
- kfree(info);
- return 1;
-}
-
-/*====================================================================
- * Handle accepted call.
- *====================================================================*/
-
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
- struct net_device* dev = find_channel(card, new_lcn);
- x25_channel_t* chan;
-
- if (dev == NULL){
- printk(KERN_INFO
- "%s: clearing orphaned connection on LCN %d!\n",
- card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- if (card->u.x.logging)
- printk(KERN_INFO "%s: X.25 call accepted on Dev %s and LCN %d!\n",
- card->devname, dev->name, new_lcn);
-
- /* Get channel configuration and notify router */
- chan = dev->priv;
- if (x25_get_chan_conf(card, chan) != CMD_OK)
- {
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- set_chan_state(dev, WAN_CONNECTED);
-
- if (chan->common.usedby == API){
- send_delayed_cmd_result(card,dev,mb);
- bind_lcn_to_dev (card, dev, new_lcn);
- }
-
- return 1;
-}
-
-/*====================================================================
- * Handle cleared call.
- *====================================================================*/
-
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
- struct net_device* dev = find_channel(card, new_lcn);
- x25_channel_t *chan;
- unsigned char old_state;
-
- if (card->u.x.logging){
- printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X "
- "Diagn:0x%02X\n",
- card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn);
- }
-
- if (dev == NULL){
- printk(KERN_INFO "%s: X.25 clear request : No device for clear\n",
- card->devname);
- return 1;
- }
-
- chan=dev->priv;
-
- old_state = chan->common.state;
-
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
-
- switch (old_state){
-
- case WAN_CONNECTING:
- send_delayed_cmd_result(card,dev,mb);
- break;
- case WAN_CONNECTED:
- send_oob_msg(card,dev,mb);
- break;
- }
- }
-
- return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1;
-}
-
-/*====================================================================
- * Handle X.25 restart event.
- *====================================================================*/
-
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- struct wan_device* wandev = &card->wandev;
- struct net_device* dev;
- x25_channel_t *chan;
- unsigned char old_state;
-
- printk(KERN_INFO
- "%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.cause, mb->cmd.diagn);
-
- /* down all logical channels */
- for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) {
- chan=dev->priv;
- old_state = chan->common.state;
-
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
- switch (old_state){
-
- case WAN_CONNECTING:
- send_delayed_cmd_result(card,dev,mb);
- break;
- case WAN_CONNECTED:
- send_oob_msg(card,dev,mb);
- break;
- }
- }
- }
- return (cmd == X25_WRITE) ? 0 : 1;
-}
-
-/*====================================================================
- * Handle timeout event.
- *====================================================================*/
-
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
-
- if (mb->cmd.pktType == 0x05) /* call request time out */
- {
- struct net_device* dev = find_channel(card,new_lcn);
-
- printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n",
- card->devname, new_lcn);
-
- if (dev){
- x25_channel_t *chan = dev->priv;
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
- send_delayed_cmd_result(card,dev,card->mbox);
- }
- }
- }else{
- printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n",
- card->devname, mb->cmd.pktType, new_lcn);
- }
- return 1;
-}
-
-/*
- * Miscellaneous
- */
-
-/*====================================================================
- * Establish physical connection.
- * o open HDLC and raise DTR
- *
- * Return: 0 connection established
- * 1 connection is in progress
- * <0 error
- *===================================================================*/
-
-static int connect (sdla_t* card)
-{
- TX25Status* status = card->flags;
-
- if (x25_open_hdlc(card) || x25_setup_hdlc(card))
- return -EIO;
-
- wanpipe_set_state(card, WAN_CONNECTING);
-
- x25_set_intr_mode(card, INTR_ON_TIMER);
- status->imask &= ~INTR_ON_TIMER;
-
- return 1;
-}
-
-/*
- * Tear down physical connection.
- * o close HDLC link
- * o drop DTR
- *
- * Return: 0
- * <0 error
- */
-
-static int disconnect (sdla_t* card)
-{
- wanpipe_set_state(card, WAN_DISCONNECTED);
- x25_set_intr_mode(card, INTR_ON_TIMER); /* disable all interrupt except timer */
- x25_close_hdlc(card); /* close HDLC link */
- x25_set_dtr(card, 0); /* drop DTR */
- return 0;
-}
-
-/*
- * Find network device by its channel number.
- */
-
-static struct net_device* get_dev_by_lcn(struct wan_device* wandev,
- unsigned lcn)
-{
- struct net_device* dev;
-
- for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv))
- if (((x25_channel_t*)dev->priv)->common.lcn == lcn)
- break;
- return dev;
-}
-
-/*
- * Initiate connection on the logical channel.
- * o for PVC we just get channel configuration
- * o for SVCs place an X.25 call
- *
- * Return: 0 connected
- * >0 connection in progress
- * <0 failure
- */
-
-static int chan_connect(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->common.svc && chan->common.usedby == WANPIPE){
- if (!chan->addr[0]){
- printk(KERN_INFO "%s: No Destination Address\n",
- card->devname);
- return -EINVAL; /* no destination address */
- }
- printk(KERN_INFO "%s: placing X.25 call to %s ...\n",
- card->devname, chan->addr);
-
- if (x25_place_call(card, chan) != CMD_OK)
- return -EIO;
-
- set_chan_state(dev, WAN_CONNECTING);
- return 1;
- }else{
- if (x25_get_chan_conf(card, chan) != CMD_OK)
- return -EIO;
-
- set_chan_state(dev, WAN_CONNECTED);
- }
- return 0;
-}
-
-/*
- * Disconnect logical channel.
- * o if SVC then clear X.25 call
- */
-
-static int chan_disc(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
-
- if (chan->common.svc){
- x25_clear_call(chan->card, chan->common.lcn, 0, 0);
-
- /* For API we disconnect on clear
- * confirmation.
- */
- if (chan->common.usedby == API)
- return 0;
- }
-
- set_chan_state(dev, WAN_DISCONNECTED);
-
- return 0;
-}
-
-/*
- * Set logical channel state.
- */
-
-static void set_chan_state(struct net_device* dev, int state)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (chan->common.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- if (card->u.x.logging){
- printk (KERN_INFO
- "%s: interface %s connected, lcn %i !\n",
- card->devname, dev->name,chan->common.lcn);
- }
- *(unsigned short*)dev->dev_addr = htons(chan->common.lcn);
- chan->i_timeout_sofar = jiffies;
-
- /* LAPB is PVC Based */
- if (card->u.x.LAPB_hdlc)
- chan->common.svc=0;
- break;
-
- case WAN_CONNECTING:
- if (card->u.x.logging){
- printk (KERN_INFO
- "%s: interface %s connecting, lcn %i ...\n",
- card->devname, dev->name, chan->common.lcn);
- }
- break;
-
- case WAN_DISCONNECTED:
- if (card->u.x.logging){
- printk (KERN_INFO
- "%s: interface %s disconnected, lcn %i !\n",
- card->devname, dev->name,chan->common.lcn);
- }
- atomic_set(&chan->common.disconnect,0);
-
- if (chan->common.svc) {
- *(unsigned short*)dev->dev_addr = 0;
- card->u.x.svc_to_dev_map[(chan->common.lcn%X25_MAX_CHAN)]=NULL;
- chan->common.lcn = 0;
- }
-
- if (chan->transmit_length){
- chan->transmit_length=0;
- atomic_set(&chan->common.driver_busy,0);
- chan->tx_offset=0;
- if (netif_queue_stopped(dev)){
- netif_wake_queue(dev);
- }
- }
- atomic_set(&chan->common.command,0);
- break;
-
- case WAN_DISCONNECTING:
- if (card->u.x.logging){
- printk (KERN_INFO
- "\n%s: interface %s disconnecting, lcn %i ...\n",
- card->devname, dev->name,chan->common.lcn);
- }
- atomic_set(&chan->common.disconnect,0);
- break;
- }
- chan->common.state = state;
- }
- chan->state_tick = jiffies;
- restore_flags(flags);
-}
-
-/*
- * Send packet on a logical channel.
- * When this function is called, tx_skb field of the channel data
- * space points to the transmit socket buffer. When transmission
- * is complete, release socket buffer and reset 'tbusy' flag.
- *
- * Return: 0 - transmission complete
- * 1 - busy
- *
- * Notes:
- * 1. If packet length is greater than MTU for this channel, we'll fragment
- * the packet into 'complete sequence' using M-bit.
- * 2. When transmission is complete, an event notification should be issued
- * to the router.
- */
-
-static int chan_send(struct net_device* dev, void* buff, unsigned data_len,
- unsigned char tx_intr)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
- unsigned len=0, qdm=0, res=0, orig_len = 0;
- void *data;
-
- /* Check to see if channel is ready */
- if ((!(status->cflags[chan->ch_idx] & 0x40) && !card->u.x.LAPB_hdlc) ||
- !(*card->u.x.hdlc_buf_status & 0x40)){
-
- if (!tx_intr){
- setup_for_delayed_transmit (dev, buff, data_len);
- return 0;
- }else{
- /* By returning 0 to tx_intr the packet will be dropped */
- ++card->wandev.stats.tx_dropped;
- ++chan->ifstats.tx_dropped;
- printk(KERN_INFO "%s: ERROR, Tx intr could not send, dropping %s:\n",
- card->devname,dev->name);
- ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
- return 0;
- }
- }
-
- if (chan->common.usedby == API){
- /* Remove the API Header */
- x25api_hdr_t *api_data = (x25api_hdr_t *)buff;
-
- /* Set the qdm bits from the packet header
- * User has the option to set the qdm bits
- */
- qdm = api_data->qdm;
-
- orig_len = len = data_len - sizeof(x25api_hdr_t);
- data = (unsigned char*)buff + sizeof(x25api_hdr_t);
- }else{
- data = buff;
- orig_len = len = data_len;
- }
-
- if (tx_intr){
- /* We are in tx_intr, minus the tx_offset from
- * the total length. The tx_offset part of the
- * data has already been sent. Also, move the
- * data pointer to proper offset location.
- */
- len -= chan->tx_offset;
- data = (unsigned char*)data + chan->tx_offset;
- }
-
- /* Check if the packet length is greater than MTU
- * If YES: Cut the len to MTU and set the M bit
- */
- if (len > chan->tx_pkt_size && !card->u.x.LAPB_hdlc){
- len = chan->tx_pkt_size;
- qdm |= M_BIT;
- }
-
-
- /* Pass only first three bits of the qdm byte to the send
- * routine. In case user sets any other bit which might
- * cause errors.
- */
-
- switch(x25_send(card, chan->common.lcn, (qdm&0x07), len, data)){
- case 0x00: /* success */
- chan->i_timeout_sofar = jiffies;
-
- dev->trans_start=jiffies;
-
- if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){
- if (!tx_intr){
- /* The M bit was set, which means that part of the
- * packet has been sent. Copy the packet into a buffer
- * and set the offset to len, so on next tx_inter
- * the packet will be sent using the below offset.
- */
- chan->tx_offset += len;
-
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += len;
-
- if (chan->tx_offset < orig_len){
- setup_for_delayed_transmit (dev, buff, data_len);
- }
- res=0;
- }else{
- /* We are already in tx_inter, thus data is already
- * in the buffer. Update the offset and wait for
- * next tx_intr. We add on to the offset, since data can
- * be X number of times larger than max data size.
- */
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += len;
-
- ++chan->if_send_stat.if_send_bfr_passed_to_adptr;
- chan->tx_offset += len;
-
- /* The user can set the qdm bit as well.
- * If the entire packet was sent and qdm is still
- * set, than it's the user who has set the M bit. In that,
- * case indicate that the packet was send by returning
- * 0 and wait for a new packet. Otherwise, wait for next
- * tx interrupt to send the rest of the packet */
-
- if (chan->tx_offset < orig_len){
- res=1;
- }else{
- res=0;
- }
- }
- }else{
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += len;
- ++chan->if_send_stat.if_send_bfr_passed_to_adptr;
- res=0;
- }
- break;
-
- case 0x33: /* Tx busy */
- if (tx_intr){
- printk(KERN_INFO "%s: Tx_intr: Big Error dropping packet %s\n",
- card->devname,dev->name);
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
- res=0;
- }else{
- DBG_PRINTK(KERN_INFO
- "%s: Send: Big Error should have tx: storring %s\n",
- card->devname,dev->name);
- setup_for_delayed_transmit (dev, buff, data_len);
- res=1;
- }
- break;
-
- default: /* failure */
- ++chan->ifstats.tx_errors;
- if (tx_intr){
- printk(KERN_INFO "%s: Tx_intr: Failure to send, dropping %s\n",
- card->devname,dev->name);
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
- res=0;
- }else{
- DBG_PRINTK(KERN_INFO "%s: Send: Failure to send !!!, storing %s\n",
- card->devname,dev->name);
- setup_for_delayed_transmit (dev, buff, data_len);
- res=1;
- }
- break;
- }
- return res;
-}
-
-
-/*
- * Parse X.25 call request data and fill x25_call_info_t structure.
- */
-
-static void parse_call_info (unsigned char* str, x25_call_info_t* info)
-{
- memset(info, 0, sizeof(x25_call_info_t));
- for (; *str; ++str)
- {
- int i;
- unsigned char ch;
-
- if (*str == '-') switch (str[1]) {
-
- /* Take minus 2 off the maximum size so that
- * last byte is 0. This way we can use string
- * manipulaton functions on call information.
- */
-
- case 'd': /* destination address */
- for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->dest[i] = ch;
- }
- break;
-
- case 's': /* source address */
- for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->src[i] = ch;
- }
- break;
-
- case 'u': /* user data */
- for (i = 0; i < (MAX_X25_DATA_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->user[i] = ch;
- }
- info->nuser = i;
- break;
-
- case 'f': /* facilities */
- for (i = 0; i < (MAX_X25_FACL_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->facil[i] = ch;
- }
- info->nfacil = i;
- break;
- }
- }
-}
-
-/*
- * Convert line speed in bps to a number used by S502 code.
- */
-
-static unsigned char bps_to_speed_code (unsigned long bps)
-{
- unsigned char number;
-
- if (bps <= 1200) number = 0x01;
- else if (bps <= 2400) number = 0x02;
- else if (bps <= 4800) number = 0x03;
- else if (bps <= 9600) number = 0x04;
- else if (bps <= 19200) number = 0x05;
- else if (bps <= 38400) number = 0x06;
- else if (bps <= 45000) number = 0x07;
- else if (bps <= 56000) number = 0x08;
- else if (bps <= 64000) number = 0x09;
- else if (bps <= 74000) number = 0x0A;
- else if (bps <= 112000) number = 0x0B;
- else if (bps <= 128000) number = 0x0C;
- else number = 0x0D;
-
- return number;
-}
-
-/*
- * Convert decimal string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are converted.
- */
-
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
- unsigned val;
-
- if (!len)
- len = strlen(str);
-
- for (val = 0; len && isdigit(*str); ++str, --len)
- val = (val * 10) + (*str - (unsigned)'0');
-
- return val;
-}
-
-/*
- * Convert hex string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are conferted.
- */
-
-static unsigned int hex_to_uint (unsigned char* str, int len)
-{
- unsigned val, ch;
-
- if (!len)
- len = strlen(str);
-
- for (val = 0; len; ++str, --len)
- {
- ch = *str;
- if (isdigit(ch))
- val = (val << 4) + (ch - (unsigned)'0');
- else if (isxdigit(ch))
- val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
- else break;
- }
- return val;
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
- int i;
-
- if( proto == ETH_P_IPX) {
- /* It's an IPX packet */
- if(!enable_IPX) {
- /* Return 1 so we don't pass it up the stack. */
- return 1;
- }
- } else {
- /* It's not IPX so pass it up the stack.*/
- return 0;
- }
-
- if( sendpacket[16] == 0x90 &&
- sendpacket[17] == 0x04)
- {
- /* It's IPXWAN */
-
- if( sendpacket[2] == 0x02 &&
- sendpacket[34] == 0x00)
- {
- /* It's a timer request packet */
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
- /* Go through the routing options and answer no to every
- * option except Unnumbered RIP/SAP
- */
- for(i = 41; sendpacket[i] == 0x00; i += 5)
- {
- /* 0x02 is the option for Unnumbered RIP/SAP */
- if( sendpacket[i + 4] != 0x02)
- {
- sendpacket[i + 1] = 0;
- }
- }
-
- /* Skip over the extended Node ID option */
- if( sendpacket[i] == 0x04 )
- {
- i += 8;
- }
-
- /* We also want to turn off all header compression opt. */
- for(; sendpacket[i] == 0x80 ;)
- {
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- /* Set the packet type to timer response */
- sendpacket[34] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
- }
- else if( sendpacket[34] == 0x02 )
- {
- /* This is an information request packet */
- printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
- /* Set the packet type to information response */
- sendpacket[34] = 0x03;
-
- /* Set the router name */
- sendpacket[51] = 'X';
- sendpacket[52] = 'T';
- sendpacket[53] = 'P';
- sendpacket[54] = 'I';
- sendpacket[55] = 'P';
- sendpacket[56] = 'E';
- sendpacket[57] = '-';
- sendpacket[58] = CVHexToAscii(network_number >> 28);
- sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 66; i < 99; i+= 1)
- {
- sendpacket[i] = 0;
- }
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
- }
- else
- {
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- /* Set the WNodeID to our network address */
- sendpacket[35] = (unsigned char)(network_number >> 24);
- sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- } else {
- /*If we get here it's an IPX-data packet, so it'll get passed up the stack.
- */
- /* switch the network numbers */
- switch_net_numbers(sendpacket, network_number, 1);
- return 0;
- }
-}
-
-/*
- * If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- * if incoming is 1 - if the net number is 0 make it ours
- */
-
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[6] << 24) +
- (sendpacket[7] << 16) + (sendpacket[8] << 8) +
- sendpacket[9]);
-
-
- if (!incoming) {
- /*If the destination network number is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[6] = sendpacket[7] = sendpacket[8] =
- sendpacket[9] = 0x00;
- }
- } else {
- /* If the incoming network is 0, make it ours */
- if( pnetwork_number == 0) {
- sendpacket[6] = (unsigned char)(network_number >> 24);
- sendpacket[7] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[8] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[9] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[18] << 24) +
- (sendpacket[19] << 16) + (sendpacket[20] << 8) +
- sendpacket[21]);
-
-
- if( !incoming ) {
- /* If the source network is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[18] = sendpacket[19] = sendpacket[20] =
- sendpacket[21] = 0x00;
- }
- } else {
- /* If the source network is 0, make it ours */
- if( pnetwork_number == 0 ) {
- sendpacket[18] = (unsigned char)(network_number >> 24);
- sendpacket[19] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[20] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[21] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-
-
-
-/********************* X25API SPECIFIC FUNCTIONS ****************/
-
-
-/*===============================================================
- * find_channel
- *
- * Manages the lcn to device map. It increases performance
- * because it eliminates the need to search through the link
- * list for a device which is bounded to a specific lcn.
- *
- *===============================================================*/
-
-
-struct net_device *find_channel(sdla_t *card, unsigned lcn)
-{
- if (card->u.x.LAPB_hdlc){
-
- return card->wandev.dev;
-
- }else{
- /* We don't know whether the incoming lcn
- * is a PVC or an SVC channel. But we do know that
- * the lcn cannot be for both the PVC and the SVC
- * channel.
-
- * If the lcn number is greater or equal to 255,
- * take the modulo 255 of that number. We only have
- * 255 locations, thus higher numbers must be mapped
- * to a number between 0 and 245.
-
- * We must separate pvc's and svc's since two don't
- * have to be contiguous. Meaning pvc's can start
- * from 1 to 10 and svc's can start from 256 to 266.
- * But 256%255 is 1, i.e. CONFLICT.
- */
-
-
- /* Highest LCN number must be less or equal to 4096 */
- if ((lcn <= MAX_LCN_NUM) && (lcn > 0)){
-
- if (lcn < X25_MAX_CHAN){
- if (card->u.x.svc_to_dev_map[lcn])
- return card->u.x.svc_to_dev_map[lcn];
-
- if (card->u.x.pvc_to_dev_map[lcn])
- return card->u.x.pvc_to_dev_map[lcn];
-
- }else{
- int new_lcn = lcn%X25_MAX_CHAN;
- if (card->u.x.svc_to_dev_map[new_lcn])
- return card->u.x.svc_to_dev_map[new_lcn];
-
- if (card->u.x.pvc_to_dev_map[new_lcn])
- return card->u.x.pvc_to_dev_map[new_lcn];
- }
- }
- return NULL;
- }
-}
-
-void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn)
-{
- x25_channel_t *chan = dev->priv;
-
- /* Modulo the lcn number by X25_MAX_CHAN (255)
- * because the lcn number can be greater than 255
- *
- * We need to split svc and pvc since they don't have
- * to be contigous.
- */
-
- if (chan->common.svc){
- card->u.x.svc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev;
- }else{
- card->u.x.pvc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev;
- }
- chan->common.lcn = lcn;
-}
-
-
-
-/*===============================================================
- * x25api_bh
- *
- *
- *==============================================================*/
-
-static void x25api_bh(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct sk_buff *skb;
-
- if (atomic_read(&chan->bh_buff_used) == 0){
- printk(KERN_INFO "%s: BH Buffer Empty in BH\n",
- card->devname);
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- while (atomic_read(&chan->bh_buff_used)){
-
- /* If the sock is in the process of unlinking the
- * driver from the socket, we must get out.
- * This never happends but is a sanity check. */
- if (test_bit(0,&chan->common.common_critical)){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- /* If LAPB HDLC, do not drop packets if socket is
- * not connected. Let the buffer fill up and
- * turn off rx interrupt */
- if (card->u.x.LAPB_hdlc){
- if (chan->common.sk == NULL || chan->common.func == NULL){
- clear_bit(0, &chan->tq_working);
- return;
- }
- }
-
- skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
- if (skb == NULL){
- printk(KERN_INFO "%s: BH Skb empty for read %i\n",
- card->devname,chan->bh_read);
- }else{
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n",
- card->devname);
- dev_kfree_skb_any(skb);
- x25api_bh_cleanup(dev);
- ++chan->ifstats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- continue;
- }
-
-
- if (chan->common.func(skb,dev,chan->common.sk) != 0){
- /* Sock full cannot send, queue us for another
- * try
- */
- printk(KERN_INFO "%s: BH: !!! Packet failed to send !!!!! \n",
- card->devname);
- atomic_set(&chan->common.receive_block,1);
- return;
- }else{
- x25api_bh_cleanup(dev);
- ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
- }
- }
- }
- clear_bit(0, &chan->tq_working);
-
- return;
-}
-
-/*===============================================================
- * x25api_bh_cleanup
- *
- *
- *==============================================================*/
-
-static int x25api_bh_cleanup(struct net_device *dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
- TX25Status* status = card->flags;
-
-
- ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
- if (chan->bh_read == MAX_BH_BUFF){
- chan->bh_read=0;
- }else{
- ++chan->bh_read;
- }
-
- /* If the Receive interrupt was off, it means
- * that we filled up our circular buffer. Check
- * that we have space in the buffer. If so
- * turn the RX interrupt back on.
- */
- if (!(status->imask & INTR_ON_RX_FRAME)){
- if (atomic_read(&chan->bh_buff_used) < (MAX_BH_BUFF+1)){
- printk(KERN_INFO "%s: BH: Turning on the interrupt\n",
- card->devname);
- status->imask |= INTR_ON_RX_FRAME;
- }
- }
-
- atomic_dec(&chan->bh_buff_used);
- return 0;
-}
-
-
-/*===============================================================
- * bh_enqueue
- *
- *
- *==============================================================*/
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
- TX25Status* status = card->flags;
-
- if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
- printk(KERN_INFO "%s: Bottom half buffer FULL\n",
- card->devname);
- return 1;
- }
-
- ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
- if (chan->bh_write == MAX_BH_BUFF){
- chan->bh_write=0;
- }else{
- ++chan->bh_write;
- }
-
- atomic_inc(&chan->bh_buff_used);
-
- if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
- printk(KERN_INFO "%s: Buffer is now full, Turning off RX Intr\n",
- card->devname);
- status->imask &= ~INTR_ON_RX_FRAME;
- }
-
- return 0;
-}
-
-
-/*===============================================================
- * timer_intr_cmd_exec
- *
- * Called by timer interrupt to execute a command
- *===============================================================*/
-
-static int timer_intr_cmd_exec (sdla_t* card)
-{
- struct net_device *dev;
- unsigned char more_to_exec=0;
- volatile x25_channel_t *chan=NULL;
- int i=0,bad_cmd=0,err=0;
-
- if (card->u.x.cmd_dev == NULL){
- card->u.x.cmd_dev = card->wandev.dev;
- }
-
- dev = card->u.x.cmd_dev;
-
- for (;;){
-
- chan = dev->priv;
-
- if (atomic_read(&chan->common.command)){
-
- bad_cmd = check_bad_command(card,dev);
-
- if ((!chan->common.mbox || atomic_read(&chan->common.disconnect)) &&
- !bad_cmd){
-
- /* Socket has died or exited, We must bring the
- * channel down before anybody else tries to
- * use it */
- err = channel_disconnect(card,dev);
- }else{
- err = execute_delayed_cmd(card, dev,
- (mbox_cmd_t*)chan->common.mbox,
- bad_cmd);
- }
-
- switch (err){
-
- case RETURN_RESULT:
-
- /* Return the result to the socket without
- * delay. NO_WAIT Command */
- atomic_set(&chan->common.command,0);
- if (atomic_read(&card->u.x.command_busy))
- atomic_set(&card->u.x.command_busy,0);
-
- send_delayed_cmd_result(card,dev,card->mbox);
-
- more_to_exec=0;
- break;
- case DELAY_RESULT:
-
- /* Wait for the remote to respond, before
- * sending the result up to the socket.
- * WAIT command */
- if (atomic_read(&card->u.x.command_busy))
- atomic_set(&card->u.x.command_busy,0);
-
- atomic_set(&chan->common.command,0);
- more_to_exec=0;
- break;
- default:
-
- /* If command could not be executed for
- * some reason (i.e return code 0x33 busy)
- * set the more_to_exec bit which will
- * indicate that this command must be exectued
- * again during next timer interrupt
- */
- more_to_exec=1;
- if (atomic_read(&card->u.x.command_busy) == 0)
- atomic_set(&card->u.x.command_busy,1);
- break;
- }
-
- bad_cmd=0;
-
- /* If flags is set, there are no hdlc buffers,
- * thus, wait for the next pass and try the
- * same command again. Otherwise, start searching
- * from next device on the next pass.
- */
- if (!more_to_exec){
- dev = move_dev_to_next(card,dev);
- }
- break;
- }else{
- /* This device has nothing to execute,
- * go to next.
- */
- if (atomic_read(&card->u.x.command_busy))
- atomic_set(&card->u.x.command_busy,0);
- dev = move_dev_to_next(card,dev);
- }
-
- if (++i == card->u.x.no_dev){
- if (!more_to_exec){
- DBG_PRINTK(KERN_INFO "%s: Nothing to execute in Timer\n",
- card->devname);
- if (atomic_read(&card->u.x.command_busy)){
- atomic_set(&card->u.x.command_busy,0);
- }
- }
- break;
- }
-
- } //End of FOR
-
- card->u.x.cmd_dev = dev;
-
- if (more_to_exec){
- /* If more commands are pending, do not turn off timer
- * interrupt */
- return 1;
- }else{
- /* No more commands, turn off timer interrupt */
- return 0;
- }
-}
-
-/*===============================================================
- * execute_delayed_cmd
- *
- * Execute an API command which was passed down from the
- * sock. Sock is very limited in which commands it can
- * execute. Wait and No Wait commands are supported.
- * Place Call, Clear Call and Reset wait commands, where
- * Accept Call is a no_wait command.
- *
- *===============================================================*/
-
-static int execute_delayed_cmd(sdla_t* card, struct net_device *dev,
- mbox_cmd_t *usr_cmd, char bad_cmd)
-{
- TX25Mbox* mbox = card->mbox;
- int err;
- x25_channel_t *chan = dev->priv;
- int delay=RETURN_RESULT;
-
- if (!(*card->u.x.hdlc_buf_status & 0x40) && !bad_cmd){
- return TRY_CMD_AGAIN;
- }
-
- /* This way a command is guaranteed to be executed for
- * a specific lcn, the network interface is bound to. */
- usr_cmd->cmd.lcn = chan->common.lcn;
-
-
- /* If channel is pvc, instead of place call
- * run x25_channel configuration. If running LAPB HDLC
- * enable communications.
- */
- if ((!chan->common.svc) && (usr_cmd->cmd.command == X25_PLACE_CALL)){
-
- if (card->u.x.LAPB_hdlc){
- DBG_PRINTK(KERN_INFO "LAPB: Connecting\n");
- connect(card);
- set_chan_state(dev,WAN_CONNECTING);
- return DELAY_RESULT;
- }else{
- DBG_PRINTK(KERN_INFO "%s: PVC is CONNECTING\n",card->devname);
- if (x25_get_chan_conf(card, chan) == CMD_OK){
- set_chan_state(dev, WAN_CONNECTED);
- }else{
- set_chan_state(dev, WAN_DISCONNECTED);
- }
- return RETURN_RESULT;
- }
- }
-
- /* Copy the socket mbox command onto the board */
-
- memcpy(&mbox->cmd, &usr_cmd->cmd, sizeof(TX25Cmd));
- if (usr_cmd->cmd.length){
- memcpy(mbox->data, usr_cmd->data, usr_cmd->cmd.length);
- }
-
- /* Check if command is bad. We need to copy the cmd into
- * the buffer regardless since we return the, mbox to
- * the user */
- if (bad_cmd){
- mbox->cmd.result=0x01;
- return RETURN_RESULT;
- }
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK && err != X25RES_NOT_READY)
- x25_error(card, err, usr_cmd->cmd.command, usr_cmd->cmd.lcn);
-
- if (mbox->cmd.result == X25RES_NOT_READY){
- return TRY_CMD_AGAIN;
- }
-
- switch (mbox->cmd.command){
-
- case X25_PLACE_CALL:
-
- switch (mbox->cmd.result){
-
- case CMD_OK:
-
- /* Check if Place call is a wait command or a
- * no wait command */
- if (atomic_read(&chan->common.command) & 0x80)
- delay=RETURN_RESULT;
- else
- delay=DELAY_RESULT;
-
-
- DBG_PRINTK(KERN_INFO "\n%s: PLACE CALL Binding dev %s to lcn %i\n",
- card->devname,dev->name, mbox->cmd.lcn);
-
- bind_lcn_to_dev (card, dev, mbox->cmd.lcn);
- set_chan_state(dev, WAN_CONNECTING);
- break;
-
-
- default:
- delay=RETURN_RESULT;
- set_chan_state(dev, WAN_DISCONNECTED);
- break;
- }
- break;
-
- case X25_ACCEPT_CALL:
-
- switch (mbox->cmd.result){
-
- case CMD_OK:
-
- DBG_PRINTK(KERN_INFO "\n%s: ACCEPT Binding dev %s to lcn %i\n",
- card->devname,dev->name,mbox->cmd.lcn);
-
- bind_lcn_to_dev (card, dev, mbox->cmd.lcn);
-
- if (x25_get_chan_conf(card, chan) == CMD_OK){
-
- set_chan_state(dev, WAN_CONNECTED);
- delay=RETURN_RESULT;
-
- }else{
- if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){
- /* if clear is successful, wait for clear confirm
- */
- delay=DELAY_RESULT;
- }else{
- /* Do not change the state here. If we fail
- * the accept the return code is send up
- *the stack, which will ether retry
- * or clear the call
- */
- DBG_PRINTK(KERN_INFO
- "%s: ACCEPT: STATE MAY BE CURRUPTED 2 !!!!!\n",
- card->devname);
- delay=RETURN_RESULT;
- }
- }
- break;
-
-
- case X25RES_ASYNC_PACKET:
- delay=TRY_CMD_AGAIN;
- break;
-
- default:
- DBG_PRINTK(KERN_INFO "%s: ACCEPT FAILED\n",card->devname);
- if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){
- delay=DELAY_RESULT;
- }else{
- /* Do not change the state here. If we fail the accept. The
- * return code is send up the stack, which will ether retry
- * or clear the call */
- DBG_PRINTK(KERN_INFO
- "%s: ACCEPT: STATE MAY BE CORRUPTED 1 !!!!!\n",
- card->devname);
- delay=RETURN_RESULT;
- }
- }
- break;
-
- case X25_CLEAR_CALL:
-
- switch (mbox->cmd.result){
-
- case CMD_OK:
- DBG_PRINTK(KERN_INFO
- "CALL CLEAR OK: Dev %s Mbox Lcn %i Chan Lcn %i\n",
- dev->name,mbox->cmd.lcn,chan->common.lcn);
- set_chan_state(dev, WAN_DISCONNECTING);
- delay = DELAY_RESULT;
- break;
-
- case X25RES_CHANNEL_IN_USE:
- case X25RES_ASYNC_PACKET:
- delay = TRY_CMD_AGAIN;
- break;
-
- case X25RES_LINK_NOT_IN_ABM:
- case X25RES_INVAL_LCN:
- case X25RES_INVAL_STATE:
- set_chan_state(dev, WAN_DISCONNECTED);
- delay = RETURN_RESULT;
- break;
-
- default:
- /* If command did not execute because of user
- * fault, do not change the state. This will
- * signal the socket that clear command failed.
- * User can retry or close the socket.
- * When socket gets killed, it will set the
- * chan->disconnect which will signal
- * driver to clear the call */
- printk(KERN_INFO "%s: Clear Command Failed, Rc %x\n",
- card->devname,mbox->cmd.command);
- delay = RETURN_RESULT;
- }
- break;
- }
-
- return delay;
-}
-
-/*===============================================================
- * api_incoming_call
- *
- * Pass an incoming call request up the listening
- * sock. If the API sock is not listening reject the
- * call.
- *
- *===============================================================*/
-
-static int api_incoming_call (sdla_t* card, TX25Mbox *mbox, int lcn)
-{
- struct sk_buff *skb;
- int len = sizeof(TX25Cmd)+mbox->cmd.length;
-
- if (alloc_and_init_skb_buf(card, &skb, len)){
- printk(KERN_INFO "%s: API incoming call, no memory\n",card->devname);
- return 1;
- }
-
- memcpy(skb_put(skb,len),&mbox->cmd,len);
-
- skb->mac.raw = skb->data;
- skb->protocol = htons(X25_PROT);
- skb->pkt_type = WAN_PACKET_ASYNC;
-
- if (card->func(skb,card->sk) < 0){
- printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname);
- dev_kfree_skb_any(skb);
- return 1;
- }
-
- return 0;
-}
-
-/*===============================================================
- * send_delayed_cmd_result
- *
- * Wait commands like PLEACE CALL or CLEAR CALL must wait
- * until the result arrives. This function passes
- * the result to a waiting sock.
- *
- *===============================================================*/
-static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev,
- TX25Mbox* mbox)
-{
- x25_channel_t *chan = dev->priv;
- mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox;
- struct sk_buff *skb;
- int len=sizeof(unsigned char);
-
- atomic_set(&chan->common.command,0);
-
- /* If the sock is in the process of unlinking the
- * driver from the socket, we must get out.
- * This never happends but is a sanity check. */
- if (test_bit(0,&chan->common.common_critical)){
- return;
- }
-
- if (!usr_cmd || !chan->common.sk || !chan->common.func){
- DBG_PRINTK(KERN_INFO "Delay result: Sock not bounded sk: %u, func: %u, mbox: %u\n",
- (unsigned int)chan->common.sk,
- (unsigned int)chan->common.func,
- (unsigned int)usr_cmd);
- return;
- }
-
- memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd));
- if (mbox->cmd.length > 0){
- memcpy(usr_cmd->data, mbox->data, mbox->cmd.length);
- }
-
- if (alloc_and_init_skb_buf(card,&skb,len)){
- printk(KERN_INFO "Delay result: No sock buffers\n");
- return;
- }
-
- memcpy(skb_put(skb,len),&mbox->cmd.command,len);
-
- skb->mac.raw = skb->data;
- skb->pkt_type = WAN_PACKET_CMD;
-
- chan->common.func(skb,dev,chan->common.sk);
-}
-
-/*===============================================================
- * clear_confirm_event
- *
- * Pass the clear confirmation event up the sock. The
- * API will disconnect only after the clear confirmation
- * has been received.
- *
- * Depending on the state, clear confirmation could
- * be an OOB event, or a result of an API command.
- *===============================================================*/
-
-static int clear_confirm_event (sdla_t *card, TX25Mbox* mb)
-{
- struct net_device *dev;
- x25_channel_t *chan;
- unsigned char old_state;
-
- dev = find_channel(card,mb->cmd.lcn);
- if (!dev){
- DBG_PRINTK(KERN_INFO "%s: *** GOT CLEAR BUT NO DEV %i\n",
- card->devname,mb->cmd.lcn);
- return 0;
- }
-
- chan=dev->priv;
- DBG_PRINTK(KERN_INFO "%s: GOT CLEAR CONFIRM %s: Mbox lcn %i Chan lcn %i\n",
- card->devname, dev->name, mb->cmd.lcn, chan->common.lcn);
-
- /* If not API fall through to default.
- * If API, send the result to a waiting
- * socket.
- */
-
- old_state = chan->common.state;
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
- switch (old_state) {
-
- case WAN_DISCONNECTING:
- case WAN_CONNECTING:
- send_delayed_cmd_result(card,dev,mb);
- break;
- case WAN_CONNECTED:
- send_oob_msg(card,dev,mb);
- break;
- }
- return 1;
- }
-
- return 0;
-}
-
-/*===============================================================
- * send_oob_msg
- *
- * Construct an NEM Message and pass it up the connected
- * sock. If the sock is not bounded discard the NEM.
- *
- *===============================================================*/
-
-static void send_oob_msg(sdla_t *card, struct net_device *dev, TX25Mbox *mbox)
-{
- x25_channel_t *chan = dev->priv;
- mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox;
- struct sk_buff *skb;
- int len=sizeof(x25api_hdr_t)+mbox->cmd.length;
- x25api_t *api_hdr;
-
- /* If the sock is in the process of unlinking the
- * driver from the socket, we must get out.
- * This never happends but is a sanity check. */
- if (test_bit(0,&chan->common.common_critical)){
- return;
- }
-
- if (!usr_cmd || !chan->common.sk || !chan->common.func){
- DBG_PRINTK(KERN_INFO "OOB MSG: Sock not bounded\n");
- return;
- }
-
- memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd));
- if (mbox->cmd.length > 0){
- memcpy(usr_cmd->data, mbox->data, mbox->cmd.length);
- }
-
- if (alloc_and_init_skb_buf(card,&skb,len)){
- printk(KERN_INFO "%s: OOB MSG: No sock buffers\n",card->devname);
- return;
- }
-
- api_hdr = (x25api_t*)skb_put(skb,len);
- api_hdr->hdr.pktType = mbox->cmd.pktType & 0x7F;
- api_hdr->hdr.qdm = mbox->cmd.qdm;
- api_hdr->hdr.cause = mbox->cmd.cause;
- api_hdr->hdr.diagn = mbox->cmd.diagn;
- api_hdr->hdr.length = mbox->cmd.length;
- api_hdr->hdr.result = mbox->cmd.result;
- api_hdr->hdr.lcn = mbox->cmd.lcn;
-
- if (mbox->cmd.length > 0){
- memcpy(api_hdr->data,mbox->data,mbox->cmd.length);
- }
-
- skb->mac.raw = skb->data;
- skb->pkt_type = WAN_PACKET_ERR;
-
- if (chan->common.func(skb,dev,chan->common.sk) < 0){
- if (bh_enqueue(dev,skb)){
- printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname);
- dev_kfree_skb_any(skb);
- }
- }
-
- DBG_PRINTK(KERN_INFO "%s: OOB MSG OK, %s, lcn %i\n",
- card->devname, dev->name, mbox->cmd.lcn);
-}
-
-/*===============================================================
- * alloc_and_init_skb_buf
- *
- * Allocate and initialize an skb buffer.
- *
- *===============================================================*/
-
-static int alloc_and_init_skb_buf (sdla_t *card, struct sk_buff **skb, int len)
-{
- struct sk_buff *new_skb = *skb;
-
- new_skb = dev_alloc_skb(len + X25_HRDHDR_SZ);
- if (new_skb == NULL){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- return 1;
- }
-
- if (skb_tailroom(new_skb) < len){
- /* No room for the packet. Call off the whole thing! */
- dev_kfree_skb_any(new_skb);
- printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n"
- ,card->devname);
- *skb = NULL;
- return 1;
- }
-
- *skb = new_skb;
- return 0;
-
-}
-
-/*===============================================================
- * api_oob_event
- *
- * Send an OOB event up to the sock
- *
- *===============================================================*/
-
-static void api_oob_event (sdla_t *card,TX25Mbox *mbox)
-{
- struct net_device *dev = find_channel(card, mbox->cmd.lcn);
- x25_channel_t *chan;
-
- if (!dev)
- return;
-
- chan=dev->priv;
-
- if (chan->common.usedby == API)
- send_oob_msg(card,dev,mbox);
-
-}
-
-
-
-
-static int channel_disconnect(sdla_t* card, struct net_device *dev)
-{
-
- int err;
- x25_channel_t *chan = dev->priv;
-
- DBG_PRINTK(KERN_INFO "%s: TIMER: %s, Device down disconnecting\n",
- card->devname,dev->name);
-
- if (chan->common.svc){
- err = x25_clear_call(card,chan->common.lcn,0,0);
- }else{
- /* If channel is PVC or LAPB HDLC, there is no call
- * to be cleared, thus drop down to the default
- * area
- */
- err = 1;
- }
-
- switch (err){
-
- case X25RES_CHANNEL_IN_USE:
- case X25RES_NOT_READY:
- err = TRY_CMD_AGAIN;
- break;
- case CMD_OK:
- DBG_PRINTK(KERN_INFO "CALL CLEAR OK: Dev %s Chan Lcn %i\n",
- dev->name,chan->common.lcn);
-
- set_chan_state(dev,WAN_DISCONNECTING);
- atomic_set(&chan->common.command,0);
- err = DELAY_RESULT;
- break;
- default:
- /* If LAPB HDLC protocol, bring the whole link down
- * once the application terminates
- */
-
- set_chan_state(dev,WAN_DISCONNECTED);
-
- if (card->u.x.LAPB_hdlc){
- DBG_PRINTK(KERN_INFO "LAPB: Disconnecting Link\n");
- hdlc_link_down (card);
- }
- atomic_set(&chan->common.command,0);
- err = RETURN_RESULT;
- break;
- }
-
- return err;
-}
-
-static void hdlc_link_down (sdla_t *card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = 5;
- int err=0;
-
- do {
- memset(mbox,0,sizeof(TX25Mbox));
- mbox->cmd.command = X25_HDLC_LINK_DISC;
- mbox->cmd.length = 1;
- mbox->data[0]=0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_DISC, 0));
-
- if (err)
- printk(KERN_INFO "%s: Hdlc Link Down Failed %x\n",card->devname,err);
-
- disconnect (card);
-
-}
-
-static int check_bad_command(sdla_t* card, struct net_device *dev)
-{
- x25_channel_t *chan = dev->priv;
- int bad_cmd = 0;
-
- switch (atomic_read(&chan->common.command)&0x7F){
-
- case X25_PLACE_CALL:
- if (chan->common.state != WAN_DISCONNECTED)
- bad_cmd=1;
- break;
- case X25_CLEAR_CALL:
- if (chan->common.state == WAN_DISCONNECTED)
- bad_cmd=1;
- break;
- case X25_ACCEPT_CALL:
- if (chan->common.state != WAN_CONNECTING)
- bad_cmd=1;
- break;
- case X25_RESET:
- if (chan->common.state != WAN_CONNECTED)
- bad_cmd=1;
- break;
- default:
- bad_cmd=1;
- break;
- }
-
- if (bad_cmd){
- printk(KERN_INFO "%s: Invalid State, BAD Command %x, dev %s, lcn %i, st %i\n",
- card->devname,atomic_read(&chan->common.command),dev->name,
- chan->common.lcn, chan->common.state);
- }
-
- return bad_cmd;
-}
-
-
-
-/*************************** XPIPEMON FUNCTIONS **************************/
-
-/*==============================================================================
- * Process UDP call of type XPIPE
- */
-
-static int process_udp_mgmt_pkt(sdla_t *card)
-{
- int c_retry = MAX_CMD_RETRY;
- unsigned int len;
- struct sk_buff *new_skb;
- TX25Mbox *mbox = card->mbox;
- int err;
- int udp_mgmt_req_valid = 1;
- struct net_device *dev;
- x25_channel_t *chan;
- unsigned short lcn;
- struct timeval tv;
-
-
- x25_udp_pkt_t *x25_udp_pkt;
- x25_udp_pkt = (x25_udp_pkt_t *)card->u.x.udp_pkt_data;
-
- dev = card->u.x.udp_dev;
- chan = dev->priv;
- lcn = chan->common.lcn;
-
- switch(x25_udp_pkt->cblock.command) {
-
- /* XPIPE_ENABLE_TRACE */
- case XPIPE_ENABLE_TRACING:
-
- /* XPIPE_GET_TRACE_INFO */
- case XPIPE_GET_TRACE_INFO:
-
- /* SET FT1 MODE */
- case XPIPE_SET_FT1_MODE:
-
- if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err;
- udp_mgmt_req_valid = 0;
- break;
- }
-
- /* XPIPE_FT1_READ_STATUS */
- case XPIPE_FT1_READ_STATUS:
-
- /* FT1 MONITOR STATUS */
- case XPIPE_FT1_STATUS_CTRL:
- if(card->hw.fwid != SFID_X25_508) {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_type_err;
- udp_mgmt_req_valid = 0;
- break;
- }
- default:
- break;
- }
-
- if(!udp_mgmt_req_valid) {
- /* set length to 0 */
- x25_udp_pkt->cblock.length = 0;
- /* set return code */
- x25_udp_pkt->cblock.result = (card->hw.fwid != SFID_X25_508) ? 0x1F : 0xCD;
-
- } else {
-
- switch (x25_udp_pkt->cblock.command) {
-
-
- case XPIPE_FLUSH_DRIVER_STATS:
- init_x25_channel_struct(chan);
- init_global_statistics(card);
- mbox->cmd.length = 0;
- break;
-
-
- case XPIPE_DRIVER_STAT_IFSEND:
- memcpy(x25_udp_pkt->data, &chan->if_send_stat, sizeof(if_send_stat_t));
- mbox->cmd.length = sizeof(if_send_stat_t);
- x25_udp_pkt->cblock.length = mbox->cmd.length;
- break;
-
- case XPIPE_DRIVER_STAT_INTR:
- memcpy(&x25_udp_pkt->data[0], &card->statistics, sizeof(global_stats_t));
- memcpy(&x25_udp_pkt->data[sizeof(global_stats_t)],
- &chan->rx_intr_stat, sizeof(rx_intr_stat_t));
-
- mbox->cmd.length = sizeof(global_stats_t) +
- sizeof(rx_intr_stat_t);
- x25_udp_pkt->cblock.length = mbox->cmd.length;
- break;
-
- case XPIPE_DRIVER_STAT_GEN:
- memcpy(x25_udp_pkt->data,
- &chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,
- sizeof(pipe_mgmt_stat_t));
-
- memcpy(&x25_udp_pkt->data[sizeof(pipe_mgmt_stat_t)],
- &card->statistics, sizeof(global_stats_t));
-
- x25_udp_pkt->cblock.result = 0;
- x25_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- mbox->cmd.length = x25_udp_pkt->cblock.length;
- break;
-
- case XPIPE_ROUTER_UP_TIME:
- do_gettimeofday(&tv);
- chan->router_up_time = tv.tv_sec - chan->router_start_time;
- *(unsigned long *)&x25_udp_pkt->data = chan->router_up_time;
- x25_udp_pkt->cblock.length = mbox->cmd.length = 4;
- x25_udp_pkt->cblock.result = 0;
- break;
-
- default :
-
- do {
- memcpy(&mbox->cmd, &x25_udp_pkt->cblock.command, sizeof(TX25Cmd));
- if(mbox->cmd.length){
- memcpy(&mbox->data,
- (char *)x25_udp_pkt->data,
- mbox->cmd.length);
- }
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && c_retry-- && x25_error(card, err, mbox->cmd.command, 0));
-
-
- if ( err == CMD_OK ||
- (err == 1 &&
- (mbox->cmd.command == 0x06 ||
- mbox->cmd.command == 0x16) ) ){
-
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK;
- } else {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_timeout;
- }
-
- /* copy the result back to our buffer */
- memcpy(&x25_udp_pkt->cblock.command, &mbox->cmd, sizeof(TX25Cmd));
-
- if(mbox->cmd.length) {
- memcpy(&x25_udp_pkt->data, &mbox->data, mbox->cmd.length);
- }
- break;
-
- } //switch
-
- }
-
- /* Fill UDP TTL */
-
- x25_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(card->u.x.udp_pkt_data, mbox->cmd.length);
-
-
- if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- err = x25_send(card, lcn, 0, len, card->u.x.udp_pkt_data);
- if (!err)
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_passed;
- else
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_failed;
-
- } else {
-
- /* Allocate socket buffer */
- if((new_skb = dev_alloc_skb(len)) != NULL) {
- void *buf;
-
- /* copy data into new_skb */
- buf = skb_put(new_skb, len);
- memcpy(buf, card->u.x.udp_pkt_data, len);
-
- /* Decapsulate packet and pass it up the protocol
- stack */
- new_skb->dev = dev;
-
- if (chan->common.usedby == API)
- new_skb->protocol = htons(X25_PROT);
- else
- new_skb->protocol = htons(ETH_P_IP);
-
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack;
-
- } else {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket;
- printk(KERN_INFO
- "%s: UDP mgmt cmnd, no socket buffers available!\n",
- card->devname);
- }
- }
-
- card->u.x.udp_pkt_lgth = 0;
-
- return 1;
-}
-
-
-/*==============================================================================
- * Determine what type of UDP call it is. DRVSTATS or XPIPE8ND ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t* card )
-{
- x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)skb->data;
-
- if((x25_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (x25_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) &&
- (x25_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (x25_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-
- if(!strncmp(x25_udp_pkt->wp_mgmt.signature,
- UDPMGMT_XPIPE_SIGNATURE, 8)){
- return UDP_XPIPE_TYPE;
- }else{
- printk(KERN_INFO "%s: UDP Packet, Failed Signature !\n",
- card->devname);
- }
- }
-
- return UDP_INVALID_TYPE;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return nothing.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
-
-
- x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* fill in UDP reply */
- x25_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- x25_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = x25_udp_pkt->udp_pkt.udp_src_port;
- x25_udp_pkt->udp_pkt.udp_src_port =
- x25_udp_pkt->udp_pkt.udp_dst_port;
- x25_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)
- (x25_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)
- (x25_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
- /* calculate UDP checksum */
- x25_udp_pkt->udp_pkt.udp_checksum = 0;
-
- x25_udp_pkt->udp_pkt.udp_checksum =
- calc_checksum(&data[UDP_OFFSET], udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- x25_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = x25_udp_pkt->ip_pkt.ip_src_address;
- x25_udp_pkt->ip_pkt.ip_src_address =
- x25_udp_pkt->ip_pkt.ip_dst_address;
- x25_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-
- /* fill in IP checksum */
- x25_udp_pkt->ip_pkt.hdr_checksum = 0;
- x25_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data, sizeof(ip_pkt_t));
-
- return len;
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
- struct net_device *dev, struct sk_buff *skb,
- int lcn)
-{
- int udp_pkt_stored = 0;
-
- if(!card->u.x.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){
- card->u.x.udp_pkt_lgth = skb->len;
- card->u.x.udp_type = udp_type;
- card->u.x.udp_pkt_src = udp_pkt_src;
- card->u.x.udp_lcn = lcn;
- card->u.x.udp_dev = dev;
- memcpy(card->u.x.udp_pkt_data, skb->data, skb->len);
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UDP_PKT;
- udp_pkt_stored = 1;
-
- }else{
- printk(KERN_INFO "%s: ERROR: UDP packet not stored for LCN %d\n",
- card->devname,lcn);
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-
-/*=============================================================================
- * Initial the ppp_private_area structure.
- */
-static void init_x25_channel_struct( x25_channel_t *chan )
-{
- memset(&chan->if_send_stat.if_send_entry,0,sizeof(if_send_stat_t));
- memset(&chan->rx_intr_stat.rx_intr_no_socket,0,sizeof(rx_intr_stat_t));
- memset(&chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,0,sizeof(pipe_mgmt_stat_t));
-}
-
-/*============================================================================
- * Initialize Global Statistics
- */
-static void init_global_statistics( sdla_t *card )
-{
- memset(&card->statistics.isr_entry,0,sizeof(global_stats_t));
-}
-
-
-/*===============================================================
- * SMP Support
- * ==============================================================*/
-
-static void S508_S514_lock(sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-}
-static void S508_S514_unlock(sdla_t *card, unsigned long *smp_flags)
-{
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-/*===============================================================
- * x25_timer_routine
- *
- * A more efficient polling routine. Each half a second
- * queue a polling task. We want to do the polling in a
- * task not timer, because timer runs in interrupt time.
- *
- * FIXME Polling should be rethinked.
- *==============================================================*/
-
-static void x25_timer_routine(unsigned long data)
-{
- sdla_t *card = (sdla_t*)data;
-
- if (!card->wandev.dev){
- printk(KERN_INFO "%s: Stopping the X25 Poll Timer: No Dev.\n",
- card->devname);
- return;
- }
-
- if (card->open_cnt != card->u.x.num_of_ch){
- printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Interface down.\n",
- card->devname);
- return;
- }
-
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Shutting down.\n",
- card->devname);
- return;
- }
-
- if (!test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- trigger_x25_poll(card);
- }
-
- card->u.x.x25_timer.expires=jiffies+(HZ>>1);
- add_timer(&card->u.x.x25_timer);
- return;
-}
-
-void disable_comm_shutdown(sdla_t *card)
-{
- TX25Mbox* mbox = card->mbox;
- int err;
-
- /* Turn of interrutps */
- mbox->data[0] = 0;
- if (card->hw.fwid == SFID_X25_508){
- mbox->data[1] = card->hw.irq;
- mbox->data[2] = 2;
- mbox->cmd.length = 3;
- }else {
- mbox->cmd.length = 1;
- }
- mbox->cmd.command = X25_SET_INTERRUPT_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- printk(KERN_INFO "INTERRUPT OFF FAIED %x\n",err);
-
- /* Bring down HDLC */
- mbox->cmd.command = X25_HDLC_LINK_CLOSE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- printk(KERN_INFO "LINK CLOSED FAILED %x\n",err);
-
-
- /* Brind down DTR */
- mbox->data[0] = 0;
- mbox->data[2] = 0;
- mbox->data[1] = 0x01;
- mbox->cmd.length = 3;
- mbox->cmd.command = X25_SET_GLOBAL_VARS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- printk(KERN_INFO "DTR DOWN FAILED %x\n",err);
-
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
deleted file mode 100644
index 032c0f81928e..000000000000
--- a/drivers/net/wan/sdladrv.c
+++ /dev/null
@@ -1,2314 +0,0 @@
-/*****************************************************************************
-* sdladrv.c SDLA Support Module. Main module.
-*
-* This module is a library of common hardware-specific functions
-* used by all Sangoma drivers.
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Mar 20, 2001 Nenad Corbic Added the auto_pci_cfg filed, to support
-* the PCISLOT #0.
-* Apr 04, 2000 Nenad Corbic Fixed the auto memory detection code.
-* The memory test at address 0xC8000.
-* Mar 09, 2000 Nenad Corbic Added Gideon's Bug Fix: clear pci
-* interrupt flags on initial load.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Updates for Linux 2.2.X kernels.
-* Sep 17, 1998 Jaspreet Singh Updates for linux 2.2.X kernels
-* Dec 20, 1996 Gene Kozin Version 3.0.0. Complete overhaul.
-* Jul 12, 1996 Gene Kozin Changes for Linux 2.0 compatibility.
-* Jun 12, 1996 Gene Kozin Added support for S503 card.
-* Apr 30, 1996 Gene Kozin SDLA hardware interrupt is acknowledged before
-* calling protocolspecific ISR.
-* Register I/O ports with Linux kernel.
-* Miscellaneous bug fixes.
-* Dec 20, 1995 Gene Kozin Fixed a bug in interrupt routine.
-* Oct 14, 1995 Gene Kozin Initial version.
-*****************************************************************************/
-
-/*****************************************************************************
- * Notes:
- * ------
- * 1. This code is ment to be system-independent (as much as possible). To
- * achive this, various macros are used to hide system-specific interfaces.
- * To compile this code, one of the following constants must be defined:
- *
- * Platform Define
- * -------- ------
- * Linux _LINUX_
- * SCO Unix _SCO_UNIX_
- *
- * 2. Supported adapter types:
- *
- * S502A
- * ES502A (S502E)
- * S503
- * S507
- * S508 (S509)
- *
- * 3. S502A Notes:
- *
- * There is no separate DPM window enable/disable control in S502A. It
- * opens immediately after a window number it written to the HMCR
- * register. To close the window, HMCR has to be written a value
- * ????1111b (e.g. 0x0F or 0xFF).
- *
- * S502A DPM window cannot be located at offset E000 (e.g. 0xAE000).
- *
- * There should be a delay of ??? before reading back S502A status
- * register.
- *
- * 4. S502E Notes:
- *
- * S502E has a h/w bug: although default IRQ line state is HIGH, enabling
- * interrupts by setting bit 1 of the control register (BASE) to '1'
- * causes it to go LOW! Therefore, disabling interrupts by setting that
- * bit to '0' causes low-to-high transition on IRQ line (ghosty
- * interrupt). The same occurs when disabling CPU by resetting bit 0 of
- * CPU control register (BASE+3) - see the next note.
- *
- * S502E CPU and DPM control is limited:
- *
- * o CPU cannot be stopped independently. Resetting bit 0 of the CPUi
- * control register (BASE+3) shuts the board down entirely, including
- * DPM;
- *
- * o DPM access cannot be controlled dynamically. Ones CPU is started,
- * bit 1 of the control register (BASE) is used to enable/disable IRQ,
- * so that access to shared memory cannot be disabled while CPU is
- * running.
- ****************************************************************************/
-
-#define _LINUX_
-
-#if defined(_LINUX_) /****** Linux *******************************/
-
-#include <linux/config.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/module.h> /* support for loadable modules */
-#include <linux/jiffies.h> /* for jiffies, HZ, etc. */
-#include <linux/sdladrv.h> /* API definitions */
-#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
-#include <linux/sdlapci.h> /* SDLA PCI hardware definitions */
-#include <linux/pci.h> /* PCI defines and function prototypes */
-#include <asm/io.h> /* for inb(), outb(), etc. */
-
-#define _INB(port) (inb(port))
-#define _OUTB(port, byte) (outb((byte),(port)))
-#define SYSTEM_TICK jiffies
-
-#include <linux/init.h>
-
-
-#elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/
-
-#if !defined(INKERNEL)
-#error This code MUST be compiled in kernel mode!
-#endif
-#include <sys/sdladrv.h> /* API definitions */
-#include <sys/sdlasfm.h> /* SDLA firmware module definitions */
-#include <sys/inline.h> /* for inb(), outb(), etc. */
-#define _INB(port) (inb(port))
-#define _OUTB(port, byte) (outb((port),(byte)))
-#define SYSTEM_TICK lbolt
-
-#else
-#error Unknown system type!
-#endif
-
-#define MOD_VERSION 3
-#define MOD_RELEASE 0
-
-#define SDLA_IODELAY 100 /* I/O Rd/Wr delay, 10 works for 486DX2-66 */
-#define EXEC_DELAY 20 /* shared memory access delay, mks */
-#define EXEC_TIMEOUT (HZ*2) /* command timeout, in ticks */
-
-/* I/O port address range */
-#define S502A_IORANGE 3
-#define S502E_IORANGE 4
-#define S503_IORANGE 3
-#define S507_IORANGE 4
-#define S508_IORANGE 4
-
-/* Maximum amount of memory */
-#define S502_MAXMEM 0x10000L
-#define S503_MAXMEM 0x10000L
-#define S507_MAXMEM 0x40000L
-#define S508_MAXMEM 0x40000L
-
-/* Minimum amount of memory */
-#define S502_MINMEM 0x8000L
-#define S503_MINMEM 0x8000L
-#define S507_MINMEM 0x20000L
-#define S508_MINMEM 0x20000L
-#define NO_PORT -1
-
-
-
-
-
-/****** Function Prototypes *************************************************/
-
-/* Hardware-specific functions */
-static int sdla_detect (sdlahw_t* hw);
-static int sdla_autodpm (sdlahw_t* hw);
-static int sdla_setdpm (sdlahw_t* hw);
-static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len);
-static int sdla_init (sdlahw_t* hw);
-static unsigned long sdla_memtest (sdlahw_t* hw);
-static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo);
-static unsigned char make_config_byte (sdlahw_t* hw);
-static int sdla_start (sdlahw_t* hw, unsigned addr);
-
-static int init_s502a (sdlahw_t* hw);
-static int init_s502e (sdlahw_t* hw);
-static int init_s503 (sdlahw_t* hw);
-static int init_s507 (sdlahw_t* hw);
-static int init_s508 (sdlahw_t* hw);
-
-static int detect_s502a (int port);
-static int detect_s502e (int port);
-static int detect_s503 (int port);
-static int detect_s507 (int port);
-static int detect_s508 (int port);
-static int detect_s514 (sdlahw_t* hw);
-static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card);
-
-/* Miscellaneous functions */
-static void peek_by_4 (unsigned long src, void* buf, unsigned len);
-static void poke_by_4 (unsigned long dest, void* buf, unsigned len);
-static int calibrate_delay (int mks);
-static int get_option_index (unsigned* optlist, unsigned optval);
-static unsigned check_memregion (void* ptr, unsigned len);
-static unsigned test_memregion (void* ptr, unsigned len);
-static unsigned short checksum (unsigned char* buf, unsigned len);
-static int init_pci_slot(sdlahw_t *);
-
-static int pci_probe(sdlahw_t *hw);
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-static struct pci_device_id sdladrv_pci_tbl[] = {
- { V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
- { } /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-/* private data */
-static char modname[] = "sdladrv";
-static char fullname[] = "SDLA Support Module";
-static char copyright[] = "(c) 1995-1999 Sangoma Technologies Inc.";
-static unsigned exec_idle;
-
-/* Hardware configuration options.
- * These are arrays of configuration options used by verification routines.
- * The first element of each array is its size (i.e. number of options).
- */
-static unsigned s502_port_options[] =
- { 4, 0x250, 0x300, 0x350, 0x360 }
-;
-static unsigned s503_port_options[] =
- { 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 }
-;
-static unsigned s508_port_options[] =
- { 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 }
-;
-
-static unsigned s502a_irq_options[] = { 0 };
-static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 };
-static unsigned s503_irq_options[] = { 5, 2, 3, 4, 5, 7 };
-static unsigned s508_irq_options[] = { 8, 3, 4, 5, 7, 10, 11, 12, 15 };
-
-static unsigned s502a_dpmbase_options[] =
-{
- 28,
- 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000,
- 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000,
- 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000,
- 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000,
-};
-static unsigned s507_dpmbase_options[] =
-{
- 32,
- 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
- 0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
- 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
- 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
-};
-static unsigned s508_dpmbase_options[] = /* incl. S502E and S503 */
-{
- 32,
- 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
- 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
- 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
- 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
-};
-
-/*
-static unsigned s502_dpmsize_options[] = { 2, 0x2000, 0x10000 };
-static unsigned s507_dpmsize_options[] = { 2, 0x2000, 0x4000 };
-static unsigned s508_dpmsize_options[] = { 1, 0x2000 };
-*/
-
-static unsigned s502a_pclk_options[] = { 2, 3600, 7200 };
-static unsigned s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 };
-static unsigned s503_pclk_options[] = { 3, 7200, 8000, 10000 };
-static unsigned s507_pclk_options[] = { 1, 12288 };
-static unsigned s508_pclk_options[] = { 1, 16000 };
-
-/* Host memory control register masks */
-static unsigned char s502a_hmcr[] =
-{
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, /* A0000 - AC000 */
- 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, /* C0000 - CC000 */
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, /* D0000 - DC000 */
- 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, /* E0000 - EC000 */
-};
-static unsigned char s502e_hmcr[] =
-{
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, /* A0000 - AE000 */
- 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, /* C0000 - CE000 */
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* D0000 - DE000 */
- 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, /* E0000 - EE000 */
-};
-static unsigned char s507_hmcr[] =
-{
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* A0000 - AE000 */
- 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, /* B0000 - BE000 */
- 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, /* C0000 - CE000 */
- 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, /* E0000 - EE000 */
-};
-static unsigned char s508_hmcr[] =
-{
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* A0000 - AE000 */
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* C0000 - CE000 */
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* D0000 - DE000 */
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* E0000 - EE000 */
-};
-
-static unsigned char s507_irqmask[] =
-{
- 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0
-};
-
-static int pci_slot_ar[MAX_S514_CARDS];
-
-/******* Kernel Loadable Module Entry Points ********************************/
-
-/*============================================================================
- * Module 'insert' entry point.
- * o print announcement
- * o initialize static data
- * o calibrate SDLA shared memory access delay.
- *
- * Return: 0 Ok
- * < 0 error.
- * Context: process
- */
-
-static int __init sdladrv_init(void)
-{
- int i=0;
-
- printk(KERN_INFO "%s v%u.%u %s\n",
- fullname, MOD_VERSION, MOD_RELEASE, copyright);
- exec_idle = calibrate_delay(EXEC_DELAY);
-#ifdef WANDEBUG
- printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle);
-#endif
-
- /* Initialize the PCI Card array, which
- * will store flags, used to mark
- * card initialization state */
- for (i=0; i<MAX_S514_CARDS; i++)
- pci_slot_ar[i] = 0xFF;
-
- return 0;
-}
-
-/*============================================================================
- * Module 'remove' entry point.
- * o release all remaining system resources
- */
-static void __exit sdladrv_cleanup(void)
-{
-}
-
-module_init(sdladrv_init);
-module_exit(sdladrv_cleanup);
-
-/******* Kernel APIs ********************************************************/
-
-/*============================================================================
- * Set up adapter.
- * o detect adapter type
- * o verify hardware configuration options
- * o check for hardware conflicts
- * o set up adapter shared memory
- * o test adapter memory
- * o load firmware
- * Return: 0 ok.
- * < 0 error
- */
-
-EXPORT_SYMBOL(sdla_setup);
-
-int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
-{
- unsigned* irq_opt = NULL; /* IRQ options */
- unsigned* dpmbase_opt = NULL; /* DPM window base options */
- unsigned* pclk_opt = NULL; /* CPU clock rate options */
- int err=0;
-
- if (sdla_detect(hw)) {
- if(hw->type != SDLA_S514)
- printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n",
- modname, hw->port);
- return -EINVAL;
- }
-
- if(hw->type != SDLA_S514) {
- printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n",
- modname, hw->type, hw->port);
-
- hw->dpmsize = SDLA_WINDOWSIZE;
- switch (hw->type) {
- case SDLA_S502A:
- hw->io_range = S502A_IORANGE;
- irq_opt = s502a_irq_options;
- dpmbase_opt = s502a_dpmbase_options;
- pclk_opt = s502a_pclk_options;
- break;
-
- case SDLA_S502E:
- hw->io_range = S502E_IORANGE;
- irq_opt = s502e_irq_options;
- dpmbase_opt = s508_dpmbase_options;
- pclk_opt = s502e_pclk_options;
- break;
-
- case SDLA_S503:
- hw->io_range = S503_IORANGE;
- irq_opt = s503_irq_options;
- dpmbase_opt = s508_dpmbase_options;
- pclk_opt = s503_pclk_options;
- break;
-
- case SDLA_S507:
- hw->io_range = S507_IORANGE;
- irq_opt = s508_irq_options;
- dpmbase_opt = s507_dpmbase_options;
- pclk_opt = s507_pclk_options;
- break;
-
- case SDLA_S508:
- hw->io_range = S508_IORANGE;
- irq_opt = s508_irq_options;
- dpmbase_opt = s508_dpmbase_options;
- pclk_opt = s508_pclk_options;
- break;
- }
-
- /* Verify IRQ configuration options */
- if (!get_option_index(irq_opt, hw->irq)) {
- printk(KERN_INFO "%s: IRQ %d is invalid!\n",
- modname, hw->irq);
- return -EINVAL;
- }
-
- /* Verify CPU clock rate configuration options */
- if (hw->pclk == 0)
- hw->pclk = pclk_opt[1]; /* use default */
-
- else if (!get_option_index(pclk_opt, hw->pclk)) {
- printk(KERN_INFO "%s: CPU clock %u is invalid!\n",
- modname, hw->pclk);
- return -EINVAL;
- }
- printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n",
- modname, hw->pclk);
-
- /* Setup adapter dual-port memory window and test memory */
- if (hw->dpmbase == 0) {
- err = sdla_autodpm(hw);
- if (err) {
- printk(KERN_INFO
- "%s: can't find available memory region!\n",
- modname);
- return err;
- }
- }
- else if (!get_option_index(dpmbase_opt,
- virt_to_phys(hw->dpmbase))) {
- printk(KERN_INFO
- "%s: memory address 0x%lX is invalid!\n",
- modname, virt_to_phys(hw->dpmbase));
- return -EINVAL;
- }
- else if (sdla_setdpm(hw)) {
- printk(KERN_INFO
- "%s: 8K memory region at 0x%lX is not available!\n",
- modname, virt_to_phys(hw->dpmbase));
- return -EINVAL;
- }
- printk(KERN_INFO
- "%s: dual-port memory window is set at 0x%lX.\n",
- modname, virt_to_phys(hw->dpmbase));
-
-
- /* If we find memory in 0xE**** Memory region,
- * warn the user to disable the SHADOW RAM.
- * Since memory corruption can occur if SHADOW is
- * enabled. This can causes random crashes ! */
- if (virt_to_phys(hw->dpmbase) >= 0xE0000){
- printk(KERN_WARNING "\n%s: !!!!!!!! WARNING !!!!!!!!\n",modname);
- printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n",
- modname, virt_to_phys(hw->dpmbase));
- printk(KERN_WARNING " Please disable the SHADOW RAM, otherwise\n");
- printk(KERN_WARNING " your system might crash randomly from time to time !\n");
- printk(KERN_WARNING "%s: !!!!!!!! WARNING !!!!!!!!\n\n",modname);
- }
- }
-
- else {
- hw->memory = test_memregion((void*)hw->dpmbase,
- MAX_SIZEOF_S514_MEMORY);
- if(hw->memory < (256 * 1024)) {
- printk(KERN_INFO
- "%s: error in testing S514 memory (0x%lX)\n",
- modname, hw->memory);
- sdla_down(hw);
- return -EINVAL;
- }
- }
-
- printk(KERN_INFO "%s: found %luK bytes of on-board memory\n",
- modname, hw->memory / 1024);
-
- /* Load firmware. If loader fails then shut down adapter */
- err = sdla_load(hw, sfm, len);
- if (err) sdla_down(hw); /* shutdown adapter */
-
- return err;
-}
-
-/*============================================================================
- * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
- */
-
-EXPORT_SYMBOL(sdla_down);
-
-int sdla_down (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int i;
- unsigned char CPU_no;
- u32 int_config, int_status;
-
- if(!port && (hw->type != SDLA_S514))
- return -EFAULT;
-
- switch (hw->type) {
- case SDLA_S502A:
- _OUTB(port, 0x08); /* halt CPU */
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- hw->regs[0] = 0x08;
- _OUTB(port + 1, 0xFF); /* close memory window */
- hw->regs[1] = 0xFF;
- break;
-
- case SDLA_S502E:
- _OUTB(port + 3, 0); /* stop CPU */
- _OUTB(port, 0); /* reset board */
- for (i = 0; i < S502E_IORANGE; ++i)
- hw->regs[i] = 0
- ;
- break;
-
- case SDLA_S503:
- case SDLA_S507:
- case SDLA_S508:
- _OUTB(port, 0); /* reset board logic */
- hw->regs[0] = 0;
- break;
-
- case SDLA_S514:
- /* halt the adapter */
- *(char *)hw->vector = S514_CPU_HALT;
- CPU_no = hw->S514_cpu_no[0];
-
- /* disable the PCI IRQ and disable memory access */
- pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
- int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B;
- pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config);
- read_S514_int_stat(hw, &int_status);
- S514_intack(hw, int_status);
- if(CPU_no == S514_CPU_A)
- pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD,
- PCI_CPU_A_MEM_DISABLE);
- else
- pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
- PCI_CPU_B_MEM_DISABLE);
-
- /* free up the allocated virtual memory */
- iounmap((void *)hw->dpmbase);
- iounmap((void *)hw->vector);
- break;
-
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/*============================================================================
- * Map shared memory window into SDLA address space.
- */
-
-EXPORT_SYMBOL(sdla_mapmem);
-
-int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
-{
- unsigned port = hw->port;
- register int tmp;
-
- switch (hw->type) {
- case SDLA_S502A:
- case SDLA_S502E:
- if (addr < S502_MAXMEM) { /* verify parameter */
- tmp = addr >> 13; /* convert to register mask */
- _OUTB(port + 2, tmp);
- hw->regs[2] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S503:
- if (addr < S503_MAXMEM) { /* verify parameter */
- tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70);
- _OUTB(port, tmp);
- hw->regs[0] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S507:
- if (addr < S507_MAXMEM) {
- if (!(_INB(port) & 0x02))
- return -EIO;
- tmp = addr >> 13; /* convert to register mask */
- _OUTB(port + 2, tmp);
- hw->regs[2] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S508:
- if (addr < S508_MAXMEM) {
- tmp = addr >> 13; /* convert to register mask */
- _OUTB(port + 2, tmp);
- hw->regs[2] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S514:
- return 0;
-
- default:
- return -EINVAL;
- }
- hw->vector = addr & 0xFFFFE000L;
- return 0;
-}
-
-/*============================================================================
- * Enable interrupt generation.
- */
-
-static int sdla_inten (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- switch (hw->type) {
- case SDLA_S502E:
- /* Note thar interrupt control operations on S502E are allowed
- * only if CPU is enabled (bit 0 of status register is set).
- */
- if (_INB(port) & 0x01) {
- _OUTB(port, 0x02); /* bit1 = 1, bit2 = 0 */
- _OUTB(port, 0x06); /* bit1 = 1, bit2 = 1 */
- hw->regs[0] = 0x06;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- tmp = hw->regs[0] | 0x04;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (!(_INB(port) & 0x02)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S508:
- tmp = hw->regs[0] | 0x10;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (!(_INB(port + 1) & 0x10)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S502A:
- case SDLA_S507:
- break;
-
- case SDLA_S514:
- break;
-
- default:
- return -EINVAL;
-
- }
- return 0;
-}
-
-/*============================================================================
- * Disable interrupt generation.
- */
-
-#if 0
-int sdla_intde (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- switch (hw->type) {
- case SDLA_S502E:
- /* Notes:
- * 1) interrupt control operations are allowed only if CPU is
- * enabled (bit 0 of status register is set).
- * 2) disabling interrupts using bit 1 of control register
- * causes IRQ line go high, therefore we are going to use
- * 0x04 instead: lower it to inhibit interrupts to PC.
- */
- if (_INB(port) & 0x01) {
- _OUTB(port, hw->regs[0] & ~0x04);
- hw->regs[0] &= ~0x04;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- tmp = hw->regs[0] & ~0x04;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) & 0x02) /* verify */
- return -EIO;
- break;
-
- case SDLA_S508:
- tmp = hw->regs[0] & ~0x10;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) & 0x10) /* verify */
- return -EIO;
- break;
-
- case SDLA_S502A:
- case SDLA_S507:
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-#endif /* 0 */
-
-/*============================================================================
- * Acknowledge SDLA hardware interrupt.
- */
-
-static int sdla_intack (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp;
-
- switch (hw->type) {
- case SDLA_S502E:
- /* To acknoledge hardware interrupt we have to toggle bit 3 of
- * control register: \_/
- * Note that interrupt control operations on S502E are allowed
- * only if CPU is enabled (bit 1 of status register is set).
- */
- if (_INB(port) & 0x01) {
- tmp = hw->regs[0] & ~0x04;
- _OUTB(port, tmp);
- tmp |= 0x04;
- _OUTB(port, tmp);
- hw->regs[0] = tmp;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- if (_INB(port) & 0x04) {
- tmp = hw->regs[0] & ~0x08;
- _OUTB(port, tmp);
- tmp |= 0x08;
- _OUTB(port, tmp);
- hw->regs[0] = tmp;
- }
- break;
-
- case SDLA_S502A:
- case SDLA_S507:
- case SDLA_S508:
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-
-/*============================================================================
- * Acknowledge S514 hardware interrupt.
- */
-
-EXPORT_SYMBOL(S514_intack);
-
-void S514_intack (sdlahw_t* hw, u32 int_status)
-{
- pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-}
-
-
-/*============================================================================
- * Read the S514 hardware interrupt status.
- */
-
-EXPORT_SYMBOL(read_S514_int_stat);
-
-void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
-{
- pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-}
-
-
-/*============================================================================
- * Generate an interrupt to adapter's CPU.
- */
-
-#if 0
-int sdla_intr (sdlahw_t* hw)
-{
- unsigned port = hw->port;
-
- switch (hw->type) {
- case SDLA_S502A:
- if (!(_INB(port) & 0x40)) {
- _OUTB(port, 0x10); /* issue NMI to CPU */
- hw->regs[0] = 0x10;
- }
- else return -EIO;
- break;
-
- case SDLA_S507:
- if ((_INB(port) & 0x06) == 0x06) {
- _OUTB(port + 3, 0);
- }
- else return -EIO;
- break;
-
- case SDLA_S508:
- if (_INB(port + 1) & 0x02) {
- _OUTB(port, 0x08);
- }
- else return -EIO;
- break;
-
- case SDLA_S502E:
- case SDLA_S503:
- default:
- return -EINVAL;
- }
- return 0;
-}
-#endif /* 0 */
-
-/*============================================================================
- * Execute Adapter Command.
- * o Set exec flag.
- * o Busy-wait until flag is reset.
- * o Return number of loops made, or 0 if command timed out.
- */
-
-EXPORT_SYMBOL(sdla_exec);
-
-int sdla_exec (void* opflag)
-{
- volatile unsigned char* flag = opflag;
- unsigned long tstop;
- int nloops;
-
- if(readb(flag) != 0x00) {
- printk(KERN_INFO
- "WANPIPE: opp flag set on entry to sdla_exec\n");
- return 0;
- }
-
- writeb(0x01, flag);
-
- tstop = SYSTEM_TICK + EXEC_TIMEOUT;
-
- for (nloops = 1; (readb(flag) == 0x01); ++ nloops) {
- unsigned delay = exec_idle;
- while (-- delay); /* delay */
- if (SYSTEM_TICK > tstop) return 0; /* time is up! */
- }
- return nloops;
-}
-
-/*============================================================================
- * Read absolute adapter memory.
- * Transfer data from adapter's memory to data buffer.
- *
- * Note:
- * Care should be taken when crossing dual-port memory window boundary.
- * This function is not atomic, so caller must disable interrupt if
- * interrupt routines are accessing adapter shared memory.
- */
-
-EXPORT_SYMBOL(sdla_peek);
-
-int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
-{
-
- if (addr + len > hw->memory) /* verify arguments */
- return -EINVAL;
-
- if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */
- peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
- return 0;
- }
-
- else { /* copy data for the S508 adapter */
- unsigned long oldvec = hw->vector;
- unsigned winsize = hw->dpmsize;
- unsigned curpos, curlen; /* current offset and block size */
- unsigned long curvec; /* current DPM window vector */
- int err = 0;
-
- while (len && !err) {
- curpos = addr % winsize; /* current window offset */
- curvec = addr - curpos; /* current window vector */
- curlen = (len > (winsize - curpos)) ?
- (winsize - curpos) : len;
- /* Relocate window and copy block of data */
- err = sdla_mapmem(hw, curvec);
- peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
- curlen);
- addr += curlen;
- buf = (char*)buf + curlen;
- len -= curlen;
- }
-
- /* Restore DPM window position */
- sdla_mapmem(hw, oldvec);
- return err;
- }
-}
-
-
-/*============================================================================
- * Read data from adapter's memory to a data buffer in 4-byte chunks.
- * Note that we ensure that the SDLA memory address is on a 4-byte boundary
- * before we begin moving the data in 4-byte chunks.
-*/
-
-static void peek_by_4 (unsigned long src, void* buf, unsigned len)
-{
-
- /* byte copy data until we get to a 4-byte boundary */
- while (len && (src & 0x03)) {
- *(char *)buf ++ = readb(src ++);
- len --;
- }
-
- /* copy data in 4-byte chunks */
- while (len >= 4) {
- *(unsigned long *)buf = readl(src);
- buf += 4;
- src += 4;
- len -= 4;
- }
-
- /* byte copy any remaining data */
- while (len) {
- *(char *)buf ++ = readb(src ++);
- len --;
- }
-}
-
-
-/*============================================================================
- * Write Absolute Adapter Memory.
- * Transfer data from data buffer to adapter's memory.
- *
- * Note:
- * Care should be taken when crossing dual-port memory window boundary.
- * This function is not atomic, so caller must disable interrupt if
- * interrupt routines are accessing adapter shared memory.
- */
-
-EXPORT_SYMBOL(sdla_poke);
-
-int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
-{
-
- if (addr + len > hw->memory) /* verify arguments */
- return -EINVAL;
-
- if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */
- poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
- return 0;
- }
-
- else { /* copy data for the S508 adapter */
- unsigned long oldvec = hw->vector;
- unsigned winsize = hw->dpmsize;
- unsigned curpos, curlen; /* current offset and block size */
- unsigned long curvec; /* current DPM window vector */
- int err = 0;
-
- while (len && !err) {
- curpos = addr % winsize; /* current window offset */
- curvec = addr - curpos; /* current window vector */
- curlen = (len > (winsize - curpos)) ?
- (winsize - curpos) : len;
- /* Relocate window and copy block of data */
- sdla_mapmem(hw, curvec);
- poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
- curlen);
- addr += curlen;
- buf = (char*)buf + curlen;
- len -= curlen;
- }
-
- /* Restore DPM window position */
- sdla_mapmem(hw, oldvec);
- return err;
- }
-}
-
-
-/*============================================================================
- * Write from a data buffer to adapter's memory in 4-byte chunks.
- * Note that we ensure that the SDLA memory address is on a 4-byte boundary
- * before we begin moving the data in 4-byte chunks.
-*/
-
-static void poke_by_4 (unsigned long dest, void* buf, unsigned len)
-{
-
- /* byte copy data until we get to a 4-byte boundary */
- while (len && (dest & 0x03)) {
- writeb (*(char *)buf ++, dest ++);
- len --;
- }
-
- /* copy data in 4-byte chunks */
- while (len >= 4) {
- writel (*(unsigned long *)buf, dest);
- dest += 4;
- buf += 4;
- len -= 4;
- }
-
- /* byte copy any remaining data */
- while (len) {
- writeb (*(char *)buf ++ , dest ++);
- len --;
- }
-}
-
-
-#ifdef DONT_COMPIPLE_THIS
-#endif /* DONT_COMPIPLE_THIS */
-
-/****** Hardware-Specific Functions *****************************************/
-
-/*============================================================================
- * Detect adapter type.
- * o if adapter type is specified then call detection routine for that adapter
- * type. Otherwise call detection routines for every adapter types until
- * adapter is detected.
- *
- * Notes:
- * 1) Detection tests are destructive! Adapter will be left in shutdown state
- * after the test.
- */
-static int sdla_detect (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int err = 0;
-
- if (!port && (hw->type != SDLA_S514))
- return -EFAULT;
-
- switch (hw->type) {
- case SDLA_S502A:
- if (!detect_s502a(port)) err = -ENODEV;
- break;
-
- case SDLA_S502E:
- if (!detect_s502e(port)) err = -ENODEV;
- break;
-
- case SDLA_S503:
- if (!detect_s503(port)) err = -ENODEV;
- break;
-
- case SDLA_S507:
- if (!detect_s507(port)) err = -ENODEV;
- break;
-
- case SDLA_S508:
- if (!detect_s508(port)) err = -ENODEV;
- break;
-
- case SDLA_S514:
- if (!detect_s514(hw)) err = -ENODEV;
- break;
-
- default:
- if (detect_s502a(port))
- hw->type = SDLA_S502A;
- else if (detect_s502e(port))
- hw->type = SDLA_S502E;
- else if (detect_s503(port))
- hw->type = SDLA_S503;
- else if (detect_s507(port))
- hw->type = SDLA_S507;
- else if (detect_s508(port))
- hw->type = SDLA_S508;
- else err = -ENODEV;
- }
- return err;
-}
-
-/*============================================================================
- * Autoselect memory region.
- * o try all available DMP address options from the top down until success.
- */
-static int sdla_autodpm (sdlahw_t* hw)
-{
- int i, err = -EINVAL;
- unsigned* opt;
-
- switch (hw->type) {
- case SDLA_S502A:
- opt = s502a_dpmbase_options;
- break;
-
- case SDLA_S502E:
- case SDLA_S503:
- case SDLA_S508:
- opt = s508_dpmbase_options;
- break;
-
- case SDLA_S507:
- opt = s507_dpmbase_options;
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Start testing from 8th position, address
- * 0xC8000 from the 508 address table.
- * We don't want to test A**** addresses, since
- * they are usually used for Video */
- for (i = 8; i <= opt[0] && err; i++) {
- hw->dpmbase = phys_to_virt(opt[i]);
- err = sdla_setdpm(hw);
- }
- return err;
-}
-
-/*============================================================================
- * Set up adapter dual-port memory window.
- * o shut down adapter
- * o make sure that no physical memory exists in this region, i.e entire
- * region reads 0xFF and is not writable when adapter is shut down.
- * o initialize adapter hardware
- * o make sure that region is usable with SDLA card, i.e. we can write to it
- * when adapter is configured.
- */
-static int sdla_setdpm (sdlahw_t* hw)
-{
- int err;
-
- /* Shut down card and verify memory region */
- sdla_down(hw);
- if (check_memregion(hw->dpmbase, hw->dpmsize))
- return -EINVAL;
-
- /* Initialize adapter and test on-board memory segment by segment.
- * If memory size appears to be less than shared memory window size,
- * assume that memory region is unusable.
- */
- err = sdla_init(hw);
- if (err) return err;
-
- if (sdla_memtest(hw) < hw->dpmsize) { /* less than window size */
- sdla_down(hw);
- return -EIO;
- }
- sdla_mapmem(hw, 0L); /* set window vector at bottom */
- return 0;
-}
-
-/*============================================================================
- * Load adapter from the memory image of the SDLA firmware module.
- * o verify firmware integrity and compatibility
- * o start adapter up
- */
-static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len)
-{
-
- int i;
-
- /* Verify firmware signature */
- if (strcmp(sfm->signature, SFM_SIGNATURE)) {
- printk(KERN_INFO "%s: not SDLA firmware!\n",
- modname);
- return -EINVAL;
- }
-
- /* Verify firmware module format version */
- if (sfm->version != SFM_VERSION) {
- printk(KERN_INFO
- "%s: firmware format %u rejected! Expecting %u.\n",
- modname, sfm->version, SFM_VERSION);
- return -EINVAL;
- }
-
- /* Verify firmware module length and checksum */
- if ((len - offsetof(sfm_t, image) != sfm->info.codesize) ||
- (checksum((void*)&sfm->info,
- sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) {
- printk(KERN_INFO "%s: firmware corrupted!\n", modname);
- return -EINVAL;
- }
-
- /* Announce */
- printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname,
- (sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware",
- sfm->info.codeid);
-
- if(hw->type == SDLA_S514)
- printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n",
- modname, hw->S514_cpu_no[0]);
-
- /* Scan through the list of compatible adapters and make sure our
- * adapter type is listed.
- */
- for (i = 0;
- (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type);
- ++i);
-
- if (i == SFM_MAX_SDLA) {
- printk(KERN_INFO "%s: firmware is not compatible with S%u!\n",
- modname, hw->type);
- return -EINVAL;
- }
-
-
- /* Make sure there is enough on-board memory */
- if (hw->memory < sfm->info.memsize) {
- printk(KERN_INFO
- "%s: firmware needs %lu bytes of on-board memory!\n",
- modname, sfm->info.memsize);
- return -EINVAL;
- }
-
- /* Move code onto adapter */
- if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) {
- printk(KERN_INFO "%s: failed to load code segment!\n",
- modname);
- return -EIO;
- }
-
- /* Prepare boot-time configuration data and kick-off CPU */
- sdla_bootcfg(hw, &sfm->info);
- if (sdla_start(hw, sfm->info.startoffs)) {
- printk(KERN_INFO "%s: Damn... Adapter won't start!\n",
- modname);
- return -EIO;
- }
-
- /* position DPM window over the mailbox and enable interrupts */
- if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) {
- printk(KERN_INFO "%s: adapter hardware failure!\n",
- modname);
- return -EIO;
- }
- hw->fwid = sfm->info.codeid; /* set firmware ID */
- return 0;
-}
-
-/*============================================================================
- * Initialize SDLA hardware: setup memory window, IRQ, etc.
- */
-static int sdla_init (sdlahw_t* hw)
-{
- int i;
-
- for (i = 0; i < SDLA_MAXIORANGE; ++i)
- hw->regs[i] = 0;
-
- switch (hw->type) {
- case SDLA_S502A: return init_s502a(hw);
- case SDLA_S502E: return init_s502e(hw);
- case SDLA_S503: return init_s503(hw);
- case SDLA_S507: return init_s507(hw);
- case SDLA_S508: return init_s508(hw);
- }
- return -EINVAL;
-}
-
-/*============================================================================
- * Test adapter on-board memory.
- * o slide DPM window from the bottom up and test adapter memory segment by
- * segment.
- * Return adapter memory size.
- */
-static unsigned long sdla_memtest (sdlahw_t* hw)
-{
- unsigned long memsize;
- unsigned winsize;
-
- for (memsize = 0, winsize = hw->dpmsize;
- !sdla_mapmem(hw, memsize) &&
- (test_memregion(hw->dpmbase, winsize) == winsize)
- ;
- memsize += winsize)
- ;
- hw->memory = memsize;
- return memsize;
-}
-
-/*============================================================================
- * Prepare boot-time firmware configuration data.
- * o position DPM window
- * o initialize configuration data area
- */
-static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo)
-{
- unsigned char* data;
-
- if (!sfminfo->datasize) return 0; /* nothing to do */
-
- if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)
- return -EIO;
-
- if(hw->type == SDLA_S514)
- data = (void*)(hw->dpmbase + sfminfo->dataoffs);
- else
- data = (void*)((u8 *)hw->dpmbase +
- (sfminfo->dataoffs - hw->vector));
-
- memset_io (data, 0, sfminfo->datasize);
-
- writeb (make_config_byte(hw), &data[0x00]);
-
- switch (sfminfo->codeid) {
- case SFID_X25_502:
- case SFID_X25_508:
- writeb (3, &data[0x01]); /* T1 timer */
- writeb (10, &data[0x03]); /* N2 */
- writeb (7, &data[0x06]); /* HDLC window size */
- writeb (1, &data[0x0B]); /* DTE */
- writeb (2, &data[0x0C]); /* X.25 packet window size */
- writew (128, &data[0x0D]); /* default X.25 data size */
- writew (128, &data[0x0F]); /* maximum X.25 data size */
- break;
- }
- return 0;
-}
-
-/*============================================================================
- * Prepare configuration byte identifying adapter type and CPU clock rate.
- */
-static unsigned char make_config_byte (sdlahw_t* hw)
-{
- unsigned char byte = 0;
-
- switch (hw->pclk) {
- case 5000: byte = 0x01; break;
- case 7200: byte = 0x02; break;
- case 8000: byte = 0x03; break;
- case 10000: byte = 0x04; break;
- case 16000: byte = 0x05; break;
- }
-
- switch (hw->type) {
- case SDLA_S502E: byte |= 0x80; break;
- case SDLA_S503: byte |= 0x40; break;
- }
- return byte;
-}
-
-/*============================================================================
- * Start adapter's CPU.
- * o calculate a pointer to adapter's cold boot entry point
- * o position DPM window
- * o place boot instruction (jp addr) at cold boot entry point
- * o start CPU
- */
-static int sdla_start (sdlahw_t* hw, unsigned addr)
-{
- unsigned port = hw->port;
- unsigned char *bootp;
- int err, tmp, i;
-
- if (!port && (hw->type != SDLA_S514)) return -EFAULT;
-
- switch (hw->type) {
- case SDLA_S502A:
- bootp = hw->dpmbase;
- bootp += 0x66;
- break;
-
- case SDLA_S502E:
- case SDLA_S503:
- case SDLA_S507:
- case SDLA_S508:
- case SDLA_S514:
- bootp = hw->dpmbase;
- break;
-
- default:
- return -EINVAL;
- }
-
- err = sdla_mapmem(hw, 0);
- if (err) return err;
-
- writeb (0xC3, bootp); /* Z80: 'jp' opcode */
- bootp ++;
- writew (addr, bootp);
-
- switch (hw->type) {
- case SDLA_S502A:
- _OUTB(port, 0x10); /* issue NMI to CPU */
- hw->regs[0] = 0x10;
- break;
-
- case SDLA_S502E:
- _OUTB(port + 3, 0x01); /* start CPU */
- hw->regs[3] = 0x01;
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (_INB(port) & 0x01) { /* verify */
- /*
- * Enabling CPU changes functionality of the
- * control register, so we have to reset its
- * mirror.
- */
- _OUTB(port, 0); /* disable interrupts */
- hw->regs[0] = 0;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- tmp = hw->regs[0] | 0x09; /* set bits 0 and 3 */
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (!(_INB(port) & 0x01)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S507:
- tmp = hw->regs[0] | 0x02;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (!(_INB(port) & 0x04)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S508:
- tmp = hw->regs[0] | 0x02;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (!(_INB(port + 1) & 0x02)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S514:
- writeb (S514_CPU_START, hw->vector);
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/*============================================================================
- * Initialize S502A adapter.
- */
-static int init_s502a (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s502a(port))
- return -ENODEV;
-
- hw->regs[0] = 0x08;
- hw->regs[1] = 0xFF;
-
- /* Verify configuration options */
- i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s502a_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Setup dual-port memory window (this also enables memory access) */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
- hw->regs[0] = 0x08;
- return 0;
-}
-
-/*============================================================================
- * Initialize S502E adapter.
- */
-static int init_s502e (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s502e(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s502e_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Setup dual-port memory window */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- _OUTB(port, 0x02);
- hw->regs[0] = 0x02;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- return (_INB(port) & 0x02) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Initialize S503 adapter.
- * ---------------------------------------------------------------------------
- */
-static int init_s503 (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s503(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s502e_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Setup dual-port memory window */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- _OUTB(port, 0x02);
- hw->regs[0] = 0x02; /* update mirror */
- return 0;
-}
-
-/*============================================================================
- * Initialize S507 adapter.
- */
-static int init_s507 (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s507(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s507_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Enable adapter's logic */
- _OUTB(port, 0x01);
- hw->regs[0] = 0x01;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (!(_INB(port) & 0x20))
- return -EIO;
-
- /* Setup dual-port memory window */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- tmp = hw->regs[0] | 0x04;
- if (hw->irq) {
- i = get_option_index(s508_irq_options, hw->irq);
- if (i) tmp |= s507_irqmask[i - 1];
- }
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- return (_INB(port) & 0x08) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Initialize S508 adapter.
- */
-static int init_s508 (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s508(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- /* Setup memory configuration */
- tmp = s508_hmcr[i - 1];
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- _OUTB(port, 0x04);
- hw->regs[0] = 0x04; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- return (_INB(port + 1) & 0x04) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Detect S502A adapter.
- * Following tests are used to detect S502A adapter:
- * 1. All registers other than status (BASE) should read 0xFF
- * 2. After writing 00001000b to control register, status register should
- * read 01000000b.
- * 3. After writing 0 to control register, status register should still
- * read 01000000b.
- * 4. After writing 00000100b to control register, status register should
- * read 01000100b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s502a (int port)
-{
- int i, j;
-
- if (!get_option_index(s502_port_options, port))
- return 0;
-
- for (j = 1; j < SDLA_MAXIORANGE; ++j) {
- if (_INB(port + j) != 0xFF)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port, 0x08); /* halt CPU */
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0x40)
- return 0;
- _OUTB(port, 0x00);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0x40)
- return 0;
- _OUTB(port, 0x04);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0x44)
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- _OUTB(port + 1, 0xFF);
- return 1;
-}
-
-/*============================================================================
- * Detect S502E adapter.
- * Following tests are used to verify adapter presence:
- * 1. All registers other than status (BASE) should read 0xFF.
- * 2. After writing 0 to CPU control register (BASE+3), status register
- * (BASE) should read 11111000b.
- * 3. After writing 00000100b to port BASE (set bit 2), status register
- * (BASE) should read 11111100b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s502e (int port)
-{
- int i, j;
-
- if (!get_option_index(s502_port_options, port))
- return 0;
- for (j = 1; j < SDLA_MAXIORANGE; ++j) {
- if (_INB(port + j) != 0xFF)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port + 3, 0); /* CPU control reg. */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xF8) /* read status */
- return 0;
- _OUTB(port, 0x04); /* set bit 2 */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xFC) /* verify */
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0);
- return 1;
-}
-
-/*============================================================================
- * Detect s503 adapter.
- * Following tests are used to verify adapter presence:
- * 1. All registers other than status (BASE) should read 0xFF.
- * 2. After writing 0 to control register (BASE), status register (BASE)
- * should read 11110000b.
- * 3. After writing 00000100b (set bit 2) to control register (BASE),
- * status register should read 11110010b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s503 (int port)
-{
- int i, j;
-
- if (!get_option_index(s503_port_options, port))
- return 0;
- for (j = 1; j < SDLA_MAXIORANGE; ++j) {
- if (_INB(port + j) != 0xFF)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port, 0); /* reset control reg.*/
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xF0) /* read status */
- return 0;
- _OUTB(port, 0x04); /* set bit 2 */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xF2) /* verify */
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0);
- return 1;
-}
-
-/*============================================================================
- * Detect s507 adapter.
- * Following tests are used to detect s507 adapter:
- * 1. All ports should read the same value.
- * 2. After writing 0x00 to control register, status register should read
- * ?011000?b.
- * 3. After writing 0x01 to control register, status register should read
- * ?011001?b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s507 (int port)
-{
- int tmp, i, j;
-
- if (!get_option_index(s508_port_options, port))
- return 0;
- tmp = _INB(port);
- for (j = 1; j < S507_IORANGE; ++j) {
- if (_INB(port + j) != tmp)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port, 0x00);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port) & 0x7E) != 0x30)
- return 0;
- _OUTB(port, 0x01);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port) & 0x7E) != 0x32)
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0x00);
- return 1;
-}
-
-/*============================================================================
- * Detect s508 adapter.
- * Following tests are used to detect s508 adapter:
- * 1. After writing 0x00 to control register, status register should read
- * ??000000b.
- * 2. After writing 0x10 to control register, status register should read
- * ??010000b
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s508 (int port)
-{
- int i;
-
- if (!get_option_index(s508_port_options, port))
- return 0;
- _OUTB(port, 0x00);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port + 1) & 0x3F) != 0x00)
- return 0;
- _OUTB(port, 0x10);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port + 1) & 0x3F) != 0x10)
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0x00);
- return 1;
-}
-
-/*============================================================================
- * Detect s514 PCI adapter.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s514 (sdlahw_t* hw)
-{
- unsigned char CPU_no, slot_no, auto_slot_cfg;
- int number_S514_cards = 0;
- u32 S514_mem_base_addr = 0;
- u32 ut_u32;
- struct pci_dev *pci_dev;
-
-
-#ifndef CONFIG_PCI
- printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname);
- return 0;
-#endif
-
- /*
- The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the
- slot number defined in 'router.conf' via the 'port' definition.
- */
- CPU_no = hw->S514_cpu_no[0];
- slot_no = hw->S514_slot_no;
- auto_slot_cfg = hw->auto_pci_cfg;
-
- if (auto_slot_cfg){
- printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n",
- modname, CPU_no);
-
- }else{
- printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n",
- modname, CPU_no, slot_no);
- }
-
- /* check to see that CPU A or B has been selected in 'router.conf' */
- switch(CPU_no) {
- case S514_CPU_A:
- case S514_CPU_B:
- break;
-
- default:
- printk(KERN_INFO "%s: S514 CPU definition invalid.\n",
- modname);
- printk(KERN_INFO "Must be 'A' or 'B'\n");
- return 0;
- }
-
- number_S514_cards = find_s514_adapter(hw, 0);
- if(!number_S514_cards)
- return 0;
-
- /* we are using a single S514 adapter with a slot of 0 so re-read the */
- /* location of this adapter */
- if((number_S514_cards == 1) && auto_slot_cfg) {
- number_S514_cards = find_s514_adapter(hw, 1);
- if(!number_S514_cards) {
- printk(KERN_INFO "%s: Error finding PCI card\n",
- modname);
- return 0;
- }
- }
-
- pci_dev = hw->pci_dev;
- /* read the physical memory base address */
- S514_mem_base_addr = (CPU_no == S514_CPU_A) ?
- (pci_dev->resource[1].start) :
- (pci_dev->resource[2].start);
-
- printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
- modname, S514_mem_base_addr);
- if(!S514_mem_base_addr) {
- if(CPU_no == S514_CPU_B)
- printk(KERN_INFO "%s: CPU #B not present on the card\n", modname);
- else
- printk(KERN_INFO "%s: No PCI memory allocated to card\n", modname);
- return 0;
- }
-
- /* enable the PCI memory */
- pci_read_config_dword(pci_dev,
- (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
- &ut_u32);
- pci_write_config_dword(pci_dev,
- (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
- (ut_u32 | PCI_MEMORY_ENABLE));
-
- /* check the IRQ allocated and enable IRQ usage */
- if(!(hw->irq = pci_dev->irq)) {
- printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
- modname);
- return 0;
- }
-
- /* BUG FIX : Mar 6 2000
- * On a initial loading of the card, we must check
- * and clear PCI interrupt bits, due to a reset
- * problem on some other boards. i.e. An interrupt
- * might be pending, even after system bootup,
- * in which case, when starting wanrouter the machine
- * would crash.
- */
- if (init_pci_slot(hw))
- return 0;
-
- pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32);
- ut_u32 |= (CPU_no == S514_CPU_A) ?
- PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
- pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
-
- printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
- modname, hw->irq);
-
- /* map the physical PCI memory to virtual memory */
- hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
- (unsigned long)MAX_SIZEOF_S514_MEMORY);
- /* map the physical control register memory to virtual memory */
- hw->vector = (unsigned long)ioremap(
- (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
- (unsigned long)16);
-
- if(!hw->dpmbase || !hw->vector) {
- printk(KERN_INFO "%s: PCI virtual memory allocation failed\n",
- modname);
- return 0;
- }
-
- /* halt the adapter */
- writeb (S514_CPU_HALT, hw->vector);
-
- return 1;
-}
-
-/*============================================================================
- * Find the S514 PCI adapter in the PCI bus.
- * Return the number of S514 adapters found (0 if no adapter found).
- */
-static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card)
-{
- unsigned char slot_no;
- int number_S514_cards = 0;
- char S514_found_in_slot = 0;
- u16 PCI_subsys_vendor;
-
- struct pci_dev *pci_dev = NULL;
-
- slot_no = hw->S514_slot_no;
-
- while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
- != NULL) {
-
- pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
- &PCI_subsys_vendor);
-
- if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
- continue;
-
- hw->pci_dev = pci_dev;
-
- if(find_first_S514_card)
- return(1);
-
- number_S514_cards ++;
-
- printk(KERN_INFO
- "%s: S514 card found, slot #%d (devfn 0x%X)\n",
- modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
- pci_dev->devfn);
-
- if (hw->auto_pci_cfg){
- hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK);
- slot_no = hw->S514_slot_no;
-
- }else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){
- S514_found_in_slot = 1;
- break;
- }
- }
-
- /* if no S514 adapter has been found, then exit */
- if (!number_S514_cards) {
- printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
- return 0;
- }
- /* if more than one S514 card has been found, then the user must have */ /* defined a slot number so that the correct adapter is used */
- else if ((number_S514_cards > 1) && hw->auto_pci_cfg) {
- printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n"
- "%s: More than one S514 adapter found.\n"
- "%s: Disable the Autodetect feature and supply\n"
- "%s: the PCISLOT numbers for each card.\n",
- modname,modname,modname,modname);
- return 0;
- }
- /* if the user has specified a slot number and the S514 adapter has */
- /* not been found in that slot, then exit */
- else if (!hw->auto_pci_cfg && !S514_found_in_slot) {
- printk(KERN_INFO
- "%s: Error, S514 card not found in specified slot #%d\n",
- modname, slot_no);
- return 0;
- }
-
- return (number_S514_cards);
-}
-
-
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Calibrate SDLA memory access delay.
- * Count number of idle loops made within 1 second and then calculate the
- * number of loops that should be made to achive desired delay.
- */
-static int calibrate_delay (int mks)
-{
- unsigned int delay;
- unsigned long stop;
-
- for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay);
- return (delay/(1000000L/mks) + 1);
-}
-
-/*============================================================================
- * Get option's index into the options list.
- * Return option's index (1 .. N) or zero if option is invalid.
- */
-static int get_option_index (unsigned* optlist, unsigned optval)
-{
- int i;
-
- for (i = 1; i <= optlist[0]; ++i)
- if ( optlist[i] == optval)
- return i;
- return 0;
-}
-
-/*============================================================================
- * Check memory region to see if it's available.
- * Return: 0 ok.
- */
-static unsigned check_memregion (void* ptr, unsigned len)
-{
- volatile unsigned char* p = ptr;
-
- for (; len && (readb (p) == 0xFF); --len, ++p) {
- writeb (0, p); /* attempt to write 0 */
- if (readb(p) != 0xFF) { /* still has to read 0xFF */
- writeb (0xFF, p);/* restore original value */
- break; /* not good */
- }
- }
-
- return len;
-}
-
-/*============================================================================
- * Test memory region.
- * Return: size of the region that passed the test.
- * Note: Region size must be multiple of 2 !
- */
-static unsigned test_memregion (void* ptr, unsigned len)
-{
- volatile unsigned short* w_ptr;
- unsigned len_w = len >> 1; /* region len in words */
- unsigned i;
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- writew (0xAA55, w_ptr);
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- if (readw (w_ptr) != 0xAA55) {
- len_w = i;
- break;
- }
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- writew (0x55AA, w_ptr);
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- if (readw(w_ptr) != 0x55AA) {
- len_w = i;
- break;
- }
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- writew (0, w_ptr);
-
- return len_w << 1;
-}
-
-/*============================================================================
- * Calculate 16-bit CRC using CCITT polynomial.
- */
-static unsigned short checksum (unsigned char* buf, unsigned len)
-{
- unsigned short crc = 0;
- unsigned mask, flag;
-
- for (; len; --len, ++buf) {
- for (mask = 0x80; mask; mask >>= 1) {
- flag = (crc & 0x8000);
- crc <<= 1;
- crc |= ((*buf & mask) ? 1 : 0);
- if (flag) crc ^= 0x1021;
- }
- }
- return crc;
-}
-
-static int init_pci_slot(sdlahw_t *hw)
-{
-
- u32 int_status;
- int volatile found=0;
- int i=0;
-
- /* Check if this is a very first load for a specific
- * pci card. If it is, clear the interrput bits, and
- * set the flag indicating that this card was initialized.
- */
-
- for (i=0; (i<MAX_S514_CARDS) && !found; i++){
- if (pci_slot_ar[i] == hw->S514_slot_no){
- found=1;
- break;
- }
- if (pci_slot_ar[i] == 0xFF){
- break;
- }
- }
-
- if (!found){
- read_S514_int_stat(hw,&int_status);
- S514_intack(hw,int_status);
- if (i == MAX_S514_CARDS){
- printk(KERN_INFO "%s: Critical Error !!!\n",modname);
- printk(KERN_INFO
- "%s: Number of Sangoma PCI cards exceeded maximum limit.\n",
- modname);
- printk(KERN_INFO "Please contact Sangoma Technologies\n");
- return 1;
- }
- pci_slot_ar[i] = hw->S514_slot_no;
- }
- return 0;
-}
-
-static int pci_probe(sdlahw_t *hw)
-{
-
- unsigned char slot_no;
- int number_S514_cards = 0;
- u16 PCI_subsys_vendor;
- u16 PCI_card_type;
-
- struct pci_dev *pci_dev = NULL;
- struct pci_bus *bus = NULL;
-
- slot_no = 0;
-
- while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
- != NULL) {
-
- pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
- &PCI_subsys_vendor);
-
- if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
- continue;
-
- pci_read_config_word(pci_dev, PCI_CARD_TYPE,
- &PCI_card_type);
-
- bus = pci_dev->bus;
-
- /* A dual cpu card can support up to 4 physical connections,
- * where a single cpu card can support up to 2 physical
- * connections. The FT1 card can only support a single
- * connection, however we cannot distinguish between a Single
- * CPU card and an FT1 card. */
- if (PCI_card_type == S514_DUAL_CPU){
- number_S514_cards += 4;
- printk(KERN_INFO
- "wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
- bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
- pci_dev->irq);
- }else{
- number_S514_cards += 2;
- printk(KERN_INFO
- "wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
- bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
- pci_dev->irq);
- }
- }
-
- return number_S514_cards;
-
-}
-
-
-
-EXPORT_SYMBOL(wanpipe_hw_probe);
-
-unsigned wanpipe_hw_probe(void)
-{
- sdlahw_t hw;
- unsigned* opt = s508_port_options;
- unsigned cardno=0;
- int i;
-
- memset(&hw, 0, sizeof(hw));
-
- for (i = 1; i <= opt[0]; i++) {
- if (detect_s508(opt[i])){
- /* S508 card can support up to two physical links */
- cardno+=2;
- printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]);
- }
- }
-
- #ifdef CONFIG_PCI
- hw.S514_slot_no = 0;
- cardno += pci_probe(&hw);
- #else
- printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n");
- printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n");
- #endif
-
- return cardno;
-}
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
deleted file mode 100644
index 7a8b22a7ea31..000000000000
--- a/drivers/net/wan/sdlamain.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/****************************************************************************
-* sdlamain.c WANPIPE(tm) Multiprotocol WAN Link Driver. Main module.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Dec 22, 2000 Nenad Corbic Updated for 2.4.X kernels.
-* Removed the polling routine.
-* Nov 13, 2000 Nenad Corbic Added hw probing on module load and dynamic
-* device allocation.
-* Nov 7, 2000 Nenad Corbic Fixed the Multi-Port PPP for kernels
-* 2.2.16 and above.
-* Aug 2, 2000 Nenad Corbic Block the Multi-Port PPP from running on
-* kernels 2.2.16 or greater. The SyncPPP
-* has changed.
-* Jul 25, 2000 Nenad Corbic Updated the Piggiback support for MultPPPP.
-* Jul 13, 2000 Nenad Corbic Added Multi-PPP support.
-* Feb 02, 2000 Nenad Corbic Fixed up piggyback probing and selection.
-* Sep 23, 1999 Nenad Corbic Added support for SMP
-* Sep 13, 1999 Nenad Corbic Each port is treated as a separate device.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Updates for Linux 2.2.X kernels.
-* Sep 17, 1998 Jaspreet Singh Updated for 2.1.121+ kernel
-* Nov 28, 1997 Jaspreet Singh Changed DRV_RELEASE to 1
-* Nov 10, 1997 Jaspreet Singh Changed sti() to restore_flags();
-* Nov 06, 1997 Jaspreet Singh Changed DRV_VERSION to 4 and DRV_RELEASE to 0
-* Oct 20, 1997 Jaspreet Singh Modified sdla_isr routine so that card->in_isr
-* assignments are taken out and placed in the
-* sdla_ppp.c, sdla_fr.c and sdla_x25.c isr
-* routines. Took out 'wandev->tx_int_enabled' and
-* replaced it with 'wandev->enable_tx_int'.
-* May 29, 1997 Jaspreet Singh Flow Control Problem
-* added "wandev->tx_int_enabled=1" line in the
-* init module. This line initializes the flag for
-* preventing Interrupt disabled with device set to
-* busy
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o added UDP management stuff
-* Jan 02, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-#include <linux/config.h> /* OS configuration options */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/init.h>
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/module.h> /* support for loadable modules */
-#include <linux/ioport.h> /* request_region(), release_region() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/rcupdate.h>
-
-#include <linux/in.h>
-#include <asm/io.h> /* phys_to_virt() */
-#include <linux/pci.h>
-#include <linux/sdlapci.h>
-#include <linux/if_wanpipe_common.h>
-
-#include <asm/uaccess.h> /* kernel <-> user copy */
-#include <linux/inetdevice.h>
-
-#include <linux/ip.h>
-#include <net/route.h>
-
-#define KMEM_SAFETYZONE 8
-
-
-#ifndef CONFIG_WANPIPE_FR
- #define wpf_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_CHDLC
- #define wpc_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_X25
- #define wpx_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_PPP
- #define wpp_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_MULTPPP
- #define wsppp_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-
-/***********FOR DEBUGGING PURPOSES*********************************************
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
- int i = 0;
- void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
- char * c1 = v;
- c1 += sizeof(unsigned int);
- *((unsigned int *)v) = size;
-
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
- c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
- c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
- c1 += 8;
- }
- v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
- printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v);
- return v;
-}
-static void dbg_kfree(void * v, int line) {
- unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
- unsigned int size = *sp;
- char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
- int i = 0;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
- || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
- || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
- ) {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- printk(KERN_INFO "line %d kfree(%p)\n",line,v);
- v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
- kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-******************************************************************************/
-
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef _DEBUG_
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-#define DRV_VERSION 5 /* version number */
-#define DRV_RELEASE 0 /* release (minor version) number */
-#define MAX_CARDS 16 /* max number of adapters */
-
-#ifndef CONFIG_WANPIPE_CARDS /* configurable option */
-#define CONFIG_WANPIPE_CARDS 1
-#endif
-
-#define CMD_OK 0 /* normal firmware return code */
-#define CMD_TIMEOUT 0xFF /* firmware command timed out */
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-/****** Function Prototypes *************************************************/
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/* WAN link driver entry points */
-static int setup(struct wan_device* wandev, wandev_conf_t* conf);
-static int shutdown(struct wan_device* wandev);
-static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg);
-
-/* IOCTL handlers */
-static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump);
-static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int);
-
-/* Miscellaneous functions */
-STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs);
-static void release_hw (sdla_t *card);
-
-static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
-static int check_s514_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
-
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-/* private data */
-static char drvname[] = "wanpipe";
-static char fullname[] = "WANPIPE(tm) Multiprotocol Driver";
-static char copyright[] = "(c) 1995-2000 Sangoma Technologies Inc.";
-static int ncards;
-static sdla_t* card_array; /* adapter data space */
-
-/* Wanpipe's own workqueue, used for all API's.
- * All protocol specific tasks will be inserted
- * into the "wanpipe_wq" workqueue.
-
- * The kernel workqueue mechanism will execute
- * all pending tasks in the "wanpipe_wq" workqueue.
- */
-
-struct workqueue_struct *wanpipe_wq;
-DECLARE_WORK(wanpipe_work, NULL, NULL);
-
-static int wanpipe_bh_critical;
-
-/******* Kernel Loadable Module Entry Points ********************************/
-
-/*============================================================================
- * Module 'insert' entry point.
- * o print announcement
- * o allocate adapter data space
- * o initialize static data
- * o register all cards with WAN router
- * o calibrate SDLA shared memory access delay.
- *
- * Return: 0 Ok
- * < 0 error.
- * Context: process
- */
-
-static int __init wanpipe_init(void)
-{
- int cnt, err = 0;
-
- printk(KERN_INFO "%s v%u.%u %s\n",
- fullname, DRV_VERSION, DRV_RELEASE, copyright);
-
- wanpipe_wq = create_workqueue("wanpipe_wq");
- if (!wanpipe_wq)
- return -ENOMEM;
-
- /* Probe for wanpipe cards and return the number found */
- printk(KERN_INFO "wanpipe: Probing for WANPIPE hardware.\n");
- ncards = wanpipe_hw_probe();
- if (ncards){
- printk(KERN_INFO "wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n",ncards,1,ncards);
- }else{
- printk(KERN_INFO "wanpipe: No S514/S508 cards found, unloading modules!\n");
- destroy_workqueue(wanpipe_wq);
- return -ENODEV;
- }
-
- /* Verify number of cards and allocate adapter data space */
- card_array = kmalloc(sizeof(sdla_t) * ncards, GFP_KERNEL);
- if (card_array == NULL) {
- destroy_workqueue(wanpipe_wq);
- return -ENOMEM;
- }
-
- memset(card_array, 0, sizeof(sdla_t) * ncards);
-
- /* Register adapters with WAN router */
- for (cnt = 0; cnt < ncards; ++ cnt) {
- sdla_t* card = &card_array[cnt];
- struct wan_device* wandev = &card->wandev;
-
- card->next = NULL;
- sprintf(card->devname, "%s%d", drvname, cnt + 1);
- wandev->magic = ROUTER_MAGIC;
- wandev->name = card->devname;
- wandev->private = card;
- wandev->enable_tx_int = 0;
- wandev->setup = &setup;
- wandev->shutdown = &shutdown;
- wandev->ioctl = &ioctl;
- err = register_wan_device(wandev);
- if (err) {
- printk(KERN_INFO
- "%s: %s registration failed with error %d!\n",
- drvname, card->devname, err);
- break;
- }
- }
- if (cnt){
- ncards = cnt; /* adjust actual number of cards */
- }else {
- kfree(card_array);
- destroy_workqueue(wanpipe_wq);
- printk(KERN_INFO "IN Init Module: NO Cards registered\n");
- err = -ENODEV;
- }
-
- return err;
-}
-
-/*============================================================================
- * Module 'remove' entry point.
- * o unregister all adapters from the WAN router
- * o release all remaining system resources
- */
-static void __exit wanpipe_cleanup(void)
-{
- int i;
-
- if (!ncards)
- return;
-
- for (i = 0; i < ncards; ++i) {
- sdla_t* card = &card_array[i];
- unregister_wan_device(card->devname);
- }
- destroy_workqueue(wanpipe_wq);
- kfree(card_array);
-
- printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n");
-}
-
-module_init(wanpipe_init);
-module_exit(wanpipe_cleanup);
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Setup/configure WAN link driver.
- * o check adapter state
- * o make sure firmware is present in configuration
- * o make sure I/O port and IRQ are specified
- * o make sure I/O region is available
- * o allocate interrupt vector
- * o setup SDLA hardware
- * o call appropriate routine to perform protocol-specific initialization
- * o mark I/O region as used
- * o if this is the first active card, then schedule background task
- *
- * This function is called when router handles ROUTER_SETUP IOCTL. The
- * configuration structure is in kernel memory (including extended data, if
- * any).
- */
-
-static int setup(struct wan_device* wandev, wandev_conf_t* conf)
-{
- sdla_t* card;
- int err = 0;
- int irq=0;
-
- /* Sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)){
- printk(KERN_INFO
- "%s: Failed Sdlamain Setup wandev %u, card %u, conf %u !\n",
- wandev->name,
- (unsigned int)wandev,(unsigned int)wandev->private,
- (unsigned int)conf);
- return -EFAULT;
- }
-
- printk(KERN_INFO "%s: Starting WAN Setup\n", wandev->name);
-
- card = wandev->private;
- if (wandev->state != WAN_UNCONFIGURED){
- printk(KERN_INFO "%s: failed sdlamain setup, busy!\n",
- wandev->name);
- return -EBUSY; /* already configured */
- }
-
- printk(KERN_INFO "\nProcessing WAN device %s...\n", wandev->name);
-
- /* Initialize the counters for each wandev
- * Used for counting number of times new_if and
- * del_if get called.
- */
- wandev->del_if_cnt = 0;
- wandev->new_if_cnt = 0;
- wandev->config_id = conf->config_id;
-
- if (!conf->data_size || (conf->data == NULL)) {
- printk(KERN_INFO
- "%s: firmware not found in configuration data!\n",
- wandev->name);
- return -EINVAL;
- }
-
- /* Check for resource conflicts and setup the
- * card for piggibacking if necessary */
- if(!conf->S514_CPU_no[0]) {
- if ((err=check_s508_conflicts(card,conf,&irq)) != 0){
- return err;
- }
- }else {
- if ((err=check_s514_conflicts(card,conf,&irq)) != 0){
- return err;
- }
- }
-
- /* If the current card has already been configured
- * or it's a piggyback card, do not try to allocate
- * resources.
- */
- if (!card->wandev.piggyback && !card->configured){
-
- /* Configure hardware, load firmware, etc. */
- memset(&card->hw, 0, sizeof(sdlahw_t));
-
- /* for an S514 adapter, pass the CPU number and the slot number read */
- /* from 'router.conf' to the 'sdla_setup()' function via the 'port' */
- /* parameter */
- if (conf->S514_CPU_no[0]){
-
- card->hw.S514_cpu_no[0] = conf->S514_CPU_no[0];
- card->hw.S514_slot_no = conf->PCI_slot_no;
- card->hw.auto_pci_cfg = conf->auto_pci_cfg;
-
- if (card->hw.auto_pci_cfg == WANOPT_YES){
- printk(KERN_INFO "%s: Setting CPU to %c and Slot to Auto\n",
- card->devname, card->hw.S514_cpu_no[0]);
- }else{
- printk(KERN_INFO "%s: Setting CPU to %c and Slot to %i\n",
- card->devname, card->hw.S514_cpu_no[0], card->hw.S514_slot_no);
- }
-
- }else{
- /* 508 Card io port and irq initialization */
- card->hw.port = conf->ioport;
- card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
- }
-
-
- /* Compute the virtual address of the card in kernel space */
- if(conf->maddr){
- card->hw.dpmbase = phys_to_virt(conf->maddr);
- }else{
- card->hw.dpmbase = (void *)conf->maddr;
- }
-
- card->hw.dpmsize = SDLA_WINDOWSIZE;
-
- /* set the adapter type if using an S514 adapter */
- card->hw.type = (conf->S514_CPU_no[0]) ? SDLA_S514 : conf->hw_opt[0];
- card->hw.pclk = conf->hw_opt[1];
-
- err = sdla_setup(&card->hw, conf->data, conf->data_size);
- if (err){
- printk(KERN_INFO "%s: Hardware setup Failed %i\n",
- card->devname,err);
- return err;
- }
-
- if(card->hw.type != SDLA_S514)
- irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
- else
- irq = card->hw.irq;
-
- /* request an interrupt vector - note that interrupts may be shared */
- /* when using the S514 PCI adapter */
-
- if(request_irq(irq, sdla_isr,
- (card->hw.type == SDLA_S514) ? SA_SHIRQ : 0,
- wandev->name, card)){
-
- printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq);
- return -EINVAL;
- }
-
- }else{
- printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n",
- wandev->name,card->configured,card->wandev.piggyback);
- }
-
-
- if (!card->configured){
-
- /* Initialize the Spin lock */
- printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);
-
- /* Piggyback spin lock has already been initialized,
- * in check_s514/s508_conflicts() */
- if (!card->wandev.piggyback){
- spin_lock_init(&card->wandev.lock);
- }
-
- /* Intialize WAN device data space */
- wandev->irq = irq;
- wandev->dma = 0;
- if(card->hw.type != SDLA_S514){
- wandev->ioport = card->hw.port;
- }else{
- wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0];
- wandev->S514_slot_no = card->hw.S514_slot_no;
- }
- wandev->maddr = (unsigned long)card->hw.dpmbase;
- wandev->msize = card->hw.dpmsize;
- wandev->hw_opt[0] = card->hw.type;
- wandev->hw_opt[1] = card->hw.pclk;
- wandev->hw_opt[2] = card->hw.memory;
- wandev->hw_opt[3] = card->hw.fwid;
- }
-
- /* Protocol-specific initialization */
- switch (card->hw.fwid) {
-
- case SFID_X25_502:
- case SFID_X25_508:
- printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n",
- card->devname);
- err = wpx_init(card, conf);
- break;
- case SFID_FR502:
- case SFID_FR508:
- printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n",
- card->devname);
- err = wpf_init(card, conf);
- break;
- case SFID_PPP502:
- case SFID_PPP508:
- printk(KERN_INFO "%s: Starting PPP Protocol Init.\n",
- card->devname);
- err = wpp_init(card, conf);
- break;
-
- case SFID_CHDLC508:
- case SFID_CHDLC514:
- if (conf->ft1){
- printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n",
- card->devname);
- err = wpft1_init(card, conf);
- break;
-
- }else if (conf->config_id == WANCONFIG_MPPP){
- printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n",
- card->devname);
- err = wsppp_init(card,conf);
- break;
-
- }else{
- printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n",
- card->devname);
- err = wpc_init(card, conf);
- break;
- }
- default:
- printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n",
- wandev->name,card->hw.fwid,SFID_CHDLC508);
- err = -EPROTONOSUPPORT;
- }
-
- if (err != 0){
- if (err == -EPROTONOSUPPORT){
- printk(KERN_INFO
- "%s: Error, Protocol selected has not been compiled!\n",
- card->devname);
- printk(KERN_INFO
- "%s: Re-configure the kernel and re-build the modules!\n",
- card->devname);
- }
-
- release_hw(card);
- wandev->state = WAN_UNCONFIGURED;
- return err;
- }
-
-
- /* Reserve I/O region and schedule background task */
- if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)
- if (!request_region(card->hw.port, card->hw.io_range,
- wandev->name)) {
- printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port);
- release_hw(card);
- wandev->state = WAN_UNCONFIGURED;
- return -EBUSY;
- }
-
- /* Only use the polling routine for the X25 protocol */
-
- card->wandev.critical=0;
- return 0;
-}
-
-/*==================================================================
- * configure_s508_card
- *
- * For a S508 adapter, check for a possible configuration error in that
- * we are loading an adapter in the same IO port as a previously loaded S508
- * card.
- */
-
-static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq)
-{
- unsigned long smp_flags;
- int i;
-
- if (conf->ioport <= 0) {
- printk(KERN_INFO
- "%s: can't configure without I/O port address!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
- if (conf->irq <= 0) {
- printk(KERN_INFO "%s: can't configure without IRQ!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
- if (test_bit(0,&card->configured))
- return 0;
-
-
- /* Check for already loaded card with the same IO port and IRQ
- * If found, copy its hardware configuration and use its
- * resources (i.e. piggybacking)
- */
-
- for (i = 0; i < ncards; i++) {
- sdla_t *nxt_card = &card_array[i];
-
- /* Skip the current card ptr */
- if (nxt_card == card)
- continue;
-
-
- /* Find a card that is already configured with the
- * same IO Port */
- if ((nxt_card->hw.type == SDLA_S508) &&
- (nxt_card->hw.port == conf->ioport) &&
- (nxt_card->next == NULL)){
-
- /* We found a card the card that has same configuration
- * as us. This means, that we must setup this card in
- * piggibacking mode. However, only CHDLC and MPPP protocol
- * support this setup */
-
- if ((conf->config_id == WANCONFIG_CHDLC ||
- conf->config_id == WANCONFIG_MPPP) &&
- (nxt_card->wandev.config_id == WANCONFIG_CHDLC ||
- nxt_card->wandev.config_id == WANCONFIG_MPPP)){
-
- *irq = nxt_card->hw.irq;
- memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
-
- /* The master could already be running, we must
- * set this as a critical area */
- lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
-
- nxt_card->next = card;
- card->next = nxt_card;
-
- card->wandev.piggyback = WANOPT_YES;
-
- /* We must initialise the piggiback spin lock here
- * since isr will try to lock card->next if it
- * exists */
- spin_lock_init(&card->wandev.lock);
-
- unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
- break;
- }else{
- /* Trying to run piggibacking with a wrong protocol */
- printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n"
- "%s: This protocol doesn't support\n"
- "%s: multi-port operation!\n",
- card->devname,nxt_card->hw.port,
- card->devname,card->devname);
- return -EEXIST;
- }
- }
- }
-
-
- /* Make sure I/O port region is available only if we are the
- * master device. If we are running in piggybacking mode,
- * we will use the resources of the master card. */
- if (!card->wandev.piggyback) {
- struct resource *rr =
- request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain");
- release_region(conf->ioport, SDLA_MAXIORANGE);
-
- if (!rr) {
- printk(KERN_INFO
- "%s: I/O region 0x%X - 0x%X is in use!\n",
- card->wandev.name, conf->ioport,
- conf->ioport + SDLA_MAXIORANGE - 1);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-/*==================================================================
- * configure_s514_card
- *
- * For a S514 adapter, check for a possible configuration error in that
- * we are loading an adapter in the same slot as a previously loaded S514
- * card.
- */
-
-
-static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq)
-{
- unsigned long smp_flags;
- int i;
-
- if (test_bit(0,&card->configured))
- return 0;
-
-
- /* Check for already loaded card with the same IO port and IRQ
- * If found, copy its hardware configuration and use its
- * resources (i.e. piggybacking)
- */
-
- for (i = 0; i < ncards; i ++) {
-
- sdla_t* nxt_card = &card_array[i];
- if(nxt_card == card)
- continue;
-
- if((nxt_card->hw.type == SDLA_S514) &&
- (nxt_card->hw.S514_slot_no == conf->PCI_slot_no) &&
- (nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&&
- (nxt_card->next == NULL)){
-
-
- if ((conf->config_id == WANCONFIG_CHDLC ||
- conf->config_id == WANCONFIG_MPPP) &&
- (nxt_card->wandev.config_id == WANCONFIG_CHDLC ||
- nxt_card->wandev.config_id == WANCONFIG_MPPP)){
-
- *irq = nxt_card->hw.irq;
- memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
-
- /* The master could already be running, we must
- * set this as a critical area */
- lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
- nxt_card->next = card;
- card->next = nxt_card;
-
- card->wandev.piggyback = WANOPT_YES;
-
- /* We must initialise the piggiback spin lock here
- * since isr will try to lock card->next if it
- * exists */
- spin_lock_init(&card->wandev.lock);
-
- unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
-
- }else{
- /* Trying to run piggibacking with a wrong protocol */
- printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n"
- "%s: This protocol doesn't support\n"
- "%s: multi-port operation!\n",
- card->devname,
- conf->S514_CPU_no[0],conf->PCI_slot_no,
- card->devname,card->devname);
- return -EEXIST;
- }
- }
- }
-
- return 0;
-}
-
-
-
-/*============================================================================
- * Shut down WAN link driver.
- * o shut down adapter hardware
- * o release system resources.
- *
- * This function is called by the router when device is being unregistered or
- * when it handles ROUTER_DOWN IOCTL.
- */
-static int shutdown(struct wan_device* wandev)
-{
- sdla_t *card;
- int err=0;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL)){
- return -EFAULT;
- }
-
- if (wandev->state == WAN_UNCONFIGURED){
- return 0;
- }
-
- card = wandev->private;
-
- if (card->tty_opt){
- if (card->tty_open){
- printk(KERN_INFO
- "%s: Shutdown Failed: TTY is still open\n",
- card->devname);
- return -EBUSY;
- }
- }
-
- wandev->state = WAN_UNCONFIGURED;
-
- set_bit(PERI_CRIT,(void*)&wandev->critical);
-
- /* In case of piggibacking, make sure that
- * we never try to shutdown both devices at the same
- * time, because they depend on one another */
-
- if (card->disable_comm){
- card->disable_comm(card);
- }
-
- /* Release Resources */
- release_hw(card);
-
- /* only free the allocated I/O range if not an S514 adapter */
- if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){
- release_region(card->hw.port, card->hw.io_range);
- }
-
- if (!card->configured){
- memset(&card->hw, 0, sizeof(sdlahw_t));
- if (card->next){
- memset(&card->next->hw, 0, sizeof(sdlahw_t));
- }
- }
-
-
- clear_bit(PERI_CRIT,(void*)&wandev->critical);
- return err;
-}
-
-static void release_hw (sdla_t *card)
-{
- sdla_t *nxt_card;
-
-
- /* Check if next device exists */
- if (card->next){
- nxt_card = card->next;
- /* If next device is down then release resources */
- if (nxt_card->wandev.state == WAN_UNCONFIGURED){
- if (card->wandev.piggyback){
- /* If this device is piggyback then use
- * information of the master device
- */
- printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname);
- sdla_down(&card->next->hw);
- free_irq(card->wandev.irq, card->next);
- card->configured = 0;
- card->next->configured = 0;
- card->wandev.piggyback = 0;
- }else{
- /* Master device shutting down */
- printk(KERN_INFO "%s: Master shutting down\n",card->devname);
- sdla_down(&card->hw);
- free_irq(card->wandev.irq, card);
- card->configured = 0;
- card->next->configured = 0;
- }
- }else{
- printk(KERN_INFO "%s: Device still running %i\n",
- nxt_card->devname,nxt_card->wandev.state);
-
- card->configured = 1;
- }
- }else{
- printk(KERN_INFO "%s: Master shutting down\n",card->devname);
- sdla_down(&card->hw);
- free_irq(card->wandev.irq, card);
- card->configured = 0;
- }
- return;
-}
-
-
-/*============================================================================
- * Driver I/O control.
- * o verify arguments
- * o perform requested action
- *
- * This function is called when router handles one of the reserved user
- * IOCTLs. Note that 'arg' stil points to user address space.
- */
-static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg)
-{
- sdla_t* card;
- int err;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- card = wandev->private;
-
- if(card->hw.type != SDLA_S514){
- disable_irq(card->hw.irq);
- }
-
- if (test_bit(SEND_CRIT, (void*)&wandev->critical)) {
- return -EAGAIN;
- }
-
- switch (cmd) {
- case WANPIPE_DUMP:
- err = ioctl_dump(wandev->private, (void*)arg);
- break;
-
- case WANPIPE_EXEC:
- err = ioctl_exec(wandev->private, (void*)arg, cmd);
- break;
- default:
- err = -EINVAL;
- }
-
- return err;
-}
-
-/****** Driver IOCTL Handlers ***********************************************/
-
-/*============================================================================
- * Dump adapter memory to user buffer.
- * o verify request structure
- * o copy request structure to kernel data space
- * o verify length/offset
- * o verify user buffer
- * o copy adapter memory image to user buffer
- *
- * Note: when dumping memory, this routine switches curent dual-port memory
- * vector, so care must be taken to avoid racing conditions.
- */
-static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
-{
- sdla_dump_t dump;
- unsigned winsize;
- unsigned long oldvec; /* DPM window vector */
- unsigned long smp_flags;
- int err = 0;
-
- if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))
- return -EFAULT;
-
- if ((dump.magic != WANPIPE_MAGIC) ||
- (dump.offset + dump.length > card->hw.memory))
- return -EINVAL;
-
- winsize = card->hw.dpmsize;
-
- if(card->hw.type != SDLA_S514) {
-
- lock_adapter_irq(&card->wandev.lock, &smp_flags);
-
- oldvec = card->hw.vector;
- while (dump.length) {
- /* current offset */
- unsigned pos = dump.offset % winsize;
- /* current vector */
- unsigned long vec = dump.offset - pos;
- unsigned len = (dump.length > (winsize - pos)) ?
- (winsize - pos) : dump.length;
- /* relocate window */
- if (sdla_mapmem(&card->hw, vec) != 0) {
- err = -EIO;
- break;
- }
-
- if(copy_to_user((void *)dump.ptr,
- (u8 *)card->hw.dpmbase + pos, len)){
-
- unlock_adapter_irq(&card->wandev.lock, &smp_flags);
- return -EFAULT;
- }
-
- dump.length -= len;
- dump.offset += len;
- dump.ptr = (char*)dump.ptr + len;
- }
-
- sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
- unlock_adapter_irq(&card->wandev.lock, &smp_flags);
-
- }else {
-
- if(copy_to_user((void *)dump.ptr,
- (u8 *)card->hw.dpmbase + dump.offset, dump.length)){
- return -EFAULT;
- }
- }
-
- return err;
-}
-
-/*============================================================================
- * Execute adapter firmware command.
- * o verify request structure
- * o copy request structure to kernel data space
- * o call protocol-specific 'exec' function
- */
-static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd)
-{
- sdla_exec_t exec;
- int err=0;
-
- if (card->exec == NULL && cmd == WANPIPE_EXEC){
- return -ENODEV;
- }
-
- if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))
- return -EFAULT;
-
- if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))
- return -EINVAL;
-
- switch (cmd) {
- case WANPIPE_EXEC:
- err = card->exec(card, exec.cmd, exec.data);
- break;
- }
- return err;
-}
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * SDLA Interrupt Service Routine.
- * o acknowledge SDLA hardware interrupt.
- * o call protocol-specific interrupt service routine, if any.
- */
-STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs)
-{
-#define card ((sdla_t*)dev_id)
-
- if(card->hw.type == SDLA_S514) { /* handle interrrupt on S514 */
- u32 int_status;
- unsigned char CPU_no = card->hw.S514_cpu_no[0];
- unsigned char card_found_for_IRQ;
- u8 IRQ_count = 0;
-
- for(;;) {
-
- read_S514_int_stat(&card->hw, &int_status);
-
- /* check if the interrupt is for this device */
- if(!((unsigned char)int_status &
- (IRQ_CPU_A | IRQ_CPU_B)))
- return IRQ_HANDLED;
-
- /* if the IRQ is for both CPUs on the same adapter, */
- /* then alter the interrupt status so as to handle */
- /* one CPU at a time */
- if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B))
- == (IRQ_CPU_A | IRQ_CPU_B)) {
- int_status &= (CPU_no == S514_CPU_A) ?
- ~IRQ_CPU_B : ~IRQ_CPU_A;
- }
-
- card_found_for_IRQ = 0;
-
- /* check to see that the CPU number for this device */
- /* corresponds to the interrupt status read */
- switch (CPU_no) {
- case S514_CPU_A:
- if((unsigned char)int_status &
- IRQ_CPU_A)
- card_found_for_IRQ = 1;
- break;
-
- case S514_CPU_B:
- if((unsigned char)int_status &
- IRQ_CPU_B)
- card_found_for_IRQ = 1;
- break;
- }
-
- /* exit if the interrupt is for another CPU on the */
- /* same IRQ */
- if(!card_found_for_IRQ)
- return IRQ_HANDLED;
-
- if (!card ||
- (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){
- printk(KERN_INFO
- "Received IRQ %d for CPU #%c\n",
- irq, CPU_no);
- printk(KERN_INFO
- "IRQ for unconfigured adapter\n");
- S514_intack(&card->hw, int_status);
- return IRQ_HANDLED;
- }
-
- if (card->in_isr) {
- printk(KERN_INFO
- "%s: interrupt re-entrancy on IRQ %d\n",
- card->devname, card->wandev.irq);
- S514_intack(&card->hw, int_status);
- return IRQ_HANDLED;
- }
-
- spin_lock(&card->wandev.lock);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
-
- S514_intack(&card->hw, int_status);
- if (card->isr)
- card->isr(card);
-
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock(&card->wandev.lock);
-
- /* handle a maximum of two interrupts (one for each */
- /* CPU on the adapter) before returning */
- if((++ IRQ_count) == 2)
- return IRQ_HANDLED;
- }
- }
-
- else { /* handle interrupt on S508 adapter */
-
- if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))
- return IRQ_HANDLED;
-
- if (card->in_isr) {
- printk(KERN_INFO
- "%s: interrupt re-entrancy on IRQ %d!\n",
- card->devname, card->wandev.irq);
- return IRQ_HANDLED;
- }
-
- spin_lock(&card->wandev.lock);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
-
- sdla_intack(&card->hw);
- if (card->isr)
- card->isr(card);
-
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock(&card->wandev.lock);
-
- }
- return IRQ_HANDLED;
-#undef card
-}
-
-/*============================================================================
- * This routine is called by the protocol-specific modules when network
- * interface is being open. The only reason we need this, is because we
- * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's
- * defined more than once into the same kernel module.
- */
-void wanpipe_open (sdla_t* card)
-{
- ++card->open_cnt;
-}
-
-/*============================================================================
- * This routine is called by the protocol-specific modules when network
- * interface is being closed. The only reason we need this, is because we
- * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's
- * defined more than once into the same kernel module.
- */
-void wanpipe_close (sdla_t* card)
-{
- --card->open_cnt;
-}
-
-/*============================================================================
- * Set WAN device state.
- */
-void wanpipe_set_state (sdla_t* card, int state)
-{
- if (card->wandev.state != state) {
- switch (state) {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: link connected!\n",
- card->devname);
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: link connecting...\n",
- card->devname);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: link disconnected!\n",
- card->devname);
- break;
- }
- card->wandev.state = state;
- }
- card->state_tick = jiffies;
-}
-
-sdla_t * wanpipe_find_card (char *name)
-{
- int cnt;
- for (cnt = 0; cnt < ncards; ++ cnt) {
- sdla_t* card = &card_array[cnt];
- if (!strcmp(card->devname,name))
- return card;
- }
- return NULL;
-}
-
-sdla_t * wanpipe_find_card_num (int num)
-{
- if (num < 1 || num > ncards)
- return NULL;
- num--;
- return &card_array[num];
-}
-
-/*
- * @work_pointer: work_struct to be done;
- * should already have PREPARE_WORK() or
- * INIT_WORK() done on it by caller;
- */
-void wanpipe_queue_work (struct work_struct *work_pointer)
-{
- if (test_and_set_bit(1, (void*)&wanpipe_bh_critical))
- printk(KERN_INFO "CRITICAL IN QUEUING WORK\n");
-
- queue_work(wanpipe_wq, work_pointer);
- clear_bit(1,(void*)&wanpipe_bh_critical);
-}
-
-void wakeup_sk_bh(struct net_device *dev)
-{
- wanpipe_common_t *chan = dev->priv;
-
- if (test_bit(0,&chan->common_critical))
- return;
-
- if (chan->sk && chan->tx_timer){
- chan->tx_timer->expires=jiffies+1;
- add_timer(chan->tx_timer);
- }
-}
-
-int change_dev_flags(struct net_device *dev, unsigned flags)
-{
- struct ifreq if_info;
- mm_segment_t fs = get_fs();
- int err;
-
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
- if_info.ifr_flags = flags;
-
- set_fs(get_ds()); /* get user space block */
- err = devinet_ioctl(SIOCSIFFLAGS, &if_info);
- set_fs(fs);
-
- return err;
-}
-
-unsigned long get_ip_address(struct net_device *dev, int option)
-{
-
- struct in_ifaddr *ifaddr;
- struct in_device *in_dev;
- unsigned long addr = 0;
-
- rcu_read_lock();
- if ((in_dev = __in_dev_get_rcu(dev)) == NULL){
- goto out;
- }
-
- if ((ifaddr = in_dev->ifa_list)== NULL ){
- goto out;
- }
-
- switch (option){
-
- case WAN_LOCAL_IP:
- addr = ifaddr->ifa_local;
- break;
-
- case WAN_POINTOPOINT_IP:
- addr = ifaddr->ifa_address;
- break;
-
- case WAN_NETMASK_IP:
- addr = ifaddr->ifa_mask;
- break;
-
- case WAN_BROADCAST_IP:
- addr = ifaddr->ifa_broadcast;
- break;
- default:
- break;
- }
-
-out:
- rcu_read_unlock();
- return addr;
-}
-
-void add_gateway(sdla_t *card, struct net_device *dev)
-{
- mm_segment_t oldfs;
- struct rtentry route;
- int res;
-
- memset((char*)&route,0,sizeof(struct rtentry));
-
- ((struct sockaddr_in *)
- &(route.rt_dst))->sin_addr.s_addr = 0;
- ((struct sockaddr_in *)
- &(route.rt_dst))->sin_family = AF_INET;
-
- ((struct sockaddr_in *)
- &(route.rt_genmask))->sin_addr.s_addr = 0;
- ((struct sockaddr_in *)
- &(route.rt_genmask)) ->sin_family = AF_INET;
-
-
- route.rt_flags = 0;
- route.rt_dev = dev->name;
-
- oldfs = get_fs();
- set_fs(get_ds());
- res = ip_rt_ioctl(SIOCADDRT,&route);
- set_fs(oldfs);
-
- if (res == 0){
- printk(KERN_INFO "%s: Gateway added for %s\n",
- card->devname,dev->name);
- }
-
- return;
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *********************************************************/
diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
deleted file mode 100644
index 812a1183c502..000000000000
--- a/drivers/net/wan/wanpipe_multppp.c
+++ /dev/null
@@ -1,2358 +0,0 @@
-/*****************************************************************************
-* wanpipe_multppp.c Multi-Port PPP driver module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Dec 15 2000 Updated for 2.4.X kernel
-* Nov 15 2000 Fixed the SyncPPP support for kernels 2.2.16 and higher.
-* The pppstruct has changed.
-* Jul 13 2000 Using the kernel Syncppp module on top of RAW Wanpipe CHDLC
-* module.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <linux/jiffies.h> /* time_after() macro */
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h> /* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h> /* Socket Driver common area */
-#include <linux/if_wanpipe.h>
-
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <net/syncppp.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef _DEBUG_
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_CONFIG 0x04
-
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF 10
-
-#define CRC_LENGTH 2
-#define PPP_HEADER_LEN 4
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- void *if_ptr; /* General Pointer used by SPPP */
- wanpipe_common_t common;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
-
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
- two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-
-/* Network device interface */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats* if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure (sdla_t* card, void* data);
-static int chdlc_comm_enable (sdla_t* card);
-static int chdlc_comm_disable (sdla_t* card);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int config_chdlc (sdla_t *card);
-
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area);
-static void port_set_state (sdla_t *card, int);
-
-/* Interrupt handlers */
-static void wsppp_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Miscellaneous functions */
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-static void send_ppp_term_request(struct net_device *dev);
-
-
-static int Intr_test_counter;
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wsppp_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
- unsigned long max_permitted_baud = 0;
- SHARED_MEMORY_INFO_STRUCT *flags;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_MPPP) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Find out which Port to use */
- if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
- if (card->next){
-
- if (conf->comm_port != card->next->u.c.comm_port){
- card->u.c.comm_port = conf->comm_port;
- }else{
- printk(KERN_ERR "%s: ERROR - %s port used!\n",
- card->wandev.name, PORT(conf->comm_port));
- return -EINVAL;
- }
- }else{
- card->u.c.comm_port = conf->comm_port;
- }
- }else{
- printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
-
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase +
- SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
- }
- }else{
- /* for a S514 adapter, set a pointer to the actual mailbox in the */
- /* allocated virtual memory area */
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }else{
- card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
- }
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies + 1 * HZ;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if (time_after(jiffies, timeout)) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n"
- "%s: for Multi-Port PPP protocol.\n",
- card->devname,u.str,card->devname);
-
- card->isr = &wsppp_isr;
- card->poll = NULL;
- card->exec = NULL;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.udp_port = conf->udp_port;
-
- card->wandev.new_if_cnt = 0;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = conf->ttl;
- card->wandev.interface = conf->interface;
-
- if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
- card->hw.type != SDLA_S514){
- printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
- card->devname, PORT(card->u.c.comm_port));
- return -EIO;
- }
-
-
- card->wandev.clocking = conf->clocking;
-
- port_num = card->u.c.comm_port;
-
- /* Setup Port Bps */
-
- if(card->wandev.clocking) {
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
- /* For Primary Port 0 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- PRI_MAX_BAUD_RATE_S514 :
- PRI_MAX_BAUD_RATE_S508;
- }
- else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- SEC_MAX_BAUD_RATE_S514 :
- SEC_MAX_BAUD_RATE_S508;
- }
-
- if(conf->bps > max_permitted_baud) {
- conf->bps = max_permitted_baud;
- printk(KERN_INFO "%s: Baud too high!\n",
- card->wandev.name);
- printk(KERN_INFO "%s: Baud rate set to %lu bps\n",
- card->wandev.name, max_permitted_baud);
- }
-
- card->wandev.bps = conf->bps;
- }else{
- card->wandev.bps = 0;
- }
-
- /* Setup the Port MTU */
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
- /* For Primary Port 0 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- } else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- }
-
- /* Add on a PPP Header */
- card->wandev.mtu += PPP_HEADER_LEN;
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- clear_bit(1, (void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- enable_irq(card->hw.irq);
-
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- flags = card->u.c.flags;
-
- /* This is for the ports link state */
- card->wandev.state = WAN_DUALPORT;
- card->u.c.state = WAN_DISCONNECTED;
-
-
- if (!card->wandev.piggyback){
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_ERR "%s: Interrupt test failed (%i)\n",
- card->devname, Intr_test_counter);
- printk(KERN_ERR "%s: Please choose another interrupt\n",
- card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt test passed (%i)\n",
- card->devname, Intr_test_counter);
- }
-
-
- if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return -EIO;
- }
-
- /* Mask the Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3
- * different locations:
- * 1) The 'if_stats' recorded for the device.
- * 2) Communication error statistics on the adapter.
- * 3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile chdlc_private_area_t* chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags;
- unsigned long timeout;
-
- /* sanity checks */
- if((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if(wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* more sanity checks */
- if(!card->u.c.flags)
- return -ENODEV;
-
- if((dev=card->wandev.dev) == NULL)
- return -ENODEV;
-
- if((chdlc_priv_area=dev->priv) == NULL)
- return -ENODEV;
-
- flags = card->u.c.flags;
-
- if(chdlc_priv_area->update_comms_stats){
- return -EAGAIN;
- }
-
- /* we will need 2 timer interrupts to complete the */
- /* reading of the statistics */
- chdlc_priv_area->update_comms_stats = 2;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies + 1 * HZ;
- for(;;) {
- if(chdlc_priv_area->update_comms_stats == 0)
- break;
- if (time_after(jiffies, timeout)){
- chdlc_priv_area->update_comms_stats = 0;
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* pdev,
- wanif_conf_t* conf)
-{
-
- struct ppp_device *pppdev = (struct ppp_device *)pdev;
- struct net_device *dev = NULL;
- struct sppp *sp;
- sdla_t* card = wandev->private;
- chdlc_private_area_t* chdlc_priv_area;
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-
- if(chdlc_priv_area == NULL)
- return -ENOMEM;
-
- memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
- chdlc_priv_area->card = card;
-
- /* initialize data */
- strcpy(card->u.c.if_name, conf->name);
-
- if(card->wandev.new_if_cnt > 0) {
- kfree(chdlc_priv_area);
- return -EEXIST;
- }
-
- card->wandev.new_if_cnt++;
-
- chdlc_priv_area->TracingEnabled = 0;
-
- //We don't need this any more
- chdlc_priv_area->route_status = NO_ROUTE;
- chdlc_priv_area->route_removed = 0;
-
- printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n",
- wandev->name);
-
- /* Setup wanpipe as a router (WANPIPE) or as an API */
- if( strcmp(conf->usedby, "WANPIPE") == 0) {
- printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n",
- wandev->name);
- card->u.c.usedby = WANPIPE;
- } else {
- printk(KERN_INFO
- "%s: API Mode is not supported for SyncPPP!\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- /* Get Multicast Information */
- chdlc_priv_area->mc = conf->mc;
-
-
- chdlc_priv_area->if_ptr = pppdev;
-
- /* prepare network device data space for registration */
-
- strcpy(dev->name,card->u.c.if_name);
-
- /* Attach PPP protocol layer to pppdev
- * The sppp_attach() will initilize the dev structure
- * and setup ppp layer protocols.
- * All we have to do is to bind in:
- * if_open(), if_close(), if_send() and get_stats() functions.
- */
- sppp_attach(pppdev);
- dev = pppdev->dev;
- sp = &pppdev->sppp;
-
- /* Enable PPP Debugging */
- // FIXME Fix this up somehow
- //sp->pp_flags |= PP_DEBUG;
- sp->pp_flags &= ~PP_CISCO;
-
- dev->init = &if_init;
- dev->priv = chdlc_priv_area;
-
- return 0;
-}
-
-
-
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- unsigned long smp_lock;
-
- /* Detach the PPP layer */
- printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n",
- wandev->name,dev->name);
-
- lock_adapter_irq(&wandev->lock,&smp_lock);
-
- sppp_detach(dev);
- chdlc_priv_area->if_ptr=NULL;
-
- chdlc_set_intr_mode(card, 0);
- if (card->u.c.comm_enabled)
- chdlc_comm_disable(card);
- unlock_adapter_irq(&wandev->lock,&smp_lock);
-
- port_set_state(card, WAN_DISCONNECTED);
-
- return 0;
-}
-
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct wan_device* wandev = &card->wandev;
-
- /* NOTE: Most of the dev initialization was
- * done in sppp_attach(), called by new_if()
- * function. All we have to do here is
- * to link four major routines below.
- */
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
-
- /* Initialize hardware parameters */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length
- * If we over fill this queue the packets will
- * be droped by the kernel.
- * sppp_attach() sets this to 10, but
- * 100 will give us more room at low speeds.
- */
- dev->tx_queue_len = 100;
-
- return 0;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- netif_wake_queue (dev);
-}
-
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct timeval tv;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- /* Only one open per interface is allowed */
- if (netif_running(dev))
- return -EBUSY;
-
- /* Start PPP Layer */
- if (sppp_open(dev)){
- return -EIO;
- }
-
- do_gettimeofday(&tv);
- chdlc_priv_area->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
-
- chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
-
- /* Stop the PPP Layer */
- sppp_close(dev);
- netif_stop_queue(dev);
-
- wanpipe_close(card);
-
- return 0;
-}
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- int udp_type = 0;
- unsigned long smp_flags;
- int err=0;
-
- netif_stop_queue(dev);
-
-
- if (skb == NULL){
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
- card->devname, dev->name);
-
- netif_wake_queue(dev);
- return 0;
- }
-
- if (ntohs(skb->protocol) != htons(PVC_PROT)){
- /* check the udp packet type */
-
- udp_type = udp_pkt_type(skb, card);
- if (udp_type == UDP_CPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- chdlc_priv_area)){
- chdlc_int->interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- netif_start_queue(dev);
- return 0;
- }
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_crit_exit;
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_crit_exit;
- }
-
- if (chdlc_send(card, skb->data, skb->len)){
- netif_stop_queue(dev);
-
- }else{
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += skb->len;
- dev->trans_start = jiffies;
- netif_start_queue(dev);
- }
-
-if_send_crit_exit:
- if (!(err=netif_queue_stopped(dev))){
- dev_kfree_skb_any(skb);
- }else{
- chdlc_priv_area->tick_counter = jiffies;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* fill in UDP reply */
- c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- c_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = c_udp_pkt->udp_pkt.udp_src_port;
- c_udp_pkt->udp_pkt.udp_src_port =
- c_udp_pkt->udp_pkt.udp_dst_port;
- c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-
- /* calculate UDP checksum */
- c_udp_pkt->udp_pkt.udp_checksum = 0;
- c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- c_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
- c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
- c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- c_udp_pkt->ip_pkt.hdr_checksum = 0;
- c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
- sdla_t *my_card;
- chdlc_private_area_t* chdlc_priv_area;
-
- /* Shutdown bug fix. In del_if() we kill
- * dev->priv pointer. This function, gets
- * called after del_if(), thus check
- * if pointer has been deleted */
- if ((chdlc_priv_area=dev->priv) == NULL)
- return NULL;
-
- my_card = chdlc_priv_area->card;
- return &my_card->wandev.stats;
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*-----------------------------------------------------------------------------
- * Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
- int err;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-
- mailbox->buffer_length = data_length;
- memcpy(mailbox->data, data, data_length);
- mailbox->command = SET_CHDLC_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-
- return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- int_data->CHDLC_interrupt_triggers = mode;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
- return err;
-}
-
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card, err, mb);
- else
- card->u.c.comm_enabled=1;
-
- return err;
-}
-
-/*============================================================================
- * Disable communications and Drop the Modem lines (DCD and RTS).
- */
-static int chdlc_comm_disable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = DISABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
-
- return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_COMMS_ERROR_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_OPERATIONAL_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Update communications error and general packet statistics.
- */
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- COMMS_ERROR_STATS_STRUCT* err_stats;
- CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
-
- /* on the first timer interrupt, read the comms error statistics */
- if(chdlc_priv_area->update_comms_stats == 2) {
- if(chdlc_read_comm_err_stats(card))
- return 1;
- err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_over_errors =
- err_stats->Rx_overrun_err_count;
- card->wandev.stats.rx_crc_errors =
- err_stats->CRC_err_count;
- card->wandev.stats.rx_frame_errors =
- err_stats->Rx_abort_count;
- card->wandev.stats.rx_fifo_errors =
- err_stats->Rx_dis_pri_bfrs_full_count;
- card->wandev.stats.rx_missed_errors =
- card->wandev.stats.rx_fifo_errors;
- card->wandev.stats.tx_aborted_errors =
- err_stats->sec_Tx_abort_count;
- }
-
- /* on the second timer interrupt, read the operational statistics */
- else {
- if(chdlc_read_op_stats(card))
- return 1;
- op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_length_errors =
- (op_stats->Rx_Data_discard_short_count +
- op_stats->Rx_Data_discard_long_count);
- }
-
- return 0;
-}
-
-/*============================================================================
- * Send packet.
- * Return: 0 - o.k.
- * 1 - no transmit buffers available
- */
-static int chdlc_send (sdla_t* card, void* data, unsigned len)
-{
- CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
-
- if (txbuf->opp_flag)
- return 1;
-
- sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
-
- txbuf->frame_length = len;
- txbuf->opp_flag = 1; /* start transmission */
-
- /* Update transmit buffer control fields */
- card->u.c.txbuf = ++txbuf;
-
- if ((void*)txbuf > card->u.c.txbuf_last)
- card->u.c.txbuf = card->u.c.txbuf_base;
-
- return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
- unsigned cmd = mb->command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- case S514_BOTH_PORTS_SAME_CLK_MODE:
- if(cmd == SET_CHDLC_CONFIGURATION) {
- printk(KERN_INFO
- "%s: Configure both ports for the same clock source\n",
- card->devname);
- break;
- }
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- }
-
- return 0;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * Cisco HDLC interrupt service routine.
- */
-STATIC void wsppp_isr (sdla_t* card)
-{
- struct net_device* dev;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
- int i;
- sdla_t *my_card;
-
-
- /* Check for which port the interrupt has been generated
- * Since Secondary Port is piggybacking on the Primary
- * the check must be done here.
- */
-
- flags = card->u.c.flags;
- if (!flags->interrupt_info_struct.interrupt_type){
- /* Check for a second port (piggybacking) */
- if((my_card = card->next)){
- flags = my_card->u.c.flags;
- if (flags->interrupt_info_struct.interrupt_type){
- card = my_card;
- card->isr(card);
- return;
- }
- }
- }
-
- dev = card->wandev.dev;
- card->in_isr = 1;
- flags = card->u.c.flags;
-
- /* If we get an interrupt with no network device, stop the interrupts
- * and issue an error */
- if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type !=
- COMMAND_COMPLETE_APP_INT_PEND){
- goto isr_done;
- }
-
-
- /* if critical due to peripheral operations
- * ie. update() or getstats() then reset the interrupt and
- * wait for the board to retrigger.
- */
- if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- flags->interrupt_info_struct.
- interrupt_type = 0;
- goto isr_done;
- }
-
-
- /* On a 508 Card, if critical due to if_send
- * Major Error !!!
- */
- if(card->hw.type != SDLA_S514) {
- if(test_bit(0, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
- card->devname, card->wandev.critical);
- goto isr_done;
- }
- }
-
- switch(flags->interrupt_info_struct.interrupt_type) {
-
- case RX_APP_INT_PEND: /* 0x01: receive interrupt */
- rx_intr(card);
- break;
-
- case TX_APP_INT_PEND: /* 0x02: transmit interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TX_FRAME;
-
- netif_wake_queue(dev);
- break;
-
- case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
- ++ Intr_test_counter;
- break;
-
- case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */
- process_chdlc_exception(card);
- break;
-
- case GLOBAL_EXCEP_COND_APP_INT_PEND:
- process_global_exception(card);
- break;
-
- case TIMER_APP_INT_PEND:
- timer_intr(card);
- break;
-
- default:
- printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
- card->devname,
- flags->interrupt_info_struct.interrupt_type);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
- break;
- }
-
-isr_done:
- card->in_isr = 0;
- flags->interrupt_info_struct.interrupt_type = 0;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr (sdla_t* card)
-{
- struct net_device *dev;
- chdlc_private_area_t *chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
- struct sk_buff *skb;
- unsigned len;
- unsigned addr = rxbuf->ptr_data_bfr;
- void *buf;
- int i,udp_type;
-
- if (rxbuf->opp_flag != 0x01) {
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
-
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it measn that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- chdlc_set_intr_mode(card,0);
- return;
- }
-
- dev = card->wandev.dev;
-
- if (!dev){
- goto rx_exit;
- }
-
- if (!netif_running(dev)){
- goto rx_exit;
- }
-
- chdlc_priv_area = dev->priv;
-
- if (rxbuf->error_flag){
- goto rx_exit;
- }
- /* Take off two CRC bytes */
-
- if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){
- goto rx_exit;
- }
-
- len = rxbuf->frame_length - CRC_LENGTH;
-
- /* Allocate socket buffer */
- skb = dev_alloc_skb(len);
-
- if (skb == NULL) {
- if (net_ratelimit()){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- ++card->wandev.stats.rx_dropped;
- goto rx_exit;
- }
-
- /* Copy data to the socket buffer */
- if((addr + len) > card->u.c.rx_top + 1) {
- unsigned tmp = card->u.c.rx_top - addr + 1;
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, addr, buf, tmp);
- addr = card->u.c.rx_base;
- len -= tmp;
- }
-
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, addr, buf, len);
-
- skb->protocol = htons(ETH_P_WAN_PPP);
-
- card->wandev.stats.rx_packets ++;
- card->wandev.stats.rx_bytes += skb->len;
- udp_type = udp_pkt_type( skb, card );
-
- if(udp_type == UDP_CPIPE_TYPE) {
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
- card, skb, dev, chdlc_priv_area)) {
- flags->interrupt_info_struct.
- interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- }else{
- /* Pass it up the protocol stack */
- skb->dev = dev;
- skb->mac.raw = skb->data;
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
-
-rx_exit:
- /* Release buffer element and calculate a pointer to the next one */
- rxbuf->opp_flag = 0x00;
- card->u.c.rxmb = ++ rxbuf;
- if((void*)rxbuf > card->u.c.rxbuf_last){
- card->u.c.rxmb = card->u.c.rxbuf_base;
- }
-}
-
-/*============================================================================
- * Timer interrupt handler.
- * The timer interrupt is used for two purposes:
- * 1) Processing udp calls from 'cpipemon'.
- * 2) Reading board-level statistics for updating the proc file system.
- */
-void timer_intr(sdla_t *card)
-{
- struct net_device* dev;
- chdlc_private_area_t* chdlc_priv_area = NULL;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-
- dev = card->wandev.dev;
- chdlc_priv_area = dev->priv;
-
- if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
- if (!config_chdlc(card)){
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
- }
- }
-
- /* process a udp call if pending */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
- process_udp_mgmt_pkt(card, dev,
- chdlc_priv_area);
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
- }
-
-
- /* read the communications statistics if required */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
- update_comms_stats(card, chdlc_priv_area);
- if(!(-- chdlc_priv_area->update_comms_stats)) {
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- /* only disable the timer interrupt if there are no udp or statistic */
- /* updates pending */
- if(!chdlc_priv_area->timer_int_enabled) {
- flags = card->u.c.flags;
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- }
-}
-
-/*------------------------------------------------------------------------------
- Miscellaneous Functions
- - set_chdlc_config() used to set configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_chdlc_config(sdla_t* card)
-{
-
- CHDLC_CONFIGURATION_STRUCT cfg;
-
- memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
-
- if(card->wandev.clocking)
- cfg.baud_rate = card->wandev.bps;
-
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
- cfg.modem_config_options = 0;
- //API OPTIONS
- cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES;
- cfg.modem_status_timer = 100;
- cfg.CHDLC_protocol_options = HDLC_STREAMING_MODE;
- cfg.percent_data_buffer_for_Tx = 50;
- cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
- cfg.max_CHDLC_data_field_length = card->wandev.mtu;
-
- cfg.transmit_keepalive_timer = 0;
- cfg.receive_keepalive_timer = 0;
- cfg.keepalive_error_tolerance = 0;
- cfg.SLARP_request_timer = 0;
-
- cfg.IP_address = 0;
- cfg.IP_netmask = 0;
-
- return chdlc_configure(card, &cfg);
-}
-
-/*============================================================================
- * Process global exception condition
- */
-static int process_global_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int err;
-
- mbox->buffer_length = 0;
- mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
- err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
-
- if(err != CMD_TIMEOUT ){
-
- switch(mbox->return_code) {
-
- case EXCEP_MODEM_STATUS_CHANGE:
-
- printk(KERN_INFO "%s: Modem status change\n",
- card->devname);
-
- switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
- case (DCD_HIGH):
- printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
- break;
- case (CTS_HIGH):
- printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);
- break;
- case ((DCD_HIGH | CTS_HIGH)):
- printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
- break;
- default:
- printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
- break;
- }
-
- if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){
- //printk(KERN_INFO "Sending TERM Request Manually !\n");
- send_ppp_term_request(card->wandev.dev);
- }
- break;
-
- case EXCEP_TRC_DISABLED:
- printk(KERN_INFO "%s: Line trace disabled\n",
- card->devname);
- break;
-
- case EXCEP_IRQ_TIMEOUT:
- printk(KERN_INFO "%s: IRQ timeout occurred\n",
- card->devname);
- break;
-
- default:
- printk(KERN_INFO "%s: Global exception %x\n",
- card->devname, mbox->return_code);
- break;
- }
- }
- return 0;
-}
-
-
-/*============================================================================
- * Process chdlc exception condition
- */
-static int process_chdlc_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_EXCEPTION_CONDITION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if(err != CMD_TIMEOUT) {
-
- switch (err) {
-
- case EXCEP_LINK_ACTIVE:
- port_set_state(card, WAN_CONNECTED);
- break;
-
- case EXCEP_LINK_INACTIVE_MODEM:
- port_set_state(card, WAN_DISCONNECTED);
- break;
-
- case EXCEP_LOOPBACK_CONDITION:
- printk(KERN_INFO "%s: Loopback Condition Detected.\n",
- card->devname);
- break;
-
- case NO_CHDLC_EXCEP_COND_TO_REPORT:
- printk(KERN_INFO "%s: No exceptions reported.\n",
- card->devname);
- break;
- default:
- printk(KERN_INFO "%s: Exception Condition %x!\n",
- card->devname,err);
- break;
- }
-
- }
- return 0;
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area )
-{
- int udp_pkt_stored = 0;
-
- if(!chdlc_priv_area->udp_pkt_lgth &&
- (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
- chdlc_priv_area->udp_pkt_lgth = skb->len;
- chdlc_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK)
- dev_kfree_skb_any(skb);
- else
- dev_kfree_skb_any(skb);
-
- return(udp_pkt_stored);
-}
-
-
-/*=============================================================================
- * Process UDP management packet.
- */
-
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area )
-{
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short buffer_length, real_len;
- unsigned long data_ptr;
- unsigned data_length;
- int udp_mgmt_req_valid = 1;
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- chdlc_udp_pkt_t *chdlc_udp_pkt;
- struct timeval tv;
- int err;
- char ut_char;
-
- chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- switch(chdlc_udp_pkt->cblock.command) {
- case READ_GLOBAL_STATISTICS:
- case READ_MODEM_STATUS:
- case READ_CHDLC_LINK_STATUS:
- case CPIPE_ROUTER_UP_TIME:
- case READ_COMMS_ERROR_STATS:
- case READ_CHDLC_OPERATIONAL_STATS:
-
- /* These two commands are executed for
- * each request */
- case READ_CHDLC_CONFIGURATION:
- case READ_CHDLC_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
-
- /* set length to 0 */
- chdlc_udp_pkt->cblock.buffer_length = 0;
-
- /* set return code */
- chdlc_udp_pkt->cblock.return_code = 0xCD;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,chdlc_udp_pkt->cblock.command);
- }
-
- } else {
- unsigned long trace_status_cfg_addr = 0;
- TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
- TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
-
- switch(chdlc_udp_pkt->cblock.command) {
-
- case CPIPE_ENABLE_TRACING:
- if (!chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
-
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_ACTIVE;
- /* Trace delay mode is not used because it slows
- down transfer and results in a standoff situation
- when there is a lot of data */
-
- /* Configure the Trace based on user inputs */
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |=
- chdlc_udp_pkt->data[0];
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_deactivation_timer = 4000;
-
-
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- card->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- /* Get the base address of the trace element list */
- mb->buffer_length = 0;
- mb->command = READ_TRACE_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
- mb->data) -> ptr_trace_stat_el_cfg_struct;
-
- sdla_peek(&card->hw, trace_status_cfg_addr,
- &trace_cfg_struct, sizeof(trace_cfg_struct));
-
- chdlc_priv_area->start_trace_addr = trace_cfg_struct.
- base_addr_trace_status_elements;
-
- chdlc_priv_area->number_trace_elements =
- trace_cfg_struct.number_trace_status_elements;
-
- chdlc_priv_area->end_trace_addr = (unsigned long)
- ((TRACE_STATUS_ELEMENT_STRUCT *)
- chdlc_priv_area->start_trace_addr +
- (chdlc_priv_area->number_trace_elements - 1));
-
- chdlc_priv_area->base_addr_trace_buffer =
- trace_cfg_struct.base_addr_trace_buffer;
-
- chdlc_priv_area->end_addr_trace_buffer =
- trace_cfg_struct.end_addr_trace_buffer;
-
- chdlc_priv_area->curr_trace_addr =
- trace_cfg_struct.next_trace_element_to_use;
-
- chdlc_priv_area->available_buffer_space = 2000 -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t) -
- sizeof(trace_info_t);
- }
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- chdlc_priv_area->TracingEnabled = 1;
- break;
-
-
- case CPIPE_DISABLE_TRACING:
- if (chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_INACTIVE;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
-
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- break;
-
-
- case CPIPE_GET_TRACE_INFO:
-
- if (!chdlc_priv_area->TracingEnabled) {
- chdlc_udp_pkt->cblock.return_code = 1;
- mb->buffer_length = 0;
- break;
- }
-
- chdlc_udp_pkt->trace_info.ismoredata = 0x00;
- buffer_length = 0; /* offset of packet already occupied */
-
- for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
-
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &chdlc_udp_pkt->data[buffer_length];
-
- sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
- (unsigned char *)&trace_element_struct,
- sizeof(TRACE_STATUS_ELEMENT_STRUCT));
-
- if (trace_element_struct.opp_flag == 0x00) {
- break;
- }
-
- /* get pointer to real data */
- data_ptr = trace_element_struct.ptr_data_bfr;
-
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element_struct.trace_length;
- }else{
- data_length = 0;
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
-
- if( (chdlc_priv_area->available_buffer_space - buffer_length)
- < ( sizeof(trace_pkt_t) + data_length) ) {
-
- /* indicate there are more frames on board & exit */
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- break;
- }
-
- trace_pkt->status = trace_element_struct.trace_type;
-
- trace_pkt->time_stamp =
- trace_element_struct.trace_time_stamp;
-
- trace_pkt->real_length =
- trace_element_struct.trace_length;
-
- /* see if we can fit the frame into the user buffer */
- real_len = trace_pkt->real_length;
-
- if (data_ptr == 0) {
- trace_pkt->data_avail = 0x00;
- } else {
- unsigned tmp = 0;
-
- /* get the data from circular buffer
- must check for end of buffer */
- trace_pkt->data_avail = 0x01;
-
- if ((data_ptr + real_len) >
- chdlc_priv_area->end_addr_trace_buffer + 1){
-
- tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
- sdla_peek(&card->hw, data_ptr,
- trace_pkt->data,tmp);
- data_ptr = chdlc_priv_area->base_addr_trace_buffer;
- }
-
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data[tmp], real_len - tmp);
- }
-
- /* zero the opp flag to show we got the frame */
- ut_char = 0x00;
- sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
-
- /* now move onto the next frame */
- chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
-
- /* check if we went over the last address */
- if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
- chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
- }
-
- if(trace_pkt->data_avail == 0x01) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += sizeof(trace_pkt_t);
-
- } /* For Loop */
-
- if (frames == chdlc_priv_area->number_trace_elements){
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
- chdlc_udp_pkt->trace_info.num_frames = frames;
-
- mb->buffer_length = buffer_length;
- chdlc_udp_pkt->cblock.buffer_length = buffer_length;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-
- break;
-
-
- case CPIPE_FT1_READ_STATUS:
- ((unsigned char *)chdlc_udp_pkt->data )[0] =
- flags->FT1_info_struct.parallel_port_A_input;
-
- ((unsigned char *)chdlc_udp_pkt->data )[1] =
- flags->FT1_info_struct.parallel_port_B_input;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 2;
- break;
-
- case CPIPE_ROUTER_UP_TIME:
- do_gettimeofday( &tv );
- chdlc_priv_area->router_up_time = tv.tv_sec -
- chdlc_priv_area->router_start_time;
- *(unsigned long *)&chdlc_udp_pkt->data =
- chdlc_priv_area->router_up_time;
- mb->buffer_length = sizeof(unsigned long);
- break;
-
- case FT1_MONITOR_STATUS_CTRL:
- /* Enable FT1 MONITOR STATUS */
- if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||
- (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-
- if( rCount++ != 0 ) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if( chdlc_udp_pkt->data[0] == 0) {
-
- if( --rCount != 0) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
-
- default:
- /* it's a board command */
- mb->command = chdlc_udp_pkt->cblock.command;
- mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
- if (mb->buffer_length) {
- memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
- data, mb->buffer_length);
- }
- /* run the command on the board */
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- break;
- }
-
- /* copy the result back to our buffer */
- memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t));
-
- if (mb->buffer_length) {
- memcpy(&chdlc_udp_pkt->data, &mb->data,
- mb->buffer_length);
- }
-
- } /* end of switch */
- } /* end of else */
-
- /* Fill UDP TTL */
- chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
-
- len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
- if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
- ++ card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += len;
- }
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, len);
- memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
-
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- dev->last_rx = jiffies;
- } else {
-
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- }
-
- chdlc_priv_area->udp_pkt_lgth = 0;
-
- return 0;
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
- CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
- char err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- return;
- }
-
- if(card->hw.type == SDLA_S514) {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct));
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- tx_config->base_addr_Tx_status_elements);
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)
- card->u.c.txbuf_base +
- (tx_config->number_Tx_status_elements - 1);
-
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- rx_config->base_addr_Rx_status_elements);
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)
- card->u.c.rxbuf_base +
- (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- tx_config->next_Tx_status_element_to_use);
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- rx_config->next_Rx_status_element_to_use);
- }
- else {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
- + (tx_config->number_Tx_status_elements - 1);
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
- + (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
- }
-
- /* Setup Actual Buffer Start and end addresses */
- card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
- card->u.c.rx_top = rx_config->end_addr_Rx_buffer;
-
-}
-
-/*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err,i;
-
- Intr_test_counter = 0;
-
- /* The critical flag is unset because during initialization (if_open)
- * we want the interrupts to be enabled so that when the wpc_isr is
- * called it does not exit due to critical flag set.
- */
-
- err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
-
- if (err == CMD_OK) {
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
- }
- else {
- return err;
- }
-
- err = chdlc_set_intr_mode(card, 0);
-
- if (err != CMD_OK)
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
-static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
-{
- chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
-
- if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
- (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
- return UDP_CPIPE_TYPE;
- }
- else return UDP_INVALID_TYPE;
-}
-
-/*============================================================================
- * Set PORT state.
- */
-static void port_set_state (sdla_t *card, int state)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
-
- if (card->u.c.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: HDLC link connected!\n",
- card->devname);
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: HDLC link connecting...\n",
- card->devname);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: HDLC link disconnected!\n",
- card->devname);
- break;
- }
-
- card->wandev.state = card->u.c.state = state;
- chdlc_priv_area->common.state = state;
- }
-}
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- if (card->next){
- /* It is ok to use spin_lock here, since we
- * already turned off interrupts */
- spin_lock(&card->next->wandev.lock);
- }
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-
-
-/*===========================================================================
- * config_chdlc
- *
- * Configure the chdlc protocol and enable communications.
- *
- * The if_open() function binds this function to the poll routine.
- * Therefore, this function will run every time the chdlc interface
- * is brought up. We cannot run this function from the if_open
- * because if_open does not have access to the remote IP address.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses have changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- *
- */
-
-static int config_chdlc (sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- if (card->u.c.comm_enabled){
- chdlc_comm_disable(card);
- port_set_state(card, WAN_DISCONNECTED);
- }
-
- if (set_chdlc_config(card)) {
- printk(KERN_INFO "%s: CHDLC Configuration Failed!\n",
- card->devname);
- return 0;
- }
- init_chdlc_tx_rx_buff(card, dev);
-
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return 0;
- }
-
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
-
- /* Initialize Rx/Tx buffer control fields */
- port_set_state(card, WAN_CONNECTING);
- return 0;
-}
-
-
-static void send_ppp_term_request(struct net_device *dev)
-{
- struct sk_buff *new_skb;
- unsigned char *buf;
-
- if ((new_skb = dev_alloc_skb(8)) != NULL) {
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, 8);
- sprintf(buf,"%c%c%c%c%c%c%c%c", 0xFF,0x03,0xC0,0x21,0x05,0x98,0x00,0x07);
-
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_WAN_PPP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- dev->last_rx = jiffies;
- }
-}
-
-
-MODULE_LICENSE("GPL");
-
-/****** End ****************************************************************/
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index bad09ebdb50b..e0874cbfefea 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -6,7 +6,7 @@ menu "Wireless LAN (non-hamradio)"
depends on NETDEVICES
config NET_RADIO
- bool "Wireless LAN drivers (non-hamradio)"
+ bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
select WIRELESS_EXT
---help---
Support for wireless LANs and everything having to do with radio,
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 108d9fed8f07..00764ddd74d8 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3139,6 +3139,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
if ( status & EV_LINK ) {
union iwreq_data wrqu;
+ int scan_forceloss = 0;
/* The link status has changed, if you want to put a
monitor hook in, do it here. (Remember that
interrupts are still disabled!)
@@ -3157,7 +3158,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
code) */
#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
code) */
-#define ASSOCIATED 0x0400 /* Assocatied */
+#define ASSOCIATED 0x0400 /* Associated */
+#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
#define RC_RESERVED 0 /* Reserved return code */
#define RC_NOREASON 1 /* Unspecified reason */
#define RC_AUTHINV 2 /* Previous authentication invalid */
@@ -3174,44 +3176,30 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
leaving BSS */
#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
Authenticated with the responding station */
- if (newStatus != ASSOCIATED) {
- if (auto_wep && !apriv->expires) {
- apriv->expires = RUN_AT(3*HZ);
- wake_up_interruptible(&apriv->thr_wait);
- }
- } else {
- struct task_struct *task = apriv->task;
+ if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
+ scan_forceloss = 1;
+ if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
if (auto_wep)
apriv->expires = 0;
- if (task)
- wake_up_process (task);
+ if (apriv->task)
+ wake_up_process (apriv->task);
set_bit(FLAG_UPDATE_UNI, &apriv->flags);
set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
- }
- /* Question : is ASSOCIATED the only status
- * that is valid ? We want to catch handover
- * and reassociations as valid status
- * Jean II */
- if(newStatus == ASSOCIATED) {
-#if 0
- /* FIXME: Grabbing scan results here
- * seems to be too early??? Just wait for
- * timeout instead. */
- if (apriv->scan_timeout > 0) {
- set_bit(JOB_SCAN_RESULTS, &apriv->flags);
- wake_up_interruptible(&apriv->thr_wait);
- }
-#endif
+
if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_EVENT, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
} else
airo_send_event(dev);
- } else {
- memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ } else if (!scan_forceloss) {
+ if (auto_wep && !apriv->expires) {
+ apriv->expires = RUN_AT(3*HZ);
+ wake_up_interruptible(&apriv->thr_wait);
+ }
/* Send event to user space */
+ memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
}
}
@@ -7136,10 +7124,10 @@ static int airo_set_scan(struct net_device *dev,
goto out;
/* Initiate a scan command */
+ ai->scan_timeout = RUN_AT(3*HZ);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LISTBSS;
issuecommand(ai, &cmd, &rsp);
- ai->scan_timeout = RUN_AT(3*HZ);
wake = 1;
out:
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index a496460ce224..af0cbb6c5c0c 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -80,8 +80,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
event handler.
*/
-static void airo_config(dev_link_t *link);
-static void airo_release(dev_link_t *link);
+static int airo_config(struct pcmcia_device *link);
+static void airo_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -101,10 +101,10 @@ static void airo_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the aironet device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -114,7 +114,7 @@ static void airo_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
@@ -141,24 +141,16 @@ typedef struct local_info_t {
======================================================================*/
-static int airo_attach(struct pcmcia_device *p_dev)
+static int airo_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "airo_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) {
- printk(KERN_ERR "airo_cs: no memory for new device\n");
- return -ENOMEM;
- }
-
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = NULL;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = NULL;
/*
General socket configuration defaults can go here. In this
@@ -167,26 +159,18 @@ static int airo_attach(struct pcmcia_device *p_dev)
and attributes of IO windows) are fixed by the nature of the
device, and can be hard-wired here.
*/
- link->conf.Attributes = 0;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.Attributes = 0;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
printk(KERN_ERR "airo_cs: no memory for new device\n");
- kfree (link);
return -ENOMEM;
}
- link->priv = local;
+ p_dev->priv = local;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- airo_config(link);
-
- return 0;
+ return airo_config(p_dev);
} /* airo_attach */
/*======================================================================
@@ -198,14 +182,11 @@ static int airo_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void airo_detach(struct pcmcia_device *p_dev)
+static void airo_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "airo_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- airo_release(link);
+ airo_release(link);
if ( ((local_info_t*)link->priv)->eth_dev ) {
stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
@@ -213,7 +194,6 @@ static void airo_detach(struct pcmcia_device *p_dev)
((local_info_t*)link->priv)->eth_dev = NULL;
kfree(link->priv);
- kfree(link);
} /* airo_detach */
/*======================================================================
@@ -227,9 +207,8 @@ static void airo_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void airo_config(dev_link_t *link)
+static int airo_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -237,8 +216,7 @@ static void airo_config(dev_link_t *link)
u_char buf[64];
win_req_t req;
memreq_t map;
-
- handle = link->handle;
+
dev = link->priv;
DEBUG(0, "airo_config(0x%p)\n", link);
@@ -252,15 +230,12 @@ static void airo_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
+
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
@@ -274,12 +249,12 @@ static void airo_config(dev_link_t *link)
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -294,16 +269,11 @@ static void airo_config(dev_link_t *link)
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
@@ -329,12 +299,12 @@ static void airo_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/*
Now set up a common memory window, if needed. There is room
- in the dev_link_t structure for one memory window handle,
+ in the struct pcmcia_device structure for one memory window handle,
but if the base addresses need to be saved, or if multiple
windows are needed, the info should go in the private data
structure for this device.
@@ -350,7 +320,7 @@ static void airo_config(dev_link_t *link)
req.Base = mem->win[0].host_addr;
req.Size = mem->win[0].len;
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -360,7 +330,7 @@ static void airo_config(dev_link_t *link)
break;
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
/*
@@ -369,33 +339,32 @@ static void airo_config(dev_link_t *link)
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
((local_info_t*)link->priv)->eth_dev =
init_airo_card( link->irq.AssignedIRQ,
- link->io.BasePort1, 1, &handle_to_dev(handle) );
+ link->io.BasePort1, 1, &handle_to_dev(link) );
if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
/*
At this point, the dev_node_t structure(s) need to be
- initialized and arranged in a linked list at link->dev.
+ initialized and arranged in a linked list at link->dev_node.
*/
strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -408,14 +377,12 @@ static void airo_config(dev_link_t *link)
printk(", mem 0x%06lx-0x%06lx", req.Base,
req.Base+req.Size-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
airo_release(link);
-
+ return -ENODEV;
} /* airo_config */
/*======================================================================
@@ -426,51 +393,26 @@ static void airo_config(dev_link_t *link)
======================================================================*/
-static void airo_release(dev_link_t *link)
+static void airo_release(struct pcmcia_device *link)
{
DEBUG(0, "airo_release(0x%p)\n", link);
-
- /* Unlink the device chain */
- link->dev = NULL;
-
- /*
- In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
- */
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int airo_suspend(struct pcmcia_device *p_dev)
+static int airo_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *local = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- pcmcia_release_configuration(link->handle);
- }
+ netif_device_detach(local->eth_dev);
return 0;
}
-static int airo_resume(struct pcmcia_device *p_dev)
+static int airo_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *local = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
reset_airo_card(local->eth_dev);
netif_device_attach(local->eth_dev);
}
@@ -492,7 +434,7 @@ static struct pcmcia_driver airo_driver = {
.drv = {
.name = "airo_cs",
},
- .probe = airo_attach,
+ .probe = airo_probe,
.remove = airo_detach,
.id_table = airo_ids,
.suspend = airo_suspend,
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 87afa6878f26..8606c88886fc 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -3463,6 +3463,7 @@ static void atmel_command_irq(struct atmel_private *priv)
u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
int fast_scan;
+ union iwreq_data wrqu;
if (status == CMD_STATUS_IDLE ||
status == CMD_STATUS_IN_PROGRESS)
@@ -3487,6 +3488,7 @@ static void atmel_command_irq(struct atmel_private *priv)
atmel_scan(priv, 1);
} else {
int bss_index = retrieve_bss(priv);
+ int notify_scan_complete = 1;
if (bss_index != -1) {
atmel_join_bss(priv, bss_index);
} else if (priv->operating_mode == IW_MODE_ADHOC &&
@@ -3495,8 +3497,14 @@ static void atmel_command_irq(struct atmel_private *priv)
} else {
priv->fast_scan = !fast_scan;
atmel_scan(priv, 1);
+ notify_scan_complete = 0;
}
priv->site_survey_state = SITE_SURVEY_COMPLETED;
+ if (notify_scan_complete) {
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+ }
}
break;
@@ -3509,6 +3517,9 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->site_survey_state = SITE_SURVEY_COMPLETED;
if (priv->station_is_associated) {
atmel_enter_state(priv, STATION_STATE_READY);
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
} else {
atmel_scan(priv, 1);
}
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index d6f4a5a3e55a..26bf1127524d 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
event handler.
*/
-static void atmel_config(dev_link_t *link);
-static void atmel_release(dev_link_t *link);
+static int atmel_config(struct pcmcia_device *link);
+static void atmel_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the atmelnet device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
@@ -152,24 +152,16 @@ typedef struct local_info_t {
======================================================================*/
-static int atmel_attach(struct pcmcia_device *p_dev)
+static int atmel_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "atmel_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) {
- printk(KERN_ERR "atmel_cs: no memory for new device\n");
- return -ENOMEM;
- }
-
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = NULL;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = NULL;
/*
General socket configuration defaults can go here. In this
@@ -178,26 +170,18 @@ static int atmel_attach(struct pcmcia_device *p_dev)
and attributes of IO windows) are fixed by the nature of the
device, and can be hard-wired here.
*/
- link->conf.Attributes = 0;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.Attributes = 0;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
printk(KERN_ERR "atmel_cs: no memory for new device\n");
- kfree (link);
return -ENOMEM;
}
- link->priv = local;
+ p_dev->priv = local;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- atmel_config(link);
-
- return 0;
+ return atmel_config(p_dev);
} /* atmel_attach */
/*======================================================================
@@ -209,17 +193,13 @@ static int atmel_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void atmel_detach(struct pcmcia_device *p_dev)
+static void atmel_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "atmel_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- atmel_release(link);
+ atmel_release(link);
kfree(link->priv);
- kfree(link);
}
/*======================================================================
@@ -236,19 +216,17 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
/* Call-back function to interrogate PCMCIA-specific information
about the current existance of the card */
static int card_present(void *arg)
-{
- dev_link_t *link = (dev_link_t *)arg;
- if (link->state & DEV_SUSPEND)
- return 0;
- else if (link->state & DEV_PRESENT)
+{
+ struct pcmcia_device *link = (struct pcmcia_device *)arg;
+
+ if (pcmcia_dev_present(link))
return 1;
-
+
return 0;
}
-static void atmel_config(dev_link_t *link)
+static int atmel_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -256,9 +234,8 @@ static void atmel_config(dev_link_t *link)
u_char buf[64];
struct pcmcia_device_id *did;
- handle = link->handle;
dev = link->priv;
- did = handle_to_dev(handle).driver_data;
+ did = handle_to_dev(link).driver_data;
DEBUG(0, "atmel_config(0x%p)\n", link);
@@ -272,15 +249,12 @@ static void atmel_config(dev_link_t *link)
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
+
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
@@ -294,12 +268,12 @@ static void atmel_config(dev_link_t *link)
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -314,16 +288,11 @@ static void atmel_config(dev_link_t *link)
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
@@ -349,14 +318,14 @@ static void atmel_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we got this far, we're cool! */
break;
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
/*
@@ -365,14 +334,14 @@ static void atmel_config(dev_link_t *link)
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (link->irq.AssignedIRQ == 0) {
printk(KERN_ALERT
@@ -384,7 +353,7 @@ static void atmel_config(dev_link_t *link)
init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1,
did ? did->driver_info : ATMEL_FW_TYPE_NONE,
- &handle_to_dev(handle),
+ &handle_to_dev(link),
card_present,
link);
if (!((local_info_t*)link->priv)->eth_dev)
@@ -393,18 +362,18 @@ static void atmel_config(dev_link_t *link)
/*
At this point, the dev_node_t structure(s) need to be
- initialized and arranged in a linked list at link->dev.
+ initialized and arranged in a linked list at link->dev_node.
*/
strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+ link->dev_node = &dev->node;
+
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
atmel_release(link);
+ return -ENODEV;
}
/*======================================================================
@@ -415,53 +384,34 @@ static void atmel_config(dev_link_t *link)
======================================================================*/
-static void atmel_release(dev_link_t *link)
+static void atmel_release(struct pcmcia_device *link)
{
struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
-
+
DEBUG(0, "atmel_release(0x%p)\n", link);
-
- /* Unlink the device chain */
- link->dev = NULL;
-
- if (dev)
+
+ if (dev)
stop_atmel_card(dev);
- ((local_info_t*)link->priv)->eth_dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ ((local_info_t*)link->priv)->eth_dev = NULL;
+
+ pcmcia_disable_device(link);
}
-static int atmel_suspend(struct pcmcia_device *dev)
+static int atmel_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
local_info_t *local = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- pcmcia_release_configuration(link->handle);
- }
+ netif_device_detach(local->eth_dev);
return 0;
}
-static int atmel_resume(struct pcmcia_device *dev)
+static int atmel_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
local_info_t *local = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- atmel_open(local->eth_dev);
- netif_device_attach(local->eth_dev);
- }
+ atmel_open(local->eth_dev);
+ netif_device_attach(local->eth_dev);
return 0;
}
@@ -515,7 +465,7 @@ static struct pcmcia_driver atmel_driver = {
.drv = {
.name = "atmel_cs",
},
- .probe = atmel_attach,
+ .probe = atmel_probe,
.remove = atmel_detach,
.id_table = atmel_ids,
.suspend = atmel_suspend,
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
index 418465600a77..25ea4748f0b9 100644
--- a/drivers/net/wireless/bcm43xx/Kconfig
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -17,8 +17,11 @@ config BCM43XX_DEBUG
config BCM43XX_DMA
bool
+ depends on BCM43XX
+
config BCM43XX_PIO
bool
+ depends on BCM43XX
choice
prompt "BCM43xx data transfer mode"
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index dcadd295de4f..2e83083935e1 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -15,7 +15,6 @@
#include "bcm43xx_debugfs.h"
#include "bcm43xx_leds.h"
-#include "bcm43xx_sysfs.h"
#define PFX KBUILD_MODNAME ": "
@@ -638,8 +637,6 @@ struct bcm43xx_key {
};
struct bcm43xx_private {
- struct bcm43xx_sysfs sysfs;
-
struct ieee80211_device *ieee;
struct ieee80211softmac_device *softmac;
@@ -772,6 +769,20 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
return ieee80211softmac_priv(dev);
}
+struct device;
+
+static inline
+struct bcm43xx_private * dev_to_bcm(struct device *dev)
+{
+ struct net_device *net_dev;
+ struct bcm43xx_private *bcm;
+
+ net_dev = dev_get_drvdata(dev);
+ bcm = bcm43xx_priv(net_dev);
+
+ return bcm;
+}
+
/* Helper function, which returns a boolean.
* TRUE, if PIO is used; FALSE, if DMA is used.
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index d2c3401e9b70..35a4fcb6d923 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -452,12 +452,12 @@ void bcm43xx_printk_dump(const char *data,
size_t i;
char c;
- printk(KERN_INFO PFX "Data dump (%s, %u bytes):",
+ printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
description, size);
for (i = 0; i < size; i++) {
c = data[i];
if (i % 8 == 0)
- printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff);
+ printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff);
else
printk("0x%02x, ", c & 0xff);
}
@@ -472,12 +472,12 @@ void bcm43xx_printk_bitdump(const unsigned char *data,
int j;
const unsigned char *d;
- printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***",
+ printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
for (i = 0; i < bytes; i++) {
d = data + i;
if (i % 8 == 0)
- printk("\n" KERN_INFO PFX "0x%08x: ", i);
+ printk("\n" KERN_INFO PFX "0x%08zx: ", i);
if (msb_to_lsb) {
for (j = 7; j >= 0; j--) {
if (*d & (1 << j))
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index c3681b8f09b4..bbecba02e697 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -196,8 +196,9 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
}
if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G "
- "(0x%08x, len: %lu)\n",
- ring->dmabase, BCM43xx_DMA_RINGMEMSIZE);
+ "(0x%llx, len: %lu)\n",
+ (unsigned long long)ring->dmabase,
+ BCM43xx_DMA_RINGMEMSIZE);
dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
ring->vbase, ring->dmabase);
return -ENOMEM;
@@ -307,8 +308,8 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
dev_kfree_skb_any(skb);
printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G "
- "(0x%08x, len: %u)\n",
- dmaaddr, ring->rx_buffersize);
+ "(0x%llx, len: %u)\n",
+ (unsigned long long)dmaaddr, ring->rx_buffersize);
return -ENOMEM;
}
meta->skb = skb;
@@ -729,8 +730,8 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring,
if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
return_slot(ring, slot);
printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G "
- "(0x%08x, len: %u)\n",
- meta->dmaaddr, skb->len);
+ "(0x%llx, len: %u)\n",
+ (unsigned long long)meta->dmaaddr, skb->len);
return -ENOMEM;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index 2d520e4b0276..b7d77638ba8c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -213,6 +213,14 @@ static inline
void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
{
}
+static inline
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+{
+}
+static inline
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+{
+}
#endif /* CONFIG_BCM43XX_DMA */
#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index c37371fc9e01..9a06e61df0a2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -52,6 +52,7 @@
#include "bcm43xx_wx.h"
#include "bcm43xx_ethtool.h"
#include "bcm43xx_xmit.h"
+#include "bcm43xx_sysfs.h"
MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
@@ -3522,6 +3523,7 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
err = bcm43xx_pio_tx(bcm, txb);
else
err = bcm43xx_dma_tx(bcm, txb);
+ bcm->net_dev->trans_start = jiffies;
return err;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 0a66f43ca0c0..33137165727f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -2151,6 +2151,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
phy->tssi2dbm = NULL;
printk(KERN_ERR PFX "Could not generate "
"tssi2dBm table\n");
+ kfree(dyn_tssi2dbm);
return -ENODEV;
}
phy->tssi2dbm = dyn_tssi2dbm;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index c59ddd40680d..0aa1bd269a25 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -27,6 +27,7 @@
#include "bcm43xx_pio.h"
#include "bcm43xx_main.h"
#include "bcm43xx_xmit.h"
+#include "bcm43xx_power.h"
#include <linux/delay.h>
@@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue,
bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
octet);
bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
- BCM43xx_PIO_TXCTL_WRITEHI);
+ BCM43xx_PIO_TXCTL_WRITELO);
} else {
bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
- BCM43xx_PIO_TXCTL_WRITEHI);
+ BCM43xx_PIO_TXCTL_WRITELO);
bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
octet);
}
@@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue,
bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
skb->data[skb->len - 1]);
bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
- BCM43xx_PIO_TXCTL_WRITEHI |
+ BCM43xx_PIO_TXCTL_WRITELO |
BCM43xx_PIO_TXCTL_COMPLETE);
} else {
bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
@@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue,
}
static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
- int packetindex)
+ struct bcm43xx_pio_txpacket *packet)
{
u16 cookie = 0x0000;
+ int packetindex;
/* We use the upper 4 bits for the PIO
* controller ID and the lower 12 bits
@@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
default:
assert(0);
}
+ packetindex = pio_txpacket_getindex(packet);
assert(((u16)packetindex & 0xF000) == 0x0000);
cookie |= (u16)packetindex;
@@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
bcm43xx_generate_txhdr(queue->bcm,
&txhdr, skb->data, skb->len,
(packet->xmitted_frags == 0),
- generate_cookie(queue, pio_txpacket_getindex(packet)));
+ generate_cookie(queue, packet));
tx_start(queue);
octets = skb->len + sizeof(txhdr);
@@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
queue->tx_devq_packets++;
queue->tx_devq_used += octets;
- assert(packet->xmitted_frags <= packet->txb->nr_frags);
+ assert(packet->xmitted_frags < packet->txb->nr_frags);
packet->xmitted_frags++;
packet->xmitted_octets += octets;
}
@@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d)
unsigned long flags;
struct bcm43xx_pio_txpacket *packet, *tmp_packet;
int err;
+ u16 txctl;
bcm43xx_lock_mmio(bcm, flags);
+
+ txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+ if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
+ goto out_unlock;
+
list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
assert(packet->xmitted_frags < packet->txb->nr_frags);
if (packet->xmitted_frags == 0) {
@@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d)
next_packet:
continue;
}
+out_unlock:
bcm43xx_unlock_mmio(bcm, flags);
}
@@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
(unsigned long)queue);
value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
- value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
+ value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+ if (qsize == 0) {
+ printk(KERN_ERR PFX "ERROR: This card does not support PIO "
+ "operation mode. Please use DMA mode "
+ "(module parameter pio=0).\n");
+ goto err_freequeue;
+ }
if (qsize <= BCM43xx_PIO_TXQADJUST) {
- printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
+ printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
+ qsize);
goto err_freequeue;
}
qsize -= BCM43xx_PIO_TXQADJUST;
@@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
{
struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
struct bcm43xx_pio_txpacket *packet;
- u16 tmp;
assert(!queue->tx_suspended);
assert(!list_empty(&queue->txfree));
- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
- if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
- return -EBUSY;
-
packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
packet->txb = txb;
packet->xmitted_frags = 0;
@@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
/* Suspend TX, if we are out of packets in the "free" queue. */
- if (unlikely(list_empty(&queue->txfree))) {
+ if (list_empty(&queue->txfree)) {
netif_stop_queue(queue->bcm->net_dev);
queue->tx_suspended = 1;
}
@@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
queue = parse_cookie(bcm, status->cookie, &packet);
assert(queue);
-//TODO
-if (!queue)
-return;
+
free_txpacket(packet, 1);
- if (unlikely(queue->tx_suspended)) {
+ if (queue->tx_suspended) {
queue->tx_suspended = 0;
netif_wake_queue(queue->bcm->net_dev);
}
- /* If there are packets on the txqueue, poke the tasklet. */
+ /* If there are packets on the txqueue, poke the tasklet
+ * to transmit them.
+ */
if (!list_empty(&queue->txqueue))
tasklet_schedule(&queue->txtask);
}
@@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
int i, preamble_readwords;
struct sk_buff *skb;
-return;
tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
- if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
- dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
+ if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
return;
- }
bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
BCM43xx_PIO_RXCTL_DATAAVAILABLE);
@@ -538,8 +547,7 @@ return;
return;
data_ready:
-//FIXME: endianess in this function.
- len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
+ len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
if (unlikely(len > 0x700)) {
pio_rx_error(queue, 0, "len > 0x700");
return;
@@ -555,7 +563,7 @@ data_ready:
preamble_readwords = 18 / sizeof(u16);
for (i = 0; i < preamble_readwords; i++) {
tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
- preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
+ preamble[i + 1] = cpu_to_le16(tmp);
}
rxhdr = (struct bcm43xx_rxhdr *)preamble;
rxflags2 = le16_to_cpu(rxhdr->flags2);
@@ -591,16 +599,40 @@ data_ready:
}
skb_put(skb, len);
for (i = 0; i < len - 1; i += 2) {
- tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
- *((u16 *)(skb->data + i)) = tmp;
+ tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+ *((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
}
if (len % 2) {
tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
skb->data[len - 1] = (tmp & 0x00FF);
+/* The specs say the following is required, but
+ * it is wrong and corrupts the PLCP. If we don't do
+ * this, the PLCP seems to be correct. So ifdef it out for now.
+ */
+#if 0
if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
- skb->data[0x20] = (tmp & 0xFF00) >> 8;
+ skb->data[2] = (tmp & 0xFF00) >> 8;
else
- skb->data[0x1E] = (tmp & 0xFF00) >> 8;
+ skb->data[0] = (tmp & 0xFF00) >> 8;
+#endif
}
+ skb_trim(skb, len - IEEE80211_FCS_LEN);
bcm43xx_rx(queue->bcm, skb, rxhdr);
}
+
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+ bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+ | BCM43xx_PIO_TXCTL_SUSPEND);
+}
+
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+ & ~BCM43xx_PIO_TXCTL_SUSPEND);
+ bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
+ tasklet_schedule(&queue->txtask);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
index 970627bc1769..dfc78209e3a3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -14,8 +14,8 @@
#define BCM43xx_PIO_RXCTL 0x08
#define BCM43xx_PIO_RXDATA 0x0A
-#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0)
-#define BCM43xx_PIO_TXCTL_WRITELO (1 << 1)
+#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0)
+#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1)
#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
@@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
u16 offset, u16 value)
{
bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+ mmiowb();
}
@@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
struct bcm43xx_xmitstatus *status);
void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+
#else /* CONFIG_BCM43XX_PIO */
static inline
@@ -133,6 +137,14 @@ static inline
void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
{
}
+static inline
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+}
+static inline
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+}
#endif /* CONFIG_BCM43XX_PIO */
#endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
index 3c92b62807c5..6569da3a7a39 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -35,77 +35,101 @@
#include "bcm43xx_main.h"
+/* Get the Slow Clock Source */
+static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+{
+ u32 tmp;
+ int err;
+
+ assert(bcm->current_core == &bcm->core_chipcommon);
+ if (bcm->current_core->rev < 6) {
+ if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+ bcm->bustype == BCM43xx_BUSTYPE_SB)
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+ if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+ assert(!err);
+ if (tmp & 0x10)
+ return BCM43xx_PCTL_CLKSRC_PCI;
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+ }
+ }
+ if (bcm->current_core->rev < 10) {
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+ tmp &= 0x7;
+ if (tmp == 0)
+ return BCM43xx_PCTL_CLKSRC_LOPWROS;
+ if (tmp == 1)
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+ if (tmp == 2)
+ return BCM43xx_PCTL_CLKSRC_PCI;
+ }
+
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+}
+
/* Get max/min slowclock frequency
* as described in http://bcm-specs.sipsolutions.net/PowerControl
*/
static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
int get_max)
{
- int limit = 0;
+ int limit;
+ int clocksrc;
int divisor;
- int selection;
- int err;
u32 tmp;
- struct bcm43xx_coreinfo *old_core;
- if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
- goto out;
- old_core = bcm->current_core;
- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
- if (err)
- goto out;
+ assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+ assert(bcm->current_core == &bcm->core_chipcommon);
+ clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
if (bcm->current_core->rev < 6) {
- if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
- (bcm->bustype == BCM43xx_BUSTYPE_SB)) {
- selection = 1;
+ switch (clocksrc) {
+ case BCM43xx_PCTL_CLKSRC_PCI:
+ divisor = 64;
+ break;
+ case BCM43xx_PCTL_CLKSRC_XTALOS:
divisor = 32;
- } else {
- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
- if (err) {
- printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
- goto out_switchback;
- }
- if (tmp & 0x10) {
- /* PCI */
- selection = 2;
- divisor = 64;
- } else {
- /* XTAL */
- selection = 1;
- divisor = 32;
- }
+ break;
+ default:
+ assert(0);
+ divisor = 1;
}
} else if (bcm->current_core->rev < 10) {
- selection = (tmp & 0x07);
- if (selection) {
+ switch (clocksrc) {
+ case BCM43xx_PCTL_CLKSRC_LOPWROS:
+ divisor = 1;
+ break;
+ case BCM43xx_PCTL_CLKSRC_XTALOS:
+ case BCM43xx_PCTL_CLKSRC_PCI:
tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
- divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
- } else
+ divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+ divisor *= 4;
+ break;
+ default:
+ assert(0);
divisor = 1;
+ }
} else {
tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
- divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
- selection = 1;
+ divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+ divisor *= 4;
}
-
- switch (selection) {
- case 0:
- /* LPO */
+
+ switch (clocksrc) {
+ case BCM43xx_PCTL_CLKSRC_LOPWROS:
if (get_max)
limit = 43000;
else
limit = 25000;
break;
- case 1:
- /* XTAL */
+ case BCM43xx_PCTL_CLKSRC_XTALOS:
if (get_max)
limit = 20200000;
else
limit = 19800000;
break;
- case 2:
- /* PCI */
+ case BCM43xx_PCTL_CLKSRC_PCI:
if (get_max)
limit = 34000000;
else
@@ -113,17 +137,14 @@ static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
break;
default:
assert(0);
+ limit = 0;
}
limit /= divisor;
-out_switchback:
- err = bcm43xx_switch_core(bcm, old_core);
- assert(err == 0);
-
-out:
return limit;
}
+
/* init power control
* as described in http://bcm-specs.sipsolutions.net/PowerControl
*/
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
index 5f63640810bd..c966ab3a5a8c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
@@ -33,6 +33,15 @@
#include <linux/types.h>
+/* Clock sources */
+enum {
+ /* PCI clock */
+ BCM43xx_PCTL_CLKSRC_PCI,
+ /* Crystal slow clock oscillator */
+ BCM43xx_PCTL_CLKSRC_XTALOS,
+ /* Low power oscillator */
+ BCM43xx_PCTL_CLKSRC_LOPWROS,
+};
struct bcm43xx_private;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index c44d890b949b..b438f48e891d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -71,14 +71,46 @@ static int get_boolean(const char *buf, size_t count)
return -EINVAL;
}
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+{
+ int i, pos = 0;
+
+ for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+ pos += snprintf(buf + pos, buf_len - pos - 1,
+ "%04X", swab16(sprom[i]) & 0xFFFF);
+ }
+ pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+
+ return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+{
+ char tmp[5] = { 0 };
+ int cnt = 0;
+ unsigned long parsed;
+
+ if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+ return -EINVAL;
+
+ while (cnt < BCM43xx_SPROM_SIZE) {
+ memcpy(tmp, dump, 4);
+ dump += 4;
+ parsed = simple_strtoul(tmp, NULL, 16);
+ sprom[cnt++] = swab16((u16)parsed);
+ }
+
+ return 0;
+}
+
static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
u16 *sprom;
unsigned long flags;
- int i, err;
+ int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -91,55 +123,53 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
bcm43xx_lock_mmio(bcm, flags);
assert(bcm->initialized);
err = bcm43xx_sprom_read(bcm, sprom);
- if (!err) {
- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
- buf[i * 2] = sprom[i] & 0x00FF;
- buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
- }
- }
+ if (!err)
+ err = sprom2hex(sprom, buf, PAGE_SIZE);
bcm43xx_unlock_mmio(bcm, flags);
kfree(sprom);
- return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
+ return err;
}
static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
u16 *sprom;
unsigned long flags;
- int i, err;
+ int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
- return -EINVAL;
sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
GFP_KERNEL);
if (!sprom)
return -ENOMEM;
- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
- sprom[i] = buf[i * 2] & 0xFF;
- sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
- }
+ err = hex2sprom(sprom, buf, count);
+ if (err)
+ goto out_kfree;
bcm43xx_lock_mmio(bcm, flags);
assert(bcm->initialized);
err = bcm43xx_sprom_write(bcm, sprom);
bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
kfree(sprom);
return err ? err : count;
}
+static DEVICE_ATTR(sprom, 0600,
+ bcm43xx_attr_sprom_show,
+ bcm43xx_attr_sprom_store);
+
static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
ssize_t count = 0;
@@ -175,7 +205,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
int mode;
@@ -215,11 +245,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
return err ? err : count;
}
+static DEVICE_ATTR(interference, 0644,
+ bcm43xx_attr_interfmode_show,
+ bcm43xx_attr_interfmode_store);
+
static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
ssize_t count;
@@ -245,7 +279,7 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
int value;
@@ -267,56 +301,41 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
return err ? err : count;
}
+static DEVICE_ATTR(shortpreamble, 0644,
+ bcm43xx_attr_preamble_show,
+ bcm43xx_attr_preamble_store);
+
int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
{
struct device *dev = &bcm->pci_dev->dev;
- struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
int err;
assert(bcm->initialized);
- sysfs->attr_sprom.attr.name = "sprom";
- sysfs->attr_sprom.attr.owner = THIS_MODULE;
- sysfs->attr_sprom.attr.mode = 0600;
- sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
- sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
- err = device_create_file(dev, &sysfs->attr_sprom);
+ err = device_create_file(dev, &dev_attr_sprom);
if (err)
goto out;
-
- sysfs->attr_interfmode.attr.name = "interference";
- sysfs->attr_interfmode.attr.owner = THIS_MODULE;
- sysfs->attr_interfmode.attr.mode = 0600;
- sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
- sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
- err = device_create_file(dev, &sysfs->attr_interfmode);
+ err = device_create_file(dev, &dev_attr_interference);
if (err)
goto err_remove_sprom;
-
- sysfs->attr_preamble.attr.name = "shortpreamble";
- sysfs->attr_preamble.attr.owner = THIS_MODULE;
- sysfs->attr_preamble.attr.mode = 0600;
- sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
- sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
- err = device_create_file(dev, &sysfs->attr_preamble);
+ err = device_create_file(dev, &dev_attr_shortpreamble);
if (err)
goto err_remove_interfmode;
out:
return err;
err_remove_interfmode:
- device_remove_file(dev, &sysfs->attr_interfmode);
+ device_remove_file(dev, &dev_attr_interference);
err_remove_sprom:
- device_remove_file(dev, &sysfs->attr_sprom);
+ device_remove_file(dev, &dev_attr_sprom);
goto out;
}
void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
{
struct device *dev = &bcm->pci_dev->dev;
- struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
- device_remove_file(dev, &sysfs->attr_preamble);
- device_remove_file(dev, &sysfs->attr_interfmode);
- device_remove_file(dev, &sysfs->attr_sprom);
+ device_remove_file(dev, &dev_attr_shortpreamble);
+ device_remove_file(dev, &dev_attr_interference);
+ device_remove_file(dev, &dev_attr_sprom);
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
index 57f14514e3e0..cc701df71e2a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
@@ -1,22 +1,6 @@
#ifndef BCM43xx_SYSFS_H_
#define BCM43xx_SYSFS_H_
-#include <linux/device.h>
-
-
-struct bcm43xx_sysfs {
- struct device_attribute attr_sprom;
- struct device_attribute attr_interfmode;
- struct device_attribute attr_preamble;
-};
-
-#define devattr_to_bcm(attr, attr_name) ({ \
- struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \
- __s = container_of((attr), struct bcm43xx_sysfs, attr_name); \
- __p = container_of(__s, struct bcm43xx_private, sysfs); \
- __p; \
- })
-
struct bcm43xx_private;
int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 3daee828ef4b..3edbb481a0a0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -962,22 +962,22 @@ static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
{
.cmd = PRIV_WX_SET_SHORTPREAMBLE,
.set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- .name = "set_shortpreambl",
+ .name = "set_shortpreamb",
},
{
.cmd = PRIV_WX_GET_SHORTPREAMBLE,
.get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
- .name = "get_shortpreambl",
+ .name = "get_shortpreamb",
},
{
.cmd = PRIV_WX_SET_SWENCRYPTION,
.set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- .name = "set_swencryption",
+ .name = "set_swencrypt",
},
{
.cmd = PRIV_WX_GET_SWENCRYPTION,
.get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
- .name = "get_swencryption",
+ .name = "get_swencrypt",
},
{
.cmd = PRIV_WX_SPROM_WRITE,
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index d335b250923a..55bed923fbe9 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
/* struct local_info::hw_priv */
struct hostap_cs_priv {
dev_node_t node;
- dev_link_t *link;
+ struct pcmcia_device *link;
int sandisk_connectplus;
};
@@ -204,15 +204,13 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
static void prism2_detach(struct pcmcia_device *p_dev);
static void prism2_release(u_long arg);
-static int prism2_config(dev_link_t *link);
+static int prism2_config(struct pcmcia_device *link);
static int prism2_pccard_card_present(local_info_t *local)
{
struct hostap_cs_priv *hw_priv = local->hw_priv;
- if (hw_priv != NULL && hw_priv->link != NULL &&
- ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) ==
- (DEV_PRESENT | DEV_CONFIG)))
+ if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link))
return 1;
return 0;
}
@@ -237,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local)
reg.Action = CS_WRITE;
reg.Offset = 0x10; /* 0x3f0 IO base 1 */
reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
@@ -249,7 +247,7 @@ static void sandisk_set_iobase(local_info_t *local)
reg.Action = CS_WRITE;
reg.Offset = 0x12; /* 0x3f2 IO base 2 */
reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
@@ -301,9 +299,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
- pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
- pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+ if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+ pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+ pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
/* No SanDisk manfid found */
ret = -ENODEV;
@@ -311,9 +309,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
}
tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
- if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
- pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
- pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+ if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+ pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+ pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
parse->longlink_mfc.nfn < 2) {
/* No multi-function links found */
ret = -ENODEV;
@@ -328,7 +326,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
reg.Value = COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -345,7 +343,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
* will be enabled during the first cor_sreset call.
*/
reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -380,7 +378,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
reg.Value = 0;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
@@ -392,7 +390,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Action = CS_WRITE;
reg.Value |= COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
@@ -405,7 +403,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Value &= ~COR_SOFT_RESET;
if (hw_priv->sandisk_connectplus)
reg.Value |= COR_IREQ_ENA;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
@@ -439,7 +437,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
reg.Value = 0;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
@@ -452,7 +450,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_WRITE;
reg.Value |= COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
@@ -466,7 +464,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_WRITE;
reg.Value = hcr;
reg.Offset = CISREG_CCSR;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
@@ -478,7 +476,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
reg.Value = old_cor & ~COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
@@ -501,40 +499,27 @@ static struct prism2_helper_functions prism2_pccard_funcs =
/* allocate local data and register with CardServices
* initialize dev_link structure, but do not configure the card yet */
-static int prism2_attach(struct pcmcia_device *p_dev)
+static int hostap_cs_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
-
- link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
- if (link == NULL)
- return -ENOMEM;
-
- memset(link, 0, sizeof(dev_link_t));
+ int ret;
PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
- link->conf.Vcc = 33;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
- link->handle = p_dev;
- p_dev->instance = link;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- if (prism2_config(link))
+ ret = prism2_config(p_dev);
+ if (ret) {
PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+ }
- return 0;
+ return ret;
}
-static void prism2_detach(struct pcmcia_device *p_dev)
+static void prism2_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
PDEBUG(DEBUG_FLOW, "prism2_detach\n");
- if (link->state & DEV_CONFIG) {
- prism2_release((u_long)link);
- }
+ prism2_release((u_long)link);
/* release net devices */
if (link->priv) {
@@ -547,7 +532,6 @@ static void prism2_detach(struct pcmcia_device *p_dev)
prism2_free_local_data(dev);
kfree(hw_priv);
}
- kfree(link);
}
@@ -558,7 +542,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
do { int ret = (retf); \
if (ret != 0) { \
PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
- cs_error(link->handle, fn, ret); \
+ cs_error(link, fn, ret); \
goto next_entry; \
} \
} while (0)
@@ -566,7 +550,7 @@ if (ret != 0) { \
/* run after a CARD_INSERTION event is received to configure the PCMCIA
* socket and make the device available to the system */
-static int prism2_config(dev_link_t *link)
+static int prism2_config(struct pcmcia_device *link)
{
struct net_device *dev;
struct hostap_interface *iface;
@@ -595,27 +579,24 @@ static int prism2_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link->handle, &conf));
- PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info,
- ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc);
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
/* Look for an appropriate configuration table entry in the CIS */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
for (;;) {
cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
CFG_CHECK2(GetTupleData,
- pcmcia_get_tuple_data(link->handle, &tuple));
+ pcmcia_get_tuple_data(link, &tuple));
CFG_CHECK2(ParseTuple,
- pcmcia_parse_tuple(link->handle, &tuple, parse));
+ pcmcia_parse_tuple(link, &tuple, parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
@@ -650,10 +631,10 @@ static int prism2_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
@@ -695,19 +676,19 @@ static int prism2_config(dev_link_t *link)
/* This reserves IO space but doesn't actually enable it */
CFG_CHECK2(RequestIO,
- pcmcia_request_io(link->handle, &link->io));
+ pcmcia_request_io(link, &link->io));
/* This configuration table entry is OK */
break;
next_entry:
CS_CHECK(GetNextTuple,
- pcmcia_get_next_tuple(link->handle, &tuple));
+ pcmcia_get_next_tuple(link, &tuple));
}
/* Need to allocate net_device before requesting IRQ handler */
dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
- &handle_to_dev(link->handle));
+ &handle_to_dev(link));
if (dev == NULL)
goto failed;
link->priv = dev;
@@ -717,7 +698,7 @@ static int prism2_config(dev_link_t *link)
local->hw_priv = hw_priv;
hw_priv->link = link;
strcpy(hw_priv->node.dev_name, dev->name);
- link->dev = &hw_priv->node;
+ link->dev_node = &hw_priv->node;
/*
* Allocate an interrupt line. Note that this does not assign a
@@ -730,7 +711,7 @@ static int prism2_config(dev_link_t *link)
link->irq.Handler = prism2_interrupt;
link->irq.Instance = dev;
CS_CHECK(RequestIRQ,
- pcmcia_request_irq(link->handle, &link->irq));
+ pcmcia_request_irq(link, &link->irq));
}
/*
@@ -739,18 +720,17 @@ static int prism2_config(dev_link_t *link)
* card and host interface into "Memory and IO" mode.
*/
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev_info, link->conf.ConfigIndex,
- link->conf.Vcc / 10, link->conf.Vcc % 10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
- link->conf.Vpp1 % 10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev_info, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp / 10,
+ link->conf.Vpp % 10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -761,9 +741,6 @@ static int prism2_config(dev_link_t *link)
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
- link->state |= DEV_CONFIG;
- link->state &= ~DEV_CONFIG_PENDING;
-
local->shutdown = 0;
sandisk_enable_wireless(dev);
@@ -778,7 +755,7 @@ static int prism2_config(dev_link_t *link)
return ret;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
kfree(parse);
@@ -790,7 +767,7 @@ static int prism2_config(dev_link_t *link)
static void prism2_release(u_long arg)
{
- dev_link_t *link = (dev_link_t *)arg;
+ struct pcmcia_device *link = (struct pcmcia_device *)arg;
PDEBUG(DEBUG_FLOW, "prism2_release\n");
@@ -799,71 +776,54 @@ static void prism2_release(u_long arg)
struct hostap_interface *iface;
iface = netdev_priv(dev);
- if (link->state & DEV_CONFIG)
- prism2_hw_shutdown(dev, 0);
+ prism2_hw_shutdown(dev, 0);
iface->local->shutdown = 1;
}
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-
+ pcmcia_disable_device(link);
PDEBUG(DEBUG_FLOW, "release - done\n");
}
-static int hostap_cs_suspend(struct pcmcia_device *p_dev)
+static int hostap_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0;
+ struct hostap_interface *iface = NULL;
- PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
-
- link->state |= DEV_SUSPEND;
+ if (dev)
+ iface = netdev_priv(dev);
- if (link->state & DEV_CONFIG) {
- struct hostap_interface *iface = netdev_priv(dev);
- if (iface && iface->local)
- dev_open = iface->local->num_dev_open > 0;
- if (dev_open) {
- netif_stop_queue(dev);
- netif_device_detach(dev);
- }
- prism2_suspend(dev);
- pcmcia_release_configuration(link->handle);
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
+ if (dev_open) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
}
+ prism2_suspend(dev);
return 0;
}
-static int hostap_cs_resume(struct pcmcia_device *p_dev)
+static int hostap_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0;
+ struct hostap_interface *iface = NULL;
- PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+ if (dev)
+ iface = netdev_priv(dev);
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- struct hostap_interface *iface = netdev_priv(dev);
- if (iface && iface->local)
- dev_open = iface->local->num_dev_open > 0;
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
- pcmcia_request_configuration(link->handle, &link->conf);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
- prism2_hw_shutdown(dev, 1);
- prism2_hw_config(dev, dev_open ? 0 : 1);
- if (dev_open) {
- netif_device_attach(dev);
- netif_start_queue(dev);
- }
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, dev_open ? 0 : 1);
+ if (dev_open) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
}
return 0;
@@ -930,7 +890,7 @@ static struct pcmcia_driver hostap_driver = {
.drv = {
.name = "hostap_cs",
},
- .probe = prism2_attach,
+ .probe = hostap_cs_probe,
.remove = prism2_detach,
.owner = THIS_MODULE,
.id_table = hostap_cs_ids,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 8b37e824dfcb..8399de581893 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local,
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
if (scan) {
- chan = scan->chid;
+ chan = le16_to_cpu(scan->chid);
} else if (bss) {
chan = bss->chan;
} else {
@@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local,
}
if (chan > 0) {
- iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
+ iwe.u.freq.m = freq_list[chan - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_FREQ_LEN);
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9dce522526c5..bca89cff85a6 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -5573,8 +5573,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
case IEEE80211_52GHZ_BAND:
network->mode = IEEE_A;
i = ieee80211_channel_to_index(priv->ieee, priv->channel);
- if (i == -1)
- BUG();
+ BUG_ON(i == -1);
if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
IPW_WARNING("Overriding invalid channel\n");
priv->channel = geo->a[0].channel;
@@ -5587,8 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
else
network->mode = IEEE_B;
i = ieee80211_channel_to_index(priv->ieee, priv->channel);
- if (i == -1)
- BUG();
+ BUG_ON(i == -1);
if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
IPW_WARNING("Overriding invalid channel\n");
priv->channel = geo->bg[0].channel;
@@ -6715,8 +6713,7 @@ static int ipw_qos_association(struct ipw_priv *priv,
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
- if (!(network->capability & WLAN_CAPABILITY_IBSS))
- BUG();
+ BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS));
qos_data = &ibss_data;
break;
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 75ce6ddb0cf5..9343d970537b 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -190,8 +190,8 @@ module_param(mem_speed, int, 0);
/*====================================================================*/
/* PCMCIA (Card Services) related functions */
-static void netwave_release(dev_link_t *link); /* Card removal */
-static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card
+static void netwave_release(struct pcmcia_device *link); /* Card removal */
+static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card
insertion */
static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */
@@ -221,10 +221,10 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
/*
- A dev_link_t structure has fields for most things that are needed
+ A struct pcmcia_device structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
+ 'priv' pointer in a struct pcmcia_device structure can be used to point to
a device-specific private data structure, like this.
A driver needs to provide a dev_node_t structure for each device
@@ -232,7 +232,7 @@ static void set_multicast_list(struct net_device *dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
@@ -268,7 +268,7 @@ struct site_survey {
};
typedef struct netwave_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
dev_node_t node;
u_char __iomem *ramBase;
@@ -376,20 +376,19 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
* configure the card at this point -- we wait until we receive a
* card insertion event.
*/
-static int netwave_attach(struct pcmcia_device *p_dev)
+static int netwave_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
struct net_device *dev;
netwave_private *priv;
DEBUG(0, "netwave_attach()\n");
- /* Initialize the dev_link_t structure */
+ /* Initialize the struct pcmcia_device structure */
dev = alloc_etherdev(sizeof(netwave_private));
if (!dev)
return -ENOMEM;
priv = netdev_priv(dev);
- link = &priv->link;
+ priv->p_dev = link;
link->priv = dev;
/* The io structure describes IO port mapping */
@@ -406,7 +405,6 @@ static int netwave_attach(struct pcmcia_device *p_dev)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -430,13 +428,7 @@ static int netwave_attach(struct pcmcia_device *p_dev)
dev->stop = &netwave_close;
link->irq.Instance = dev;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- netwave_pcmcia_config( link);
-
- return 0;
+ return netwave_pcmcia_config( link);
} /* netwave_attach */
/*
@@ -447,17 +439,15 @@ static int netwave_attach(struct pcmcia_device *p_dev)
* structures are freed. Otherwise, the structures will be freed
* when the device is released.
*/
-static void netwave_detach(struct pcmcia_device *p_dev)
+static void netwave_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "netwave_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- netwave_release(link);
+ netwave_release(link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
free_netdev(dev);
@@ -743,8 +733,7 @@ static const struct iw_handler_def netwave_handler_def =
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void netwave_pcmcia_config(dev_link_t *link) {
- client_handle_t handle = link->handle;
+static int netwave_pcmcia_config(struct pcmcia_device *link) {
struct net_device *dev = link->priv;
netwave_private *priv = netdev_priv(dev);
tuple_t tuple;
@@ -766,15 +755,12 @@ static void netwave_pcmcia_config(dev_link_t *link) {
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/*
* Try allocating IO ports. This tries a few fixed addresses.
* If you want, you can also read the card's config table to
@@ -782,11 +768,11 @@ static void netwave_pcmcia_config(dev_link_t *link) {
*/
for (i = j = 0x0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
@@ -794,16 +780,16 @@ static void netwave_pcmcia_config(dev_link_t *link) {
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
* This actually configures the PCMCIA socket -- setting up
* the I/O windows and the interrupt mapping.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
- * Allocate a 32K memory window. Note that the dev_link_t
+ * Allocate a 32K memory window. Note that the struct pcmcia_device
* structure provides space for one window handle -- if your
* device needs several windows, you'll need to keep track of
* the handles in your private data structure, dev->priv.
@@ -813,7 +799,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
req.Base = 0; req.Size = 0x8000;
req.AccessSpeed = mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = 0x20000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
@@ -823,7 +809,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
@@ -831,8 +817,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
}
strcpy(priv->node.dev_name, dev->name);
- link->dev = &priv->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &priv->node;
/* Reset card before reading physical address */
netwave_doreset(dev->base_addr, ramBase);
@@ -852,12 +837,13 @@ static void netwave_pcmcia_config(dev_link_t *link) {
printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n",
get_uint16(ramBase + NETWAVE_EREG_ARW),
get_uint16(ramBase + NETWAVE_EREG_ARW+2));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
netwave_release(link);
+ return -ENODEV;
} /* netwave_pcmcia_config */
/*
@@ -867,52 +853,35 @@ failed:
* device, and release the PCMCIA configuration. If the device is
* still open, this will be postponed until it is closed.
*/
-static void netwave_release(dev_link_t *link)
+static void netwave_release(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- netwave_private *priv = netdev_priv(dev);
-
- DEBUG(0, "netwave_release(0x%p)\n", link);
+ struct net_device *dev = link->priv;
+ netwave_private *priv = netdev_priv(dev);
- /* Don't bother checking to see if these succeed or not */
- if (link->win) {
- iounmap(priv->ramBase);
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ DEBUG(0, "netwave_release(0x%p)\n", link);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
+ if (link->win)
+ iounmap(priv->ramBase);
}
-static int netwave_suspend(struct pcmcia_device *p_dev)
+static int netwave_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int netwave_resume(struct pcmcia_device *p_dev)
+static int netwave_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- netwave_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ netwave_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -1119,7 +1088,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
u_char __iomem *ramBase;
struct net_device *dev = (struct net_device *)dev_id;
struct netwave_private *priv = netdev_priv(dev);
- dev_link_t *link = &priv->link;
+ struct pcmcia_device *link = priv->p_dev;
int i;
if (!netif_device_present(dev))
@@ -1138,7 +1107,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
status = inb(iobase + NETWAVE_REG_ASR);
- if (!DEV_OK(link)) {
+ if (!pcmcia_dev_present(link)) {
DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x "
"from removed or suspended card!\n", status);
break;
@@ -1373,11 +1342,11 @@ static int netwave_rx(struct net_device *dev)
static int netwave_open(struct net_device *dev) {
netwave_private *priv = netdev_priv(dev);
- dev_link_t *link = &priv->link;
+ struct pcmcia_device *link = priv->p_dev;
DEBUG(1, "netwave_open: starting.\n");
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1390,7 +1359,7 @@ static int netwave_open(struct net_device *dev) {
static int netwave_close(struct net_device *dev) {
netwave_private *priv = netdev_priv(dev);
- dev_link_t *link = &priv->link;
+ struct pcmcia_device *link = priv->p_dev;
DEBUG(1, "netwave_close: finishing.\n");
@@ -1411,7 +1380,7 @@ static struct pcmcia_driver netwave_driver = {
.drv = {
.name = "netwave_cs",
},
- .probe = netwave_attach,
+ .probe = netwave_probe,
.remove = netwave_detach,
.id_table = netwave_ids,
.suspend = netwave_suspend,
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 8dfdfbd5966c..06523e2a8471 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -390,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
}
} else {
struct {
- __le16 qual, signal, noise;
+ __le16 qual, signal, noise, unused;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index ec6f2a48895b..434f7d7ad841 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
/* PCMCIA specific device information (goes in the card field of
* struct orinoco_private */
struct orinoco_pccard {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
/* Used to handle hard reset */
@@ -63,8 +63,8 @@ struct orinoco_pccard {
/* Function prototypes */
/********************************************************************/
-static void orinoco_cs_config(dev_link_t *link);
-static void orinoco_cs_release(dev_link_t *link);
+static int orinoco_cs_config(struct pcmcia_device *link);
+static void orinoco_cs_release(struct pcmcia_device *link);
static void orinoco_cs_detach(struct pcmcia_device *p_dev);
/********************************************************************/
@@ -75,13 +75,13 @@ static int
orinoco_cs_hard_reset(struct orinoco_private *priv)
{
struct orinoco_pccard *card = priv->card;
- dev_link_t *link = &card->link;
+ struct pcmcia_device *link = card->p_dev;
int err;
/* We need atomic ops here, because we're not holding the lock */
set_bit(0, &card->hard_reset_in_progress);
- err = pcmcia_reset_card(link->handle, NULL);
+ err = pcmcia_reset_card(link, NULL);
if (err)
return err;
@@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
* configure the card at this point -- we wait until we receive a card
* insertion event. */
static int
-orinoco_cs_attach(struct pcmcia_device *p_dev)
+orinoco_cs_probe(struct pcmcia_device *link)
{
struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev_link_t *link;
dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
if (! dev)
@@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
card = priv->card;
/* Link both structures together */
- link = &card->link;
+ card->p_dev = link;
link->priv = dev;
/* Interrupt setup */
@@ -135,16 +134,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- link->next = NULL;
-
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- orinoco_cs_config(link);
-
- return 0;
+ return orinoco_cs_config(link);
} /* orinoco_cs_attach */
/*
@@ -153,16 +143,14 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void orinoco_cs_detach(struct pcmcia_device *p_dev)
+static void orinoco_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- if (link->state & DEV_CONFIG)
- orinoco_cs_release(link);
+ orinoco_cs_release(link);
- DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
- if (link->dev) {
+ DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+ if (link->dev_node) {
DEBUG(0, PFX "About to unregister net device %p\n",
dev);
unregister_netdev(dev);
@@ -180,11 +168,10 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev)
last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
} while (0)
-static void
-orinoco_cs_config(dev_link_t *link)
+static int
+orinoco_cs_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- client_handle_t handle = link->handle;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
@@ -196,7 +183,7 @@ orinoco_cs_config(dev_link_t *link)
cisparse_t parse;
void __iomem *mem;
- CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
/*
* This reads the card's CONFIG tuple to find its
@@ -207,19 +194,15 @@ orinoco_cs_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
/*
* In this loop, we scan the CIS for configuration table
@@ -236,13 +219,13 @@ orinoco_cs_config(dev_link_t *link)
* implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_cftable_entry_t dflt = { .index = 0 };
- if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
- || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+ if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+ || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -274,10 +257,10 @@ orinoco_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
@@ -307,7 +290,7 @@ orinoco_cs_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
@@ -317,9 +300,8 @@ orinoco_cs_config(dev_link_t *link)
break;
next_entry:
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ pcmcia_disable_device(link);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
if (last_ret == CS_NO_MORE_ITEMS) {
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
@@ -333,7 +315,7 @@ orinoco_cs_config(dev_link_t *link)
* a handler to the interrupt, unless the 'Handler' member of
* the irq structure is initialized.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/* We initialize the hermes structure before completing PCMCIA
* configuration just in case the interrupt handler gets
@@ -350,7 +332,7 @@ orinoco_cs_config(dev_link_t *link)
* card and host interface into "Memory and IO" mode.
*/
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
/* Ok, we have the configuration, prepare to register the netdev */
dev->base_addr = link->io.BasePort1;
@@ -358,7 +340,7 @@ orinoco_cs_config(dev_link_t *link)
SET_MODULE_OWNER(dev);
card->node.major = card->node.minor = 0;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -366,20 +348,18 @@ orinoco_cs_config(dev_link_t *link)
}
/* At this point, the dev_node_t structure(s) needs to be
- * initialized and arranged in a linked list at link->dev. */
+ * initialized and arranged in a linked list at link->dev_node. */
strcpy(card->node.dev_name, dev->name);
- link->dev = &card->node; /* link->dev being non-NULL is also
+ link->dev_node = &card->node; /* link->dev_node being non-NULL is also
used to indicate that the
net_device has been registered */
- link->state &= ~DEV_CONFIG_PENDING;
/* Finally, report what we've done */
- printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
- dev->name, link->conf.ConfigIndex,
- link->conf.Vcc / 10, link->conf.Vcc % 10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
- link->conf.Vpp1 % 10);
+ printk(KERN_DEBUG "%s: index 0x%02x: ",
+ dev->name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp / 10,
+ link->conf.Vpp % 10);
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -389,13 +369,14 @@ orinoco_cs_config(dev_link_t *link)
link->io.BasePort2 + link->io.NumPorts2 - 1);
printk("\n");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
orinoco_cs_release(link);
+ return -ENODEV;
} /* orinoco_cs_config */
/*
@@ -404,7 +385,7 @@ orinoco_cs_config(dev_link_t *link)
* still open, this will be postponed until it is closed.
*/
static void
-orinoco_cs_release(dev_link_t *link)
+orinoco_cs_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
@@ -416,88 +397,68 @@ orinoco_cs_release(dev_link_t *link)
priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
if (priv->hw.iobase)
ioport_unmap(priv->hw.iobase);
} /* orinoco_cs_release */
-static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
+static int orinoco_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
unsigned long flags;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- /* This is probably racy, but I can't think of
- a better way, short of rewriting the PCMCIA
- layer to not suck :-( */
- if (! test_bit(0, &card->hard_reset_in_progress)) {
- spin_lock_irqsave(&priv->lock, flags);
+ /* This is probably racy, but I can't think of
+ a better way, short of rewriting the PCMCIA
+ layer to not suck :-( */
+ if (! test_bit(0, &card->hard_reset_in_progress)) {
+ spin_lock_irqsave(&priv->lock, flags);
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: Error %d downing interface\n",
- dev->name, err);
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
- netif_device_detach(dev);
- priv->hw_unavailable++;
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- pcmcia_release_configuration(link->handle);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return 0;
}
-static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+static int orinoco_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
unsigned long flags;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- /* FIXME: should we double check that this is
- * the same card as we had before */
- pcmcia_request_configuration(link->handle, &link->conf);
-
- if (! test_bit(0, &card->hard_reset_in_progress)) {
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
- dev->name, err);
- return -EIO;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
+ if (! test_bit(0, &card->hard_reset_in_progress)) {
+ err = orinoco_reinit_firmware(dev);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+ dev->name, err);
+ return -EIO;
+ }
- netif_device_attach(dev);
- priv->hw_unavailable--;
+ spin_lock_irqsave(&priv->lock, flags);
- if (priv->open && ! priv->hw_unavailable) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card\n",
- dev->name, err);
- }
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
- spin_unlock_irqrestore(&priv->lock, flags);
+ if (priv->open && ! priv->hw_unavailable) {
+ err = __orinoco_up(dev);
+ if (err)
+ printk(KERN_ERR "%s: Error %d restarting card\n",
+ dev->name, err);
}
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return 0;
@@ -604,7 +565,7 @@ static struct pcmcia_driver orinoco_driver = {
.drv = {
.name = DRIVER_NAME,
},
- .probe = orinoco_cs_attach,
+ .probe = orinoco_cs_probe,
.remove = orinoco_cs_detach,
.id_table = orinoco_cs_ids,
.suspend = orinoco_cs_suspend,
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7880d8c31aad..879eb427607c 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -90,8 +90,8 @@ module_param(pc_debug, int, 0);
#define DEBUG(n, args...)
#endif
/** Prototypes based on PCMCIA skeleton driver *******************************/
-static void ray_config(dev_link_t *link);
-static void ray_release(dev_link_t *link);
+static int ray_config(struct pcmcia_device *link);
+static void ray_release(struct pcmcia_device *link);
static void ray_detach(struct pcmcia_device *p_dev);
/***** Prototypes indicated by device structure ******************************/
@@ -190,20 +190,17 @@ static int bc;
static char *phy_addr = NULL;
-/* A linked list of "instances" of the ray device. Each actual
- PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
-*/
-static dev_link_t *dev_list = NULL;
-
-/* A dev_link_t structure has fields for most things that are needed
+/* A struct pcmcia_device structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
+ 'priv' pointer in a struct pcmcia_device structure can be used to point to
a device-specific private data structure, like this.
*/
static unsigned int ray_mem_speed = 500;
+/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
+static struct pcmcia_device *this_device = NULL;
+
MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");
MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");
MODULE_LICENSE("GPL");
@@ -306,56 +303,46 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
configure the card at this point -- we wait until we receive a
card insertion event.
=============================================================================*/
-static int ray_attach(struct pcmcia_device *p_dev)
+static int ray_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
ray_dev_t *local;
struct net_device *dev;
-
- DEBUG(1, "ray_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-
- if (!link)
- return -ENOMEM;
+ DEBUG(1, "ray_attach()\n");
/* Allocate space for private device-specific data */
dev = alloc_etherdev(sizeof(ray_dev_t));
-
if (!dev)
goto fail_alloc_dev;
local = dev->priv;
-
- memset(link, 0, sizeof(struct dev_link_t));
+ local->finder = p_dev;
/* The io structure describes IO port mapping. None used here */
- link->io.NumPorts1 = 0;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 5;
+ p_dev->io.NumPorts1 = 0;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 5;
/* Interrupt setup. For PCMCIA, driver takes what's given */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = &ray_interrupt;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = &ray_interrupt;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
-
- link->priv = dev;
- link->irq.Instance = dev;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
+
+ p_dev->priv = dev;
+ p_dev->irq.Instance = dev;
- local->finder = link;
+ local->finder = p_dev;
local->card_status = CARD_INSERTED;
local->authentication_state = UNAUTHENTICATED;
local->num_multi = 0;
- DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n",
- link,dev,local,&ray_interrupt);
+ DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n",
+ p_dev,dev,local,&ray_interrupt);
/* Raylink entries in the device structure */
dev->hard_start_xmit = &ray_dev_start_xmit;
@@ -379,16 +366,10 @@ static int ray_attach(struct pcmcia_device *p_dev)
init_timer(&local->timer);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ray_config(link);
-
- return 0;
+ this_device = p_dev;
+ return ray_config(p_dev);
fail_alloc_dev:
- kfree(link);
return -ENOMEM;
} /* ray_attach */
/*=============================================================================
@@ -397,37 +378,25 @@ fail_alloc_dev:
structures are freed. Otherwise, the structures will be freed
when the device is released.
=============================================================================*/
-static void ray_detach(struct pcmcia_device *p_dev)
+static void ray_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- dev_link_t **linkp;
struct net_device *dev;
ray_dev_t *local;
DEBUG(1, "ray_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
+ this_device = NULL;
dev = link->priv;
- if (link->state & DEV_CONFIG) {
- ray_release(link);
+ ray_release(link);
- local = (ray_dev_t *)dev->priv;
- del_timer(&local->timer);
- }
+ local = (ray_dev_t *)dev->priv;
+ del_timer(&local->timer);
- /* Unlink device structure, free pieces */
- *linkp = link->next;
if (link->priv) {
- if (link->dev) unregister_netdev(dev);
+ if (link->dev_node) unregister_netdev(dev);
free_netdev(dev);
}
- kfree(link);
DEBUG(2,"ray_cs ray_detach ending\n");
} /* ray_detach */
/*=============================================================================
@@ -438,9 +407,8 @@ static void ray_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
#define MAX_TUPLE_SIZE 128
-static void ray_config(dev_link_t *link)
+static int ray_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
tuple_t tuple;
cisparse_t parse;
int last_fn = 0, last_ret = 0;
@@ -455,48 +423,45 @@ static void ray_config(dev_link_t *link)
/* This reads the card's CONFIG tuple to find its configuration regs */
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = buf;
tuple.TupleDataMax = MAX_TUPLE_SIZE;
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Determine card type and firmware version */
buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = buf;
tuple.TupleDataMax = MAX_TUPLE_SIZE;
tuple.TupleOffset = 2;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
for (i=0; i<tuple.TupleDataLen - 4; i++)
if (buf[i] == 0) buf[i] = ' ';
printk(KERN_INFO "ray_cs Detected: %s\n",buf);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Now allocate an interrupt line. Note that this does not
actually assign a handler to the interrupt.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
dev->irq = link->irq.AssignedIRQ;
/* This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*** Set up 32k window for shared memory (transmit and control) ************/
req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
req.Base = 0;
req.Size = 0x8000;
req.AccessSpeed = ray_mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = 0x0000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
local->sram = ioremap(req.Base,req.Size);
@@ -506,7 +471,7 @@ static void ray_config(dev_link_t *link)
req.Base = 0;
req.Size = 0x4000;
req.AccessSpeed = ray_mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle));
mem.CardOffset = 0x8000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
local->rmem = ioremap(req.Base,req.Size);
@@ -516,7 +481,7 @@ static void ray_config(dev_link_t *link)
req.Base = 0;
req.Size = 0x1000;
req.AccessSpeed = ray_mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle));
mem.CardOffset = 0x0000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
local->amem = ioremap(req.Base,req.Size);
@@ -526,32 +491,32 @@ static void ray_config(dev_link_t *link)
DEBUG(3,"ray_config amem=%p\n",local->amem);
if (ray_init(dev) < 0) {
ray_release(link);
- return;
+ return -ENODEV;
}
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = register_netdev(dev);
if (i != 0) {
printk("ray_config register_netdev() failed\n");
ray_release(link);
- return;
+ return i;
}
strcpy(local->node.dev_name, dev->name);
- link->dev = &local->node;
+ link->dev_node = &local->node;
- link->state &= ~DEV_CONFIG_PENDING;
printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
dev->name, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
ray_release(link);
+ return -ENODEV;
} /* ray_config */
static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
@@ -578,9 +543,9 @@ static int ray_init(struct net_device *dev)
UCHAR *p;
struct ccs __iomem *pccs;
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(1, "ray_init(0x%p)\n", dev);
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(0,"ray_init - device not present\n");
return -1;
}
@@ -640,10 +605,10 @@ static int dl_startup_params(struct net_device *dev)
int ccsindex;
ray_dev_t *local = (ray_dev_t *)dev->priv;
struct ccs __iomem *pccs;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(1,"dl_startup_params entered\n");
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs dl_startup_params - device not present\n");
return -1;
}
@@ -747,9 +712,9 @@ static void verify_dl_startup(u_long data)
ray_dev_t *local = (ray_dev_t *)data;
struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
UCHAR status;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs verify_dl_startup - device not present\n");
return;
}
@@ -787,8 +752,8 @@ static void start_net(u_long data)
ray_dev_t *local = (ray_dev_t *)data;
struct ccs __iomem *pccs;
int ccsindex;
- dev_link_t *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ struct pcmcia_device *link = local->finder;
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs start_net - device not present\n");
return;
}
@@ -814,9 +779,9 @@ static void join_net(u_long data)
struct ccs __iomem *pccs;
int ccsindex;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs join_net - device not present\n");
return;
}
@@ -840,7 +805,7 @@ static void join_net(u_long data)
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
=============================================================================*/
-static void ray_release(dev_link_t *link)
+static void ray_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
ray_dev_t *local = dev->priv;
@@ -849,56 +814,38 @@ static void ray_release(dev_link_t *link)
DEBUG(1, "ray_release(0x%p)\n", link);
del_timer(&local->timer);
- link->state &= ~DEV_CONFIG;
iounmap(local->sram);
iounmap(local->rmem);
iounmap(local->amem);
/* Do bother checking to see if these succeed or not */
- i = pcmcia_release_window(link->win);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i);
i = pcmcia_release_window(local->amem_handle);
if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
i = pcmcia_release_window(local->rmem_handle);
if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
- i = pcmcia_release_configuration(link->handle);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i);
- i = pcmcia_release_irq(link->handle, &link->irq);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
+ pcmcia_disable_device(link);
DEBUG(2,"ray_release ending\n");
}
-static int ray_suspend(struct pcmcia_device *p_dev)
+static int ray_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
-
- pcmcia_release_configuration(link->handle);
- }
-
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int ray_resume(struct pcmcia_device *p_dev)
+static int ray_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- ray_reset(dev);
- netif_device_attach(dev);
- }
- }
+ if (link->open) {
+ ray_reset(dev);
+ netif_device_attach(dev);
+ }
return 0;
}
@@ -910,10 +857,10 @@ int ray_dev_init(struct net_device *dev)
int i;
#endif /* RAY_IMMEDIATE_INIT */
ray_dev_t *local = dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(1,"ray_dev_init(dev=%p)\n",dev);
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_dev_init - device not present\n");
return -1;
}
@@ -944,10 +891,10 @@ int ray_dev_init(struct net_device *dev)
static int ray_dev_config(struct net_device *dev, struct ifmap *map)
{
ray_dev_t *local = dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
/* Dummy routine to satisfy device structure */
DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map);
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_dev_config - device not present\n");
return -1;
}
@@ -958,10 +905,10 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map)
static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
ray_dev_t *local = dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
short length = skb->len;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_dev_start_xmit - device not present\n");
return -1;
}
@@ -1570,7 +1517,7 @@ static int ray_commit(struct net_device *dev,
static iw_stats * ray_get_wireless_stats(struct net_device * dev)
{
ray_dev_t * local = (ray_dev_t *) dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
struct status __iomem *p = local->sram + STATUS_BASE;
if(local == (ray_dev_t *) NULL)
@@ -1588,7 +1535,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
}
#endif /* WIRELESS_SPY */
- if((link->state & DEV_PRESENT)) {
+ if(pcmcia_dev_present(link)) {
local->wstats.qual.noise = readb(&p->rxnoise);
local->wstats.qual.updated |= 4;
}
@@ -1657,18 +1604,14 @@ static const struct iw_handler_def ray_handler_def =
/*===========================================================================*/
static int ray_open(struct net_device *dev)
{
- dev_link_t *link;
ray_dev_t *local = (ray_dev_t *)dev->priv;
+ struct pcmcia_device *link;
+ link = local->finder;
DEBUG(1, "ray_open('%s')\n", dev->name);
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
- if (!DEV_OK(link)) {
- return -ENODEV;
- }
-
- if (link->open == 0) local->num_multi = 0;
+ if (link->open == 0)
+ local->num_multi = 0;
link->open++;
/* If the card is not started, time to start it ! - Jean II */
@@ -1695,15 +1638,12 @@ static int ray_open(struct net_device *dev)
/*===========================================================================*/
static int ray_dev_close(struct net_device *dev)
{
- dev_link_t *link;
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ struct pcmcia_device *link;
+ link = local->finder;
DEBUG(1, "ray_dev_close('%s')\n", dev->name);
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
- if (link == NULL)
- return -ENODEV;
-
link->open--;
netif_stop_queue(dev);
@@ -1725,9 +1665,9 @@ static void ray_reset(struct net_device *dev) {
static int interrupt_ecf(ray_dev_t *local, int ccs)
{
int i = 50;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs interrupt_ecf - device not present\n");
return -1;
}
@@ -1752,9 +1692,9 @@ static int get_free_tx_ccs(ray_dev_t *local)
{
int i;
struct ccs __iomem *pccs = ccs_base(local);
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n");
return ECARDGONE;
}
@@ -1783,9 +1723,9 @@ static int get_free_ccs(ray_dev_t *local)
{
int i;
struct ccs __iomem *pccs = ccs_base(local);
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs get_free_ccs - device not present\n");
return ECARDGONE;
}
@@ -1858,9 +1798,9 @@ static int parse_addr(char *in_str, UCHAR *out)
static struct net_device_stats *ray_get_stats(struct net_device *dev)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
struct status __iomem *p = local->sram + STATUS_BASE;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs net_device_stats - device not present\n");
return &local->stats;
}
@@ -1888,12 +1828,12 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)
static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
int ccsindex;
int i;
struct ccs __iomem *pccs;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_update_parm - device not present\n");
return;
}
@@ -1925,10 +1865,10 @@ static void ray_update_multi_list(struct net_device *dev, int all)
struct ccs __iomem *pccs;
int i = 0;
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
void __iomem *p = local->sram + HOST_TO_ECF_BASE;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_update_multi_list - device not present\n");
return;
}
@@ -2005,7 +1945,7 @@ static void set_multicast_list(struct net_device *dev)
static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = (struct net_device *)dev_id;
- dev_link_t *link;
+ struct pcmcia_device *link;
ray_dev_t *local;
struct ccs __iomem *pccs;
struct rcs __iomem *prcs;
@@ -2020,8 +1960,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
local = (ray_dev_t *)dev->priv;
- link = (dev_link_t *)local->finder;
- if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
+ link = (struct pcmcia_device *)local->finder;
+ if (!pcmcia_dev_present(link)) {
DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
return IRQ_NONE;
}
@@ -2540,9 +2480,9 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
/*===========================================================================*/
static void authenticate(ray_dev_t *local)
{
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(0,"ray_cs Starting authentication.\n");
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs authenticate - device not present\n");
return;
}
@@ -2606,10 +2546,10 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
static void associate(ray_dev_t *local)
{
struct ccs __iomem *pccs;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
struct net_device *dev = link->priv;
int ccsindex;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs associate - device not present\n");
return;
}
@@ -2689,14 +2629,14 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
* eg ifconfig
*/
int i;
- dev_link_t *link;
+ struct pcmcia_device *link;
struct net_device *dev;
ray_dev_t *local;
UCHAR *p;
struct freq_hop_element *pfh;
UCHAR c[33];
- link = dev_list;
+ link = this_device;
if (!link)
return 0;
dev = (struct net_device *)link->priv;
@@ -2898,7 +2838,7 @@ static struct pcmcia_driver ray_driver = {
.drv = {
.name = "ray_cs",
},
- .probe = ray_attach,
+ .probe = ray_probe,
.remove = ray_detach,
.id_table = ray_ids,
.suspend = ray_suspend,
@@ -2940,7 +2880,6 @@ static void __exit exit_ray_cs(void)
#endif
pcmcia_unregister_driver(&ray_driver);
- BUG_ON(dev_list != NULL);
} /* exit_ray_cs */
module_init(init_ray_cs);
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 42660fe64bfd..bd73ebf03340 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -31,7 +31,7 @@ typedef struct ray_dev_t {
void __iomem *sram; /* pointer to beginning of shared RAM */
void __iomem *amem; /* pointer to attribute mem window */
void __iomem *rmem; /* pointer to receive buffer window */
- dev_link_t *finder; /* pointer back to dev_link_t for card */
+ struct pcmcia_device *finder; /* pointer back to struct pcmcia_device for card */
struct timer_list timer;
long tx_ccs_lock;
long ccs_lock;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 5fa6fbe35bb9..f7b77ce54d7b 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
/* PCMCIA specific device information (goes in the card field of
* struct orinoco_private */
struct orinoco_pccard {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
};
@@ -71,8 +71,8 @@ struct orinoco_pccard {
/* Function prototypes */
/********************************************************************/
-static void spectrum_cs_config(dev_link_t *link);
-static void spectrum_cs_release(dev_link_t *link);
+static int spectrum_cs_config(struct pcmcia_device *link);
+static void spectrum_cs_release(struct pcmcia_device *link);
/********************************************************************/
/* Firmware downloader */
@@ -238,14 +238,14 @@ spectrum_aux_open(hermes_t *hw)
* If IDLE is 1, stop the firmware, so that it can be safely rewritten.
*/
static int
-spectrum_reset(dev_link_t *link, int idle)
+spectrum_reset(struct pcmcia_device *link, int idle)
{
int last_ret, last_fn;
conf_reg_t reg;
u_int save_cor;
/* Doing it if hardware is gone is guaranteed crash */
- if (!(link->state & DEV_CONFIG))
+ if (pcmcia_dev_present(link))
return -ENODEV;
/* Save original COR value */
@@ -253,7 +253,7 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
save_cor = reg.Value;
/* Soft-Reset card */
@@ -261,14 +261,14 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Offset = CISREG_COR;
reg.Value = (save_cor | COR_SOFT_RESET);
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
udelay(1000);
/* Read CCSR */
reg.Action = CS_READ;
reg.Offset = CISREG_CCSR;
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
/*
* Start or stop the firmware. Memory width bit should be
@@ -278,7 +278,7 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Offset = CISREG_CCSR;
reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
udelay(1000);
/* Restore original COR configuration index */
@@ -286,12 +286,12 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Offset = CISREG_COR;
reg.Value = (save_cor & ~COR_SOFT_RESET);
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
udelay(1000);
return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
return -ENODEV;
}
@@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
* care of the PDA - read it and then write it on top of the firmware.
*/
static int
-spectrum_dl_image(hermes_t *hw, dev_link_t *link,
+spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
const unsigned char *image)
{
int ret;
@@ -505,14 +505,13 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link,
* reset on the card, to make sure it's in a sane state.
*/
static int
-spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
{
int ret;
- client_handle_t handle = link->handle;
const struct firmware *fw_entry;
if (request_firmware(&fw_entry, primary_fw_name,
- &handle_to_dev(handle)) == 0) {
+ &handle_to_dev(link)) == 0) {
primsym = fw_entry->data;
} else {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -521,7 +520,7 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
}
if (request_firmware(&fw_entry, secondary_fw_name,
- &handle_to_dev(handle)) == 0) {
+ &handle_to_dev(link)) == 0) {
secsym = fw_entry->data;
} else {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -554,12 +553,12 @@ static int
spectrum_cs_hard_reset(struct orinoco_private *priv)
{
struct orinoco_pccard *card = priv->card;
- dev_link_t *link = &card->link;
+ struct pcmcia_device *link = card->p_dev;
int err;
if (!hermes_present(&priv->hw)) {
/* The firmware needs to be reloaded */
- if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+ if (spectrum_dl_firmware(&priv->hw, link) != 0) {
printk(KERN_ERR PFX "Firmware download failed\n");
err = -ENODEV;
}
@@ -584,12 +583,11 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
* configure the card at this point -- we wait until we receive a card
* insertion event. */
static int
-spectrum_cs_attach(struct pcmcia_device *p_dev)
+spectrum_cs_probe(struct pcmcia_device *link)
{
struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev_link_t *link;
dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
if (! dev)
@@ -598,7 +596,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
card = priv->card;
/* Link both structures together */
- link = &card->link;
+ card->p_dev = link;
link->priv = dev;
/* Interrupt setup */
@@ -615,13 +613,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- spectrum_cs_config(link);
-
- return 0;
+ return spectrum_cs_config(link);
} /* spectrum_cs_attach */
/*
@@ -630,16 +622,14 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void spectrum_cs_detach(struct pcmcia_device *p_dev)
+static void spectrum_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- if (link->state & DEV_CONFIG)
- spectrum_cs_release(link);
+ spectrum_cs_release(link);
- DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
- if (link->dev) {
+ DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+ if (link->dev_node) {
DEBUG(0, PFX "About to unregister net device %p\n",
dev);
unregister_netdev(dev);
@@ -653,11 +643,10 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev)
* device available to the system.
*/
-static void
-spectrum_cs_config(dev_link_t *link)
+static int
+spectrum_cs_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- client_handle_t handle = link->handle;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
@@ -669,7 +658,7 @@ spectrum_cs_config(dev_link_t *link)
cisparse_t parse;
void __iomem *mem;
- CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
/*
* This reads the card's CONFIG tuple to find its
@@ -680,19 +669,15 @@ spectrum_cs_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
/*
* In this loop, we scan the CIS for configuration table
@@ -709,13 +694,13 @@ spectrum_cs_config(dev_link_t *link)
* implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_cftable_entry_t dflt = { .index = 0 };
- if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
- || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+ if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+ || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -747,10 +732,10 @@ spectrum_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
@@ -780,7 +765,7 @@ spectrum_cs_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
@@ -790,9 +775,8 @@ spectrum_cs_config(dev_link_t *link)
break;
next_entry:
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ pcmcia_disable_device(link);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
if (last_ret == CS_NO_MORE_ITEMS) {
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
@@ -806,7 +790,7 @@ spectrum_cs_config(dev_link_t *link)
* a handler to the interrupt, unless the 'Handler' member of
* the irq structure is initialized.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/* We initialize the hermes structure before completing PCMCIA
* configuration just in case the interrupt handler gets
@@ -823,7 +807,7 @@ spectrum_cs_config(dev_link_t *link)
* card and host interface into "Memory and IO" mode.
*/
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
/* Ok, we have the configuration, prepare to register the netdev */
dev->base_addr = link->io.BasePort1;
@@ -836,7 +820,7 @@ spectrum_cs_config(dev_link_t *link)
goto failed;
}
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -844,20 +828,18 @@ spectrum_cs_config(dev_link_t *link)
}
/* At this point, the dev_node_t structure(s) needs to be
- * initialized and arranged in a linked list at link->dev. */
+ * initialized and arranged in a linked list at link->dev_node. */
strcpy(card->node.dev_name, dev->name);
- link->dev = &card->node; /* link->dev being non-NULL is also
+ link->dev_node = &card->node; /* link->dev_node being non-NULL is also
used to indicate that the
net_device has been registered */
- link->state &= ~DEV_CONFIG_PENDING;
/* Finally, report what we've done */
- printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
- dev->name, link->conf.ConfigIndex,
- link->conf.Vcc / 10, link->conf.Vcc % 10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
- link->conf.Vpp1 % 10);
+ printk(KERN_DEBUG "%s: index 0x%02x: ",
+ dev->name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp / 10,
+ link->conf.Vpp % 10);
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -867,13 +849,14 @@ spectrum_cs_config(dev_link_t *link)
link->io.BasePort2 + link->io.NumPorts2 - 1);
printk("\n");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
spectrum_cs_release(link);
+ return -ENODEV;
} /* spectrum_cs_config */
/*
@@ -882,7 +865,7 @@ spectrum_cs_config(dev_link_t *link)
* still open, this will be postponed until it is closed.
*/
static void
-spectrum_cs_release(dev_link_t *link)
+spectrum_cs_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
@@ -894,64 +877,46 @@ spectrum_cs_release(dev_link_t *link)
priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
if (priv->hw.iobase)
ioport_unmap(priv->hw.iobase);
} /* spectrum_cs_release */
static int
-spectrum_cs_suspend(struct pcmcia_device *p_dev)
+spectrum_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
unsigned long flags;
int err = 0;
- link->state |= DEV_SUSPEND;
/* Mark the device as stopped, to block IO until later */
- if (link->state & DEV_CONFIG) {
- spin_lock_irqsave(&priv->lock, flags);
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: Error %d downing interface\n",
- dev->name, err);
+ spin_lock_irqsave(&priv->lock, flags);
- netif_device_detach(dev);
- priv->hw_unavailable++;
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
- spin_unlock_irqrestore(&priv->lock, flags);
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
- pcmcia_release_configuration(link->handle);
- }
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
static int
-spectrum_cs_resume(struct pcmcia_device *p_dev)
+spectrum_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- /* FIXME: should we double check that this is
- * the same card as we had before */
- pcmcia_request_configuration(link->handle, &link->conf);
- netif_device_attach(dev);
- priv->hw_unavailable--;
- schedule_work(&priv->reset_work);
- }
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+ schedule_work(&priv->reset_work);
+
return 0;
}
@@ -979,7 +944,7 @@ static struct pcmcia_driver orinoco_driver = {
.drv = {
.name = DRIVER_NAME,
},
- .probe = spectrum_cs_attach,
+ .probe = spectrum_cs_probe,
.remove = spectrum_cs_detach,
.suspend = spectrum_cs_suspend,
.resume = spectrum_cs_resume,
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 98122f3a4bc2..f7724eb2fa7e 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1005,7 +1005,7 @@ static inline void
wv_82593_reconfig(struct net_device * dev)
{
net_local * lp = netdev_priv(dev);
- dev_link_t * link = lp->link;
+ struct pcmcia_device * link = lp->link;
unsigned long flags;
/* Arm the flag, will be cleard in wv_82593_config() */
@@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device * dev)
{
int i;
conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 };
- dev_link_t * link = ((net_local *)netdev_priv(dev))->link;
+ struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name);
#endif
- i = pcmcia_access_configuration_register(link->handle, &reg);
+ i = pcmcia_access_configuration_register(link, &reg);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, AccessConfigurationRegister, i);
+ cs_error(link, AccessConfigurationRegister, i);
return FALSE;
}
@@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device * dev)
reg.Action = CS_WRITE;
reg.Value = reg.Value | COR_SW_RESET;
- i = pcmcia_access_configuration_register(link->handle, &reg);
+ i = pcmcia_access_configuration_register(link, &reg);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, AccessConfigurationRegister, i);
+ cs_error(link, AccessConfigurationRegister, i);
return FALSE;
}
reg.Action = CS_WRITE;
reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
- i = pcmcia_access_configuration_register(link->handle, &reg);
+ i = pcmcia_access_configuration_register(link, &reg);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, AccessConfigurationRegister, i);
+ cs_error(link, AccessConfigurationRegister, i);
return FALSE;
}
@@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device * dev)
* (called by wavelan_event())
*/
static inline int
-wv_pcmcia_config(dev_link_t * link)
+wv_pcmcia_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
tuple_t tuple;
cisparse_t parse;
struct net_device * dev = (struct net_device *) link->priv;
@@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t * link)
{
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- i = pcmcia_get_first_tuple(handle, &tuple);
+ i = pcmcia_get_first_tuple(link, &tuple);
if(i != CS_SUCCESS)
break;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- i = pcmcia_get_tuple_data(handle, &tuple);
+ i = pcmcia_get_tuple_data(link, &tuple);
if(i != CS_SUCCESS)
break;
- i = pcmcia_parse_tuple(handle, &tuple, &parse);
+ i = pcmcia_parse_tuple(link, &tuple, &parse);
if(i != CS_SUCCESS)
break;
link->conf.ConfigBase = parse.config.base;
@@ -3983,19 +3982,16 @@ wv_pcmcia_config(dev_link_t * link)
while(0);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, ParseTuple, i);
- link->state &= ~DEV_CONFIG_PENDING;
+ cs_error(link, ParseTuple, i);
return FALSE;
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
+
do
{
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
break;
}
@@ -4003,10 +3999,10 @@ wv_pcmcia_config(dev_link_t * link)
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
break;
}
@@ -4015,15 +4011,15 @@ wv_pcmcia_config(dev_link_t * link)
* the I/O windows and the interrupt mapping.
*/
link->conf.ConfigIndex = 1;
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
break;
}
/*
- * Allocate a small memory window. Note that the dev_link_t
+ * Allocate a small memory window. Note that the struct pcmcia_device
* structure provides space for one window handle -- if your
* device needs several windows, you'll need to keep track of
* the handles in your private data structure, link->priv.
@@ -4031,10 +4027,10 @@ wv_pcmcia_config(dev_link_t * link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
req.AccessSpeed = mem_speed;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
break;
}
@@ -4046,7 +4042,7 @@ wv_pcmcia_config(dev_link_t * link)
i = pcmcia_map_mem_page(link->win, &mem);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, MapMemPage, i);
+ cs_error(link, MapMemPage, i);
break;
}
@@ -4060,7 +4056,7 @@ wv_pcmcia_config(dev_link_t * link)
lp->mem, dev->irq, (u_int) dev->base_addr);
#endif
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = register_netdev(dev);
if(i != 0)
{
@@ -4072,7 +4068,6 @@ wv_pcmcia_config(dev_link_t * link)
}
while(0); /* Humm... Disguised goto !!! */
- link->state &= ~DEV_CONFIG_PENDING;
/* If any step failed, release any partially configured state */
if(i != 0)
{
@@ -4081,7 +4076,7 @@ wv_pcmcia_config(dev_link_t * link)
}
strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name);
- link->dev = &((net_local *) netdev_priv(dev))->node;
+ link->dev_node = &((net_local *) netdev_priv(dev))->node;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "<-wv_pcmcia_config()\n");
@@ -4096,26 +4091,20 @@ wv_pcmcia_config(dev_link_t * link)
* still open, this will be postponed until it is closed.
*/
static void
-wv_pcmcia_release(dev_link_t *link)
+wv_pcmcia_release(struct pcmcia_device *link)
{
- struct net_device * dev = (struct net_device *) link->priv;
- net_local * lp = netdev_priv(dev);
+ struct net_device * dev = (struct net_device *) link->priv;
+ net_local * lp = netdev_priv(dev);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
+ printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
#endif
- /* Don't bother checking to see if these succeed or not */
- iounmap(lp->mem);
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ iounmap(lp->mem);
+ pcmcia_disable_device(link);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
+ printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
#endif
}
@@ -4479,7 +4468,7 @@ static int
wavelan_open(struct net_device * dev)
{
net_local * lp = netdev_priv(dev);
- dev_link_t * link = lp->link;
+ struct pcmcia_device * link = lp->link;
kio_addr_t base = dev->base_addr;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4533,7 +4522,7 @@ wavelan_open(struct net_device * dev)
static int
wavelan_close(struct net_device * dev)
{
- dev_link_t * link = ((net_local *)netdev_priv(dev))->link;
+ struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link;
kio_addr_t base = dev->base_addr;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4587,45 +4576,36 @@ wavelan_close(struct net_device * dev)
* card insertion event.
*/
static int
-wavelan_attach(struct pcmcia_device *p_dev)
+wavelan_probe(struct pcmcia_device *p_dev)
{
- dev_link_t * link; /* Info for cardmgr */
struct net_device * dev; /* Interface generic data */
net_local * lp; /* Interface specific data */
+ int ret;
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_attach()\n");
#endif
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) return -ENOMEM;
-
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 8;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 3;
+ p_dev->io.NumPorts1 = 8;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 3;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = wavelan_interrupt;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = wavelan_interrupt;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
- /* Chain drivers */
- link->next = NULL;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate the generic data structure */
dev = alloc_etherdev(sizeof(net_local));
- if (!dev) {
- kfree(link);
+ if (!dev)
return -ENOMEM;
- }
- link->priv = link->irq.Instance = dev;
+
+ p_dev->priv = p_dev->irq.Instance = dev;
lp = netdev_priv(dev);
@@ -4642,7 +4622,6 @@ wavelan_attach(struct pcmcia_device *p_dev)
spin_lock_init(&lp->spinlock);
/* back links */
- lp->link = link;
lp->dev = dev;
/* wavelan NET3 callbacks */
@@ -4668,15 +4647,18 @@ wavelan_attach(struct pcmcia_device *p_dev)
/* Other specific data */
dev->mtu = WAVELAN_MTU;
- link->handle = p_dev;
- p_dev->instance = link;
+ ret = wv_pcmcia_config(p_dev);
+ if (ret)
+ return ret;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- if(wv_pcmcia_config(link) &&
- wv_hw_config(dev))
- wv_init_info(dev);
- else
+ ret = wv_hw_config(dev);
+ if (ret) {
dev->irq = 0;
+ pcmcia_disable_device(p_dev);
+ return ret;
+ }
+
+ wv_init_info(dev);
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<- wavelan_attach()\n");
@@ -4693,25 +4675,14 @@ wavelan_attach(struct pcmcia_device *p_dev)
* is released.
*/
static void
-wavelan_detach(struct pcmcia_device *p_dev)
+wavelan_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
#endif
- /*
- * If the device is currently configured and active, we won't
- * actually delete it yet. Instead, it is marked so that when the
- * release() function is called, that will trigger a proper
- * detach().
- */
- if(link->state & DEV_CONFIG)
- {
- /* Some others haven't done their job : give them another chance */
- wv_pcmcia_release(link);
- }
+ /* Some others haven't done their job : give them another chance */
+ wv_pcmcia_release(link);
/* Free pieces */
if(link->priv)
@@ -4720,23 +4691,21 @@ wavelan_detach(struct pcmcia_device *p_dev)
/* Remove ourselves from the kernel list of ethernet devices */
/* Warning : can't be called from interrupt, timer or wavelan_close() */
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- link->dev = NULL;
+ link->dev_node = NULL;
((net_local *)netdev_priv(dev))->link = NULL;
((net_local *)netdev_priv(dev))->dev = NULL;
free_netdev(dev);
}
- kfree(link);
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<- wavelan_detach()\n");
#endif
}
-static int wavelan_suspend(struct pcmcia_device *p_dev)
+static int wavelan_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device * dev = (struct net_device *) link->priv;
/* NB: wavelan_close will be called, but too late, so we are
@@ -4748,36 +4717,22 @@ static int wavelan_suspend(struct pcmcia_device *p_dev)
/* Stop receiving new messages and wait end of transmission */
wv_ru_stop(dev);
+ if (link->open)
+ netif_device_detach(dev);
+
/* Power down the module */
hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
- /* The card is now suspended */
- link->state |= DEV_SUSPEND;
-
- if(link->state & DEV_CONFIG)
- {
- if(link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
-
return 0;
}
-static int wavelan_resume(struct pcmcia_device *p_dev)
+static int wavelan_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device * dev = (struct net_device *) link->priv;
- link->state &= ~DEV_SUSPEND;
- if(link->state & DEV_CONFIG)
- {
- pcmcia_request_configuration(link->handle, &link->conf);
- if(link->open) /* If RESET -> True, If RESUME -> False ? */
- {
- wv_hw_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ wv_hw_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -4798,7 +4753,7 @@ static struct pcmcia_driver wavelan_driver = {
.drv = {
.name = "wavelan_cs",
},
- .probe = wavelan_attach,
+ .probe = wavelan_probe,
.remove = wavelan_detach,
.id_table = wavelan_ids,
.suspend = wavelan_suspend,
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 451f6271dcbc..c65fe7a391ec 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -602,7 +602,7 @@ struct net_local
dev_node_t node; /* ???? What is this stuff ???? */
struct net_device * dev; /* Reverse link... */
spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
- dev_link_t * link; /* pcmcia structure */
+ struct pcmcia_device * link; /* pcmcia structure */
en_stats stats; /* Ethernet interface statistics */
int nresets; /* Number of hw resets */
u_char configured; /* If it is configured */
@@ -733,9 +733,9 @@ static int
static inline void
wv_hw_reset(struct net_device *); /* Same, + start receiver unit */
static inline int
- wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */
+ wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */
static void
- wv_pcmcia_release(dev_link_t *);/* Remove a device */
+ wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
/* ---------------------- INTERRUPT HANDLING ---------------------- */
static irqreturn_t
wavelan_interrupt(int, /* Interrupt handler */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 4303c50c2ab6..65ceb088f700 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -611,5 +611,6 @@ struct wl3501_card {
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
struct dev_node_t node;
+ struct pcmcia_device *p_dev;
};
#endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 48e10b0c7e74..e52a650f6737 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -103,8 +103,8 @@ module_param(pc_debug, int, 0);
* release a socket, in response to card insertion and ejection events. They
* are invoked from the wl24 event handler.
*/
-static void wl3501_config(dev_link_t *link);
-static void wl3501_release(dev_link_t *link);
+static int wl3501_config(struct pcmcia_device *link);
+static void wl3501_release(struct pcmcia_device *link);
/*
* The dev_info variable is the "key" that is used to match up this
@@ -226,17 +226,6 @@ static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to,
iw_set_mgmt_info_element(from->id, to, from->data, from->len);
}
-/*
- * A linked list of "instances" of the wl24 device. Each actual PCMCIA card
- * corresponds to one device instance, and is described by one dev_link_t
- * structure (defined in ds.h).
- *
- * You may not want to use a linked list for this -- for example, the memory
- * card driver uses an array of dev_link_t pointers, where minor device numbers
- * are used to derive the corresponding array index.
- */
-static dev_link_t *wl3501_dev_list;
-
static inline void wl3501_switch_page(struct wl3501_card *this, u8 page)
{
wl3501_outb(page, this->base_addr + WL3501_NIC_BSS);
@@ -1281,15 +1270,10 @@ static int wl3501_close(struct net_device *dev)
struct wl3501_card *this = dev->priv;
int rc = -ENODEV;
unsigned long flags;
- dev_link_t *link;
+ struct pcmcia_device *link;
+ link = this->p_dev;
spin_lock_irqsave(&this->lock, flags);
- /* Check if the device is in wl3501_dev_list */
- for (link = wl3501_dev_list; link; link = link->next)
- if (link->priv == dev)
- break;
- if (!link)
- goto out;
link->open--;
/* Stop wl3501_hard_start_xmit() from now on */
@@ -1301,7 +1285,6 @@ static int wl3501_close(struct net_device *dev)
rc = 0;
printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
-out:
spin_unlock_irqrestore(&this->lock, flags);
return rc;
}
@@ -1400,14 +1383,11 @@ static int wl3501_open(struct net_device *dev)
int rc = -ENODEV;
struct wl3501_card *this = dev->priv;
unsigned long flags;
- dev_link_t *link;
+ struct pcmcia_device *link;
+ link = this->p_dev;
spin_lock_irqsave(&this->lock, flags);
- /* Check if the device is in wl3501_dev_list */
- for (link = wl3501_dev_list; link; link = link->next)
- if (link->priv == dev)
- break;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
goto out;
netif_device_attach(dev);
link->open++;
@@ -1497,38 +1477,23 @@ static struct ethtool_ops ops = {
* Services. If it has been released, all local data structures are freed.
* Otherwise, the structures will be freed when the device is released.
*/
-static void wl3501_detach(struct pcmcia_device *p_dev)
+static void wl3501_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- dev_link_t **linkp;
struct net_device *dev = link->priv;
- /* Locate device structure */
- for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (!*linkp)
- goto out;
-
/* If the device is currently configured and active, we won't actually
* delete it yet. Instead, it is marked so that when the release()
* function is called, that will trigger a proper detach(). */
- if (link->state & DEV_CONFIG) {
- while (link->open > 0)
- wl3501_close(dev);
-
- netif_device_detach(dev);
- wl3501_release(link);
- }
+ while (link->open > 0)
+ wl3501_close(dev);
- /* Unlink device structure, free pieces */
- *linkp = link->next;
+ netif_device_detach(dev);
+ wl3501_release(link);
if (link->priv)
free_netdev(link->priv);
- kfree(link);
-out:
+
return;
}
@@ -1953,33 +1918,26 @@ static const struct iw_handler_def wl3501_handler_def = {
* The dev_link structure is initialized, but we don't actually configure the
* card at this point -- we wait until we receive a card insertion event.
*/
-static int wl3501_attach(struct pcmcia_device *p_dev)
+static int wl3501_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
struct net_device *dev;
struct wl3501_card *this;
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(*link), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
-
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 16;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 5;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = wl3501_interrupt;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = wl3501_interrupt;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
dev = alloc_etherdev(sizeof(struct wl3501_card));
if (!dev)
@@ -1992,22 +1950,15 @@ static int wl3501_attach(struct pcmcia_device *p_dev)
dev->get_stats = wl3501_get_stats;
this = dev->priv;
this->wireless_data.spy_data = &this->spy_data;
+ this->p_dev = p_dev;
dev->wireless_data = &this->wireless_data;
dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def;
SET_ETHTOOL_OPS(dev, &ops);
netif_stop_queue(dev);
- link->priv = link->irq.Instance = dev;
-
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- wl3501_config(link);
+ p_dev->priv = p_dev->irq.Instance = dev;
- return 0;
+ return wl3501_config(p_dev);
out_link:
- kfree(link);
- link = NULL;
return -ENOMEM;
}
@@ -2022,11 +1973,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
* received, to configure the PCMCIA socket, and to make the ethernet device
* available to the system.
*/
-static void wl3501_config(dev_link_t *link)
+static int wl3501_config(struct pcmcia_device *link)
{
tuple_t tuple;
cisparse_t parse;
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
int i = 0, j, last_fn, last_ret;
unsigned char bf[64];
@@ -2035,18 +1985,15 @@ static void wl3501_config(dev_link_t *link)
/* This reads the card's CONFIG tuple to find its config registers. */
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = bf;
tuple.TupleDataMax = sizeof(bf);
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Try allocating IO ports. This tries a few fixed addresses. If you
* want, you can also read the card's config table to pick addresses --
* see the serial driver for an example. */
@@ -2056,28 +2003,28 @@ static void wl3501_config(dev_link_t *link)
* 0x200-0x2ff, and so on, because this seems safer */
link->io.BasePort1 = j;
link->io.BasePort2 = link->io.BasePort1 + 0x10;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
/* Now allocate an interrupt line. Note that this does not actually
* assign a handler to the interrupt. */
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/* This actually configures the PCMCIA socket -- setting up the I/O
* windows and the interrupt mapping. */
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev)) {
printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
goto failed;
@@ -2088,10 +2035,9 @@ static void wl3501_config(dev_link_t *link)
this = dev->priv;
/*
* At this point, the dev_node_t structure(s) should be initialized and
- * arranged in a linked list at link->dev.
+ * arranged in a linked list at link->dev_node.
*/
- link->dev = &this->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &this->node;
this->base_addr = dev->base_addr;
@@ -2127,13 +2073,13 @@ static void wl3501_config(dev_link_t *link)
spin_lock_init(&this->lock);
init_waitqueue_head(&this->wait);
netif_start_queue(dev);
- goto out;
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
wl3501_release(link);
-out:
- return;
+ return -ENODEV;
}
/**
@@ -2144,52 +2090,36 @@ out:
* and release the PCMCIA configuration. If the device is still open, this
* will be postponed until it is closed.
*/
-static void wl3501_release(dev_link_t *link)
+static void wl3501_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
/* Unlink the device chain */
- if (link->dev) {
+ if (link->dev_node)
unregister_netdev(dev);
- link->dev = NULL;
- }
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int wl3501_suspend(struct pcmcia_device *p_dev)
+static int wl3501_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
-
wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int wl3501_resume(struct pcmcia_device *p_dev)
+static int wl3501_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- wl3501_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ wl3501_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -2207,7 +2137,7 @@ static struct pcmcia_driver wl3501_driver = {
.drv = {
.name = "wl3501_cs",
},
- .probe = wl3501_attach,
+ .probe = wl3501_probe,
.remove = wl3501_detach,
.id_table = wl3501_ids,
.suspend = wl3501_suspend,
@@ -2221,9 +2151,7 @@ static int __init wl3501_init_module(void)
static void __exit wl3501_exit_module(void)
{
- dprintk(0, ": unloading");
pcmcia_unregister_driver(&wl3501_driver);
- BUG_ON(wl3501_dev_list != NULL);
}
module_init(wl3501_init_module);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 75d56bfef0ee..fd0f43b7db5b 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1441,8 +1441,7 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct yellowfin_private *np;
- if (!dev)
- BUG();
+ BUG_ON(!dev);
np = netdev_priv(dev);
pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status,
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 4e53be9c03ab..bbeabe3fc4c6 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -535,7 +535,7 @@ pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
{
char *out = buf;
struct pdcspath_entry *pathentry;
-
+
if (!entry || !buf)
return -EINVAL;
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 42b32ff2fca6..278f325021ee 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -178,6 +178,11 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define ROPE6_CTL 0x230
#define ROPE7_CTL 0x238
+#define IOC_ROPE0_CFG 0x500 /* pluto only */
+#define IOC_ROPE_AO 0x10 /* Allow "Relaxed Ordering" */
+
+
+
#define HF_ENABLE 0x40
@@ -1759,19 +1764,33 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
sba_dev->num_ioc = num_ioc;
for (i = 0; i < num_ioc; i++) {
- /*
- ** Make sure the box crashes if we get any errors on a rope.
- */
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
-
- /* flush out the writes */
+ unsigned long ioc_hpa = sba_dev->ioc[i].ioc_hpa;
+ unsigned int j;
+
+ for (j=0; j < sizeof(u64) * ROPES_PER_IOC; j+=sizeof(u64)) {
+
+ /*
+ * Clear ROPE(N)_CONFIG AO bit.
+ * Disables "NT Ordering" (~= !"Relaxed Ordering")
+ * Overrides bit 1 in DMA Hint Sets.
+ * Improves netperf UDP_STREAM by ~10% for bcm5701.
+ */
+ if (IS_PLUTO(sba_dev->iodc)) {
+ unsigned long rope_cfg, cfg_val;
+
+ rope_cfg = ioc_hpa + IOC_ROPE0_CFG + j;
+ cfg_val = READ_REG(rope_cfg);
+ cfg_val &= ~IOC_ROPE_AO;
+ WRITE_REG(cfg_val, rope_cfg);
+ }
+
+ /*
+ ** Make sure the box crashes on rope errors.
+ */
+ WRITE_REG(HF_ENABLE, ioc_hpa + ROPE0_CTL + j);
+ }
+
+ /* flush out the last writes */
READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
DBG_INIT(" ioc[%d] ROPE_CFG 0x%Lx ROPE_DBG 0x%Lx\n",
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 719b863bc20e..828eb45062de 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -155,7 +155,7 @@ superio_init(struct pci_dev *pcidev)
struct pci_dev *pdev = sio->lio_pdev;
u16 word;
- if (sio->suckyio_irq_enabled)
+ if (sio->suckyio_irq_enabled)
return;
BUG_ON(!pdev);
@@ -194,7 +194,7 @@ superio_init(struct pci_dev *pcidev)
request_region (sio->acpi_base, 0x1f, "acpi");
/* Enable the legacy I/O function */
- pci_read_config_word (pdev, PCI_COMMAND, &word);
+ pci_read_config_word (pdev, PCI_COMMAND, &word);
word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
pci_write_config_word (pdev, PCI_COMMAND, word);
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 158d92563259..b953d5907c05 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -81,15 +81,15 @@ static char *version =
#define FORCE_EPP_MODE 0x08
typedef struct parport_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
int ndev;
dev_node_t node;
struct parport *port;
} parport_info_t;
static void parport_detach(struct pcmcia_device *p_dev);
-static void parport_config(dev_link_t *link);
-static void parport_cs_release(dev_link_t *);
+static int parport_config(struct pcmcia_device *link);
+static void parport_cs_release(struct pcmcia_device *);
/*======================================================================
@@ -99,10 +99,9 @@ static void parport_cs_release(dev_link_t *);
======================================================================*/
-static int parport_attach(struct pcmcia_device *p_dev)
+static int parport_probe(struct pcmcia_device *link)
{
parport_info_t *info;
- dev_link_t *link;
DEBUG(0, "parport_attach()\n");
@@ -110,23 +109,17 @@ static int parport_attach(struct pcmcia_device *p_dev)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link; link->priv = info;
+ link->priv = info;
+ info->p_dev = link;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- parport_config(link);
-
- return 0;
+ return parport_config(link);
} /* parport_attach */
/*======================================================================
@@ -138,14 +131,11 @@ static int parport_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void parport_detach(struct pcmcia_device *p_dev)
+static void parport_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "parport_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- parport_cs_release(link);
+ parport_cs_release(link);
kfree(link->priv);
} /* parport_detach */
@@ -161,14 +151,12 @@ static void parport_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-void parport_config(dev_link_t *link)
+static int parport_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
parport_info_t *info = link->priv;
tuple_t tuple;
u_short buf[128];
cisparse_t parse;
- config_info_t conf;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt = { 0 };
struct parport *p;
@@ -180,24 +168,18 @@ void parport_config(dev_link_t *link)
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
- /* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
@@ -212,7 +194,7 @@ void parport_config(dev_link_t *link)
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we've got this far, we're done */
break;
@@ -220,15 +202,12 @@ void parport_config(dev_link_t *link)
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
- release_region(link->io.BasePort1, link->io.NumPorts1);
- if (link->io.NumPorts2)
- release_region(link->io.BasePort2, link->io.NumPorts2);
p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
link->irq.AssignedIRQ, PARPORT_DMA_NONE,
NULL);
@@ -247,17 +226,15 @@ void parport_config(dev_link_t *link)
info->node.minor = p->number;
info->port = p;
strcpy(info->node.dev_name, p->name);
- link->dev = &info->node;
+ link->dev_node = &info->node;
+
+ return 0;
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
parport_cs_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
-
+ return -ENODEV;
} /* parport_config */
/*======================================================================
@@ -268,53 +245,21 @@ failed:
======================================================================*/
-void parport_cs_release(dev_link_t *link)
-{
- parport_info_t *info = link->priv;
-
- DEBUG(0, "parport_release(0x%p)\n", link);
-
- if (info->ndev) {
- struct parport *p = info->port;
- parport_pc_unregister_port(p);
- request_region(link->io.BasePort1, link->io.NumPorts1,
- info->node.dev_name);
- if (link->io.NumPorts2)
- request_region(link->io.BasePort2, link->io.NumPorts2,
- info->node.dev_name);
- }
- info->ndev = 0;
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-
-} /* parport_cs_release */
-
-static int parport_suspend(struct pcmcia_device *dev)
+void parport_cs_release(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
+ parport_info_t *info = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
+ DEBUG(0, "parport_release(0x%p)\n", link);
- return 0;
-}
-
-static int parport_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
+ if (info->ndev) {
+ struct parport *p = info->port;
+ parport_pc_unregister_port(p);
+ }
+ info->ndev = 0;
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
+ pcmcia_disable_device(link);
+} /* parport_cs_release */
- return 0;
-}
static struct pcmcia_device_id parport_ids[] = {
PCMCIA_DEVICE_FUNC_ID(3),
@@ -328,11 +273,9 @@ static struct pcmcia_driver parport_cs_driver = {
.drv = {
.name = "parport_cs",
},
- .probe = parport_attach,
+ .probe = parport_probe,
.remove = parport_detach,
.id_table = parport_ids,
- .suspend = parport_suspend,
- .resume = parport_resume,
};
static int __init init_parport_cs(void)
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index d5890027f8af..48bbf32fd980 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -97,7 +97,7 @@ static struct superio_struct { /* For Super-IO chips autodetection */
int io;
int irq;
int dma;
-} superios[NR_SUPERIOS] __devinitdata = { {0,},};
+} superios[NR_SUPERIOS] = { {0,},};
static int user_specified;
#if defined(CONFIG_PARPORT_PC_SUPERIO) || \
@@ -1557,7 +1557,7 @@ static int __devinit get_superio_dma (struct parport *p)
return PARPORT_DMA_NONE;
}
-static int __devinit get_superio_irq (struct parport *p)
+static int get_superio_irq (struct parport *p)
{
int i=0;
while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -1579,7 +1579,7 @@ static int __devinit get_superio_irq (struct parport *p)
* this shall always be the case!)
*
*/
-static int __devinit parport_SPP_supported(struct parport *pb)
+static int parport_SPP_supported(struct parport *pb)
{
unsigned char r, w;
@@ -1660,7 +1660,7 @@ static int __devinit parport_SPP_supported(struct parport *pb)
* two bits of ECR aren't writable, so we check by writing ECR and
* reading it back to see if it's what we expect.
*/
-static int __devinit parport_ECR_present(struct parport *pb)
+static int parport_ECR_present(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
unsigned char r = 0xc;
@@ -1712,7 +1712,7 @@ static int __devinit parport_ECR_present(struct parport *pb)
* be misdetected here is rather academic.
*/
-static int __devinit parport_PS2_supported(struct parport *pb)
+static int parport_PS2_supported(struct parport *pb)
{
int ok = 0;
@@ -1868,7 +1868,7 @@ static int __devinit parport_ECP_supported(struct parport *pb)
}
#endif
-static int __devinit parport_ECPPS2_supported(struct parport *pb)
+static int parport_ECPPS2_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
int result;
@@ -1886,7 +1886,7 @@ static int __devinit parport_ECPPS2_supported(struct parport *pb)
/* EPP mode detection */
-static int __devinit parport_EPP_supported(struct parport *pb)
+static int parport_EPP_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
@@ -1931,7 +1931,7 @@ static int __devinit parport_EPP_supported(struct parport *pb)
return 1;
}
-static int __devinit parport_ECPEPP_supported(struct parport *pb)
+static int parport_ECPEPP_supported(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
int result;
@@ -2073,7 +2073,7 @@ static int __devinit irq_probe_SPP(struct parport *pb)
* When ECP is available we can autoprobe for IRQs.
* NOTE: If we can autoprobe it, we can register the IRQ.
*/
-static int __devinit parport_irq_probe(struct parport *pb)
+static int parport_irq_probe(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
@@ -2779,7 +2779,7 @@ static struct parport_pc_pci {
/* If set, this is called after probing for ports. If 'failed'
* is non-zero we couldn't use any of the ports. */
void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
+} cards[] = {
/* siig_1p_10x */ { 1, { { 2, 3 }, } },
/* siig_2p_10x */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* siig_1p_20x */ { 1, { { 0, 1 }, } },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index d121644646b9..98b83a85c60e 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -100,8 +100,6 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 6e79f5675b0d..638004546700 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -360,9 +360,6 @@ static int __init rpaphp_init(void)
while ((dn = of_find_node_by_type(dn, "pci")))
rpaphp_add_slot(dn);
- if (!num_slots)
- return -ENODEV;
-
return 0;
}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a77e79c8c82e..9855c4c920b8 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -504,6 +504,201 @@ void pci_scan_msi_device(struct pci_dev *dev)
nr_reserved_vectors++;
}
+#ifdef CONFIG_PM
+int pci_save_msi_state(struct pci_dev *dev)
+{
+ int pos, i = 0;
+ u16 control;
+ struct pci_cap_saved_state *save_state;
+ u32 *cap;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (pos <= 0 || dev->no_msi)
+ return 0;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (!(control & PCI_MSI_FLAGS_ENABLE))
+ return 0;
+
+ save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
+ GFP_KERNEL);
+ if (!save_state) {
+ printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
+ return -ENOMEM;
+ }
+ cap = &save_state->data[0];
+
+ pci_read_config_dword(dev, pos, &cap[i++]);
+ control = cap[0] >> 16;
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
+ if (control & PCI_MSI_FLAGS_64BIT) {
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
+ pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
+ } else
+ pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
+ if (control & PCI_MSI_FLAGS_MASKBIT)
+ pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
+ disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+ save_state->cap_nr = PCI_CAP_ID_MSI;
+ pci_add_saved_cap(dev, save_state);
+ return 0;
+}
+
+void pci_restore_msi_state(struct pci_dev *dev)
+{
+ int i = 0, pos;
+ u16 control;
+ struct pci_cap_saved_state *save_state;
+ u32 *cap;
+
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (!save_state || pos <= 0)
+ return;
+ cap = &save_state->data[0];
+
+ control = cap[i++] >> 16;
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
+ if (control & PCI_MSI_FLAGS_64BIT) {
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
+ pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
+ } else
+ pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
+ if (control & PCI_MSI_FLAGS_MASKBIT)
+ pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
+ pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+ pci_remove_saved_cap(save_state);
+ kfree(save_state);
+}
+
+int pci_save_msix_state(struct pci_dev *dev)
+{
+ int pos;
+ u16 control;
+ struct pci_cap_saved_state *save_state;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ if (pos <= 0 || dev->no_msi)
+ return 0;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (!(control & PCI_MSIX_FLAGS_ENABLE))
+ return 0;
+ save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
+ GFP_KERNEL);
+ if (!save_state) {
+ printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
+ return -ENOMEM;
+ }
+ *((u16 *)&save_state->data[0]) = control;
+
+ disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+ save_state->cap_nr = PCI_CAP_ID_MSIX;
+ pci_add_saved_cap(dev, save_state);
+ return 0;
+}
+
+void pci_restore_msix_state(struct pci_dev *dev)
+{
+ u16 save;
+ int pos;
+ int vector, head, tail = 0;
+ void __iomem *base;
+ int j;
+ struct msg_address address;
+ struct msg_data data;
+ struct msi_desc *entry;
+ int temp;
+ struct pci_cap_saved_state *save_state;
+
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
+ if (!save_state)
+ return;
+ save = *((u16 *)&save_state->data[0]);
+ pci_remove_saved_cap(save_state);
+ kfree(save_state);
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ if (pos <= 0)
+ return;
+
+ /* route the table */
+ temp = dev->irq;
+ if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX))
+ return;
+ vector = head = dev->irq;
+ while (head != tail) {
+ entry = msi_desc[vector];
+ base = entry->mask_base;
+ j = entry->msi_attrib.entry_nr;
+
+ msi_address_init(&address);
+ msi_data_init(&data, vector);
+
+ address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
+ address.lo_address.value |= entry->msi_attrib.current_cpu <<
+ MSI_TARGET_CPU_SHIFT;
+
+ writel(address.lo_address.value,
+ base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+ writel(address.hi_address,
+ base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+ writel(*(u32*)&data,
+ base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_DATA_OFFSET);
+
+ tail = msi_desc[vector]->link.tail;
+ vector = tail;
+ }
+ dev->irq = temp;
+
+ pci_write_config_word(dev, msi_control_reg(pos), save);
+ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+}
+#endif
+
+static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
+{
+ struct msg_address address;
+ struct msg_data data;
+ int pos, vector = dev->irq;
+ u16 control;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ /* Configure MSI capability structure */
+ msi_address_init(&address);
+ msi_data_init(&data, vector);
+ entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+ MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+ pci_write_config_dword(dev, msi_lower_address_reg(pos),
+ address.lo_address.value);
+ if (is_64bit_address(control)) {
+ pci_write_config_dword(dev,
+ msi_upper_address_reg(pos), address.hi_address);
+ pci_write_config_word(dev,
+ msi_data_reg(pos, 1), *((u32*)&data));
+ } else
+ pci_write_config_word(dev,
+ msi_data_reg(pos, 0), *((u32*)&data));
+ if (entry->msi_attrib.maskbit) {
+ unsigned int maskbits, temp;
+ /* All MSIs are unmasked by default, Mask them all */
+ pci_read_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ &maskbits);
+ temp = (1 << multi_msi_capable(control));
+ temp = ((temp - 1) & ~temp);
+ maskbits |= temp;
+ pci_write_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ maskbits);
+ }
+}
+
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
@@ -516,8 +711,6 @@ void pci_scan_msi_device(struct pci_dev *dev)
static int msi_capability_init(struct pci_dev *dev)
{
struct msi_desc *entry;
- struct msg_address address;
- struct msg_data data;
int pos, vector;
u16 control;
@@ -549,33 +742,8 @@ static int msi_capability_init(struct pci_dev *dev)
/* Replace with MSI handler */
irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
/* Configure MSI capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- pci_write_config_dword(dev, msi_lower_address_reg(pos),
- address.lo_address.value);
- if (is_64bit_address(control)) {
- pci_write_config_dword(dev,
- msi_upper_address_reg(pos), address.hi_address);
- pci_write_config_word(dev,
- msi_data_reg(pos, 1), *((u32*)&data));
- } else
- pci_write_config_word(dev,
- msi_data_reg(pos, 0), *((u32*)&data));
- if (entry->msi_attrib.maskbit) {
- unsigned int maskbits, temp;
- /* All MSIs are unmasked by default, Mask them all */
- pci_read_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- &maskbits);
- temp = (1 << multi_msi_capable(control));
- temp = ((temp - 1) & ~temp);
- maskbits |= temp;
- pci_write_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- maskbits);
- }
+ msi_register_init(dev, entry);
+
attach_msi_entry(entry, vector);
/* Set MSI enabled bits */
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
@@ -625,8 +793,10 @@ static int msix_capability_init(struct pci_dev *dev,
if (!entry)
break;
vector = get_msi_vector(dev);
- if (vector < 0)
+ if (vector < 0) {
+ kmem_cache_free(msi_cachep, entry);
break;
+ }
j = entries[i].entry;
entries[i].vector = vector;
@@ -731,6 +901,7 @@ int pci_enable_msi(struct pci_dev* dev)
vector_irq[dev->irq] = -1;
nr_released_vectors--;
spin_unlock_irqrestore(&msi_lock, flags);
+ msi_register_init(dev, msi_desc[dev->irq]);
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
return 0;
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f22f69ac6445..1456759936c5 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
struct pci_driver * drv = pci_dev->driver;
int i = 0;
- if (drv && drv->suspend)
+ if (drv && drv->suspend) {
i = drv->suspend(pci_dev, state);
- else
+ suspend_report_result(drv->suspend, i);
+ } else {
pci_save_state(pci_dev);
+ }
return i;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bea1ad1ad5ba..2329f941a0dc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t 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
*/
- if (state != PCI_D0 && dev->current_state > state)
+ if (state != PCI_D0 && dev->current_state > state) {
+ printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
+ __FUNCTION__, pci_name(dev), state, dev->current_state);
return -EINVAL;
- else if (dev->current_state == state)
+ } else if (dev->current_state == state)
return 0; /* we're already there */
/* find PCI PM capability in list */
@@ -444,6 +446,10 @@ pci_save_state(struct pci_dev *dev)
/* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++)
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+ if ((i = pci_save_msi_state(dev)) != 0)
+ return i;
+ if ((i = pci_save_msix_state(dev)) != 0)
+ return i;
return 0;
}
@@ -458,6 +464,8 @@ pci_restore_state(struct pci_dev *dev)
for (i = 0; i < 16; i++)
pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
+ pci_restore_msi_state(dev);
+ pci_restore_msix_state(dev);
return 0;
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8f3fb47ea671..30630cbe2fe3 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -55,6 +55,17 @@ void pci_no_msi(void);
static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
static inline void pci_no_msi(void) { }
#endif
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
+int pci_save_msi_state(struct pci_dev *dev);
+int pci_save_msix_state(struct pci_dev *dev);
+void pci_restore_msi_state(struct pci_dev *dev);
+void pci_restore_msix_state(struct pci_dev *dev);
+#else
+static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; }
+static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; }
+static inline void pci_restore_msi_state(struct pci_dev *dev) {}
+static inline void pci_restore_msix_state(struct pci_dev *dev) {}
+#endif
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 4970f47be72c..19e2b174d33c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -592,7 +592,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
pci_write_config_byte( dev, AMD8131_MISC, tmp);
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
static void __init quirk_svw_msi(struct pci_dev *dev)
{
@@ -642,13 +642,15 @@ static void quirk_via_irq(struct pci_dev *dev)
new_irq = dev->irq & 0xf;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq) {
- printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
+ printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
pci_name(dev), irq, new_irq);
udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
/*
* VIA VT82C598 has its device ID settable and many BIOSes
@@ -865,6 +867,35 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge );
/*
+ * On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled
+ * when a PCI-Soundcard is added. The BIOS only gives Options
+ * "Disabled" and "AUTO". This Quirk Sets the corresponding
+ * Register-Value to enable the Soundcard.
+ */
+static void __init k8t_sound_hostbridge(struct pci_dev *dev)
+{
+ unsigned char val;
+
+ printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n");
+ pci_read_config_byte(dev, 0x50, &val);
+ if (val == 0x88 || val == 0xc8) {
+ pci_write_config_byte(dev, 0x50, val & (~0x40));
+
+ /* Verify the Change for Status output */
+ pci_read_config_byte(dev, 0x50, &val);
+ if (val & 0x40)
+ printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n");
+ else
+ printk(KERN_INFO "PCI: MSI-K8T soundcard on\n");
+ } else {
+ printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: "
+ "no Change!\n");
+ }
+
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
+
+/*
* On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
* is not activated. The myth is that Asus said that they do not want the
* users to be irritated by just another PCI Device in the Win98 device
@@ -921,6 +952,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
switch (dev->subsystem_device) {
case 0x1882: /* M6V notebook */
+ case 0x1977: /* A6VA notebook */
asus_hides_smbus = 1;
}
}
@@ -999,6 +1031,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asu
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc );
static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
{
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 1f4ad0e7836e..61cb4b29f55c 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -250,7 +250,7 @@ config M32R_CFC_NUM
config PCMCIA_VRC4171
tristate "NEC VRC4171 Card Controllers support"
- depends on VRC4171 && PCMCIA
+ depends on CPU_VR41XX && ISA && PCMCIA
config PCMCIA_VRC4173
tristate "NEC VRC4173 CARDU support"
@@ -263,6 +263,13 @@ config OMAP_CF
Say Y here to support the CompactFlash controller on OMAP.
Note that this doesn't support "True IDE" mode.
+config AT91_CF
+ tristate "AT91 CompactFlash Controller"
+ depends on PCMCIA && ARCH_AT91RM9200
+ help
+ Say Y here to support the CompactFlash controller on AT91 chips.
+ Or choose M to compile the driver as a module named "at91_cf".
+
config PCCARD_NONSTATIC
tristate
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index bcecf5133b7e..4276965517f2 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -10,7 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
-pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o
+pcmcia-y += ds.o pcmcia_resource.o
pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
obj-$(CONFIG_PCMCIA) += pcmcia.o
@@ -36,6 +36,7 @@ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
obj-$(CONFIG_OMAP_CF) += omap_cf.o
+obj-$(CONFIG_AT91_CF) += at91_cf.o
sa11xx_core-y += soc_common.o sa11xx_base.o
pxa2xx_core-y += soc_common.o pxa2xx_base.o
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
new file mode 100644
index 000000000000..a4d50940ebeb
--- /dev/null
+++ b/drivers/pcmcia/at91_cf.c
@@ -0,0 +1,376 @@
+/*
+ * at91_cf.c -- AT91 CompactFlash controller driver
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+/*
+ * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW;
+ * some other bit in {A24,A22..A11} is nREG to flag memory access
+ * (vs attributes). So more than 2KB/region would just be waste.
+ */
+#define CF_ATTR_PHYS (AT91_CF_BASE)
+#define CF_IO_PHYS (AT91_CF_BASE + (1 << 23))
+#define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800)
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "at91_cf";
+
+struct at91_cf_socket {
+ struct pcmcia_socket socket;
+
+ unsigned present:1;
+
+ struct platform_device *pdev;
+ struct at91_cf_data *board;
+};
+
+#define SZ_2K (2 * SZ_1K)
+
+static inline int at91_cf_present(struct at91_cf_socket *cf)
+{
+ return !at91_get_gpio_value(cf->board->det_pin);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int at91_cf_ss_init(struct pcmcia_socket *s)
+{
+ return 0;
+}
+
+static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+ struct at91_cf_socket *cf = (struct at91_cf_socket *) _cf;
+
+ if (irq == cf->board->det_pin) {
+ unsigned present = at91_cf_present(cf);
+
+ /* kick pccard as needed */
+ if (present != cf->present) {
+ cf->present = present;
+ pr_debug("%s: card %s\n", driver_name,
+ present ? "present" : "gone");
+ pcmcia_parse_events(&cf->socket, SS_DETECT);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+ struct at91_cf_socket *cf;
+
+ if (!sp)
+ return -EINVAL;
+
+ cf = container_of(s, struct at91_cf_socket, socket);
+
+ /* NOTE: CF is always 3VCARD */
+ if (at91_cf_present(cf)) {
+ int rdy = cf->board->irq_pin; /* RDY/nIRQ */
+ int vcc = cf->board->vcc_pin;
+
+ *sp = SS_DETECT | SS_3VCARD;
+ if (!rdy || at91_get_gpio_value(rdy))
+ *sp |= SS_READY;
+ if (!vcc || at91_get_gpio_value(vcc))
+ *sp |= SS_POWERON;
+ } else
+ *sp = 0;
+
+ return 0;
+}
+
+static int
+at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+ struct at91_cf_socket *cf;
+
+ cf = container_of(sock, struct at91_cf_socket, socket);
+
+ /* switch Vcc if needed and possible */
+ if (cf->board->vcc_pin) {
+ switch (s->Vcc) {
+ case 0:
+ at91_set_gpio_value(cf->board->vcc_pin, 0);
+ break;
+ case 33:
+ at91_set_gpio_value(cf->board->vcc_pin, 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* toggle reset if needed */
+ at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET);
+
+ pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+ return 0;
+}
+
+static int at91_cf_ss_suspend(struct pcmcia_socket *s)
+{
+ return at91_cf_set_socket(s, &dead_socket);
+}
+
+/* we already mapped the I/O region */
+static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+ struct at91_cf_socket *cf;
+ u32 csr;
+
+ cf = container_of(s, struct at91_cf_socket, socket);
+ io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ);
+
+ /*
+ * Use 16 bit accesses unless/until we need 8-bit i/o space.
+ * Always set CSR4 ... PCMCIA won't always unmap things.
+ */
+ csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW;
+
+ /*
+ * NOTE: this CF controller ignores IOIS16, so we can't really do
+ * MAP_AUTOSZ. The 16bit mode allows single byte access on either
+ * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many
+ * purposes (and handles ide-cs).
+ *
+ * The 8bit mode is needed for odd byte access on D0-D7. It seems
+ * some cards only like that way to get at the odd byte, despite
+ * CF 3.0 spec table 35 also giving the D8-D15 option.
+ */
+ if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) {
+ csr |= AT91_SMC_DBW_8;
+ pr_debug("%s: 8bit i/o bus\n", driver_name);
+ } else {
+ csr |= AT91_SMC_DBW_16;
+ pr_debug("%s: 16bit i/o bus\n", driver_name);
+ }
+ at91_sys_write(AT91_SMC_CSR(4), csr);
+
+ io->start = cf->socket.io_offset;
+ io->stop = io->start + SZ_2K - 1;
+
+ return 0;
+}
+
+/* pcmcia layer maps/unmaps mem regions */
+static int
+at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+ struct at91_cf_socket *cf;
+
+ if (map->card_start)
+ return -EINVAL;
+
+ cf = container_of(s, struct at91_cf_socket, socket);
+
+ map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+ if (map->flags & MAP_ATTRIB)
+ map->static_start = CF_ATTR_PHYS;
+ else
+ map->static_start = CF_MEM_PHYS;
+
+ return 0;
+}
+
+static struct pccard_operations at91_cf_ops = {
+ .init = at91_cf_ss_init,
+ .suspend = at91_cf_ss_suspend,
+ .get_status = at91_cf_get_status,
+ .set_socket = at91_cf_set_socket,
+ .set_io_map = at91_cf_set_io_map,
+ .set_mem_map = at91_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_probe(struct device *dev)
+{
+ struct at91_cf_socket *cf;
+ struct at91_cf_data *board = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *io;
+ unsigned int csa;
+ int status;
+
+ if (!board || !board->det_pin || !board->rst_pin)
+ return -ENODEV;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io)
+ return -ENODEV;
+
+ cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ if (!cf)
+ return -ENOMEM;
+
+ cf->board = board;
+ cf->pdev = pdev;
+ dev_set_drvdata(dev, cf);
+
+ /* CF takes over CS4, CS5, CS6 */
+ csa = at91_sys_read(AT91_EBI_CSA);
+ at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
+
+ /* force poweron defaults for these pins ... */
+ (void) at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */
+ (void) at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */
+ (void) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */
+ (void) at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */
+
+ /* nWAIT is _not_ a default setting */
+ (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */
+
+ /*
+ * Static memory controller timing adjustments.
+ * REVISIT: these timings are in terms of MCK cycles, so
+ * when MCK changes (cpufreq etc) so must these values...
+ */
+ at91_sys_write(AT91_SMC_CSR(4),
+ AT91_SMC_ACSS_STD
+ | AT91_SMC_DBW_16
+ | AT91_SMC_BAT
+ | AT91_SMC_WSEN
+ | AT91_SMC_NWS_(32) /* wait states */
+ | AT91_SMC_RWSETUP_(6) /* setup time */
+ | AT91_SMC_RWHOLD_(4) /* hold time */
+ );
+
+ /* must be a GPIO; ergo must trigger on both edges */
+ status = request_irq(board->det_pin, at91_cf_irq,
+ SA_SAMPLE_RANDOM, driver_name, cf);
+ if (status < 0)
+ goto fail0;
+
+ /*
+ * The card driver will request this irq later as needed.
+ * but it causes lots of "irqNN: nobody cared" messages
+ * unless we report that we handle everything (sigh).
+ * (Note: DK board doesn't wire the IRQ pin...)
+ */
+ if (board->irq_pin) {
+ status = request_irq(board->irq_pin, at91_cf_irq,
+ SA_SHIRQ, driver_name, cf);
+ if (status < 0)
+ goto fail0a;
+ cf->socket.pci_irq = board->irq_pin;
+ } else
+ cf->socket.pci_irq = NR_IRQS + 1;
+
+ /* pcmcia layer only remaps "real" memory not iospace */
+ cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K);
+ if (!cf->socket.io_offset)
+ goto fail1;
+
+ /* reserve CS4, CS5, and CS6 regions; but use just CS4 */
+ if (!request_mem_region(io->start, io->end + 1 - io->start,
+ driver_name))
+ goto fail1;
+
+ pr_info("%s: irqs det #%d, io #%d\n", driver_name,
+ board->det_pin, board->irq_pin);
+
+ cf->socket.owner = THIS_MODULE;
+ cf->socket.dev.dev = dev;
+ cf->socket.ops = &at91_cf_ops;
+ cf->socket.resource_ops = &pccard_static_ops;
+ cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
+ | SS_CAP_MEM_ALIGN;
+ cf->socket.map_size = SZ_2K;
+ cf->socket.io[0].res = io;
+
+ status = pcmcia_register_socket(&cf->socket);
+ if (status < 0)
+ goto fail2;
+
+ return 0;
+
+fail2:
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(io->start, io->end + 1 - io->start);
+fail1:
+ if (board->irq_pin)
+ free_irq(board->irq_pin, cf);
+fail0a:
+ free_irq(board->det_pin, cf);
+fail0:
+ at91_sys_write(AT91_EBI_CSA, csa);
+ kfree(cf);
+ return status;
+}
+
+static int __exit at91_cf_remove(struct device *dev)
+{
+ struct at91_cf_socket *cf = dev_get_drvdata(dev);
+ struct resource *io = cf->socket.io[0].res;
+ unsigned int csa;
+
+ pcmcia_unregister_socket(&cf->socket);
+ free_irq(cf->board->irq_pin, cf);
+ free_irq(cf->board->det_pin, cf);
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(io->start, io->end + 1 - io->start);
+
+ csa = at91_sys_read(AT91_EBI_CSA);
+ at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
+
+ kfree(cf);
+ return 0;
+}
+
+static struct device_driver at91_cf_driver = {
+ .name = (char *) driver_name,
+ .bus = &platform_bus_type,
+ .probe = at91_cf_probe,
+ .remove = __exit_p(at91_cf_remove),
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_init(void)
+{
+ return driver_register(&at91_cf_driver);
+}
+module_init(at91_cf_init);
+
+static void __exit at91_cf_exit(void)
+{
+ driver_unregister(&at91_cf_driver);
+}
+module_exit(at91_cf_exit);
+
+MODULE_DESCRIPTION("AT91 Compact Flash Driver");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 120fa8da6392..912c03e5eb0a 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -12,7 +12,6 @@
* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 613f2f1fbfdd..3162998579c1 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -16,7 +16,6 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -111,9 +110,9 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
if (socket->dev.dev != dev)
continue;
- down(&socket->skt_sem);
+ mutex_lock(&socket->skt_mutex);
socket_suspend(socket);
- up(&socket->skt_sem);
+ mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
@@ -129,9 +128,9 @@ int pcmcia_socket_dev_resume(struct device *dev)
list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
if (socket->dev.dev != dev)
continue;
- down(&socket->skt_sem);
+ mutex_lock(&socket->skt_mutex);
socket_resume(socket);
- up(&socket->skt_sem);
+ mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
@@ -237,7 +236,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
init_completion(&socket->socket_released);
init_completion(&socket->thread_done);
init_waitqueue_head(&socket->thread_wait);
- init_MUTEX(&socket->skt_sem);
+ mutex_init(&socket->skt_mutex);
spin_lock_init(&socket->thread_lock);
ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
@@ -406,8 +405,6 @@ static void socket_shutdown(struct pcmcia_socket *s)
cb_free(s);
#endif
s->functions = 0;
- kfree(s->config);
- s->config = NULL;
s->ops->get_status(s, &status);
if (status & SS_POWERON) {
@@ -664,7 +661,7 @@ static int pccardd(void *__skt)
spin_unlock_irqrestore(&skt->thread_lock, flags);
if (events) {
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
if (events & SS_DETECT)
socket_detect_change(skt);
if (events & SS_BATDEAD)
@@ -673,7 +670,7 @@ static int pccardd(void *__skt)
send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
if (events & SS_READY)
send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
continue;
}
@@ -717,8 +714,8 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
{
int ret = 0;
- /* s->skt_sem also protects s->callback */
- down(&s->skt_sem);
+ /* s->skt_mutex also protects s->callback */
+ mutex_lock(&s->skt_mutex);
if (c) {
/* registration */
@@ -734,7 +731,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
} else
s->callback = NULL;
err:
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
return ret;
}
@@ -752,7 +749,7 @@ int pccard_reset_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "resetting socket\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
@@ -781,7 +778,7 @@ int pccard_reset_card(struct pcmcia_socket *skt)
ret = CS_SUCCESS;
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* reset_card */
@@ -797,7 +794,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "suspending socket\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
@@ -814,7 +811,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
}
ret = socket_suspend(skt);
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* suspend_card */
@@ -827,7 +824,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "waking up socket\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
@@ -841,7 +838,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
if (!ret && skt->callback)
skt->callback->resume(skt);
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* resume_card */
@@ -855,7 +852,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "user eject request\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = -ENODEV;
@@ -871,7 +868,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
socket_remove(skt);
ret = 0;
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* eject_card */
@@ -884,7 +881,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "user insert request\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (skt->state & SOCKET_PRESENT) {
ret = -EBUSY;
@@ -896,7 +893,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
}
ret = 0;
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* insert_card */
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 7b37eba35bf1..d6164cd583fd 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -15,7 +15,7 @@
#ifndef _LINUX_CS_INTERNAL_H
#define _LINUX_CS_INTERNAL_H
-#include <linux/config.h>
+#include <linux/kref.h>
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
@@ -23,7 +23,7 @@
#define CLIENT_IO_REQ 0x0004
#define CLIENT_UNBOUND 0x0008
#define CLIENT_STALE 0x0010
-#define CLIENT_WIN_REQ(i) (0x20<<(i))
+#define CLIENT_WIN_REQ(i) (0x1<<(i))
#define CLIENT_CARDBUS 0x8000
#define REGION_MAGIC 0xE3C9
@@ -31,7 +31,7 @@ typedef struct region_t {
u_short region_magic;
u_short state;
dev_info_t dev_info;
- client_handle_t mtd;
+ struct pcmcia_device *mtd;
u_int MediaID;
region_info_t info;
} region_t;
@@ -40,12 +40,12 @@ typedef struct region_t {
/* Each card function gets one of these guys */
typedef struct config_t {
+ struct kref ref;
u_int state;
u_int Attributes;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
- u_int Present;
u_int CardValues;
io_req_t io;
struct {
@@ -95,12 +95,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)
}
}
-#define CHECK_SOCKET(s) \
- (((s) >= sockets) || (socket_table[s]->ops == NULL))
-
-#define SOCKET(h) (h->socket)
-#define CONFIG(h) (&SOCKET(h)->config[(h)->func])
-
/* In cardbus.c */
int cb_alloc(struct pcmcia_socket *s);
void cb_free(struct pcmcia_socket *s);
@@ -133,10 +127,9 @@ extern struct class_interface pccard_sysfs_interface;
extern struct rw_semaphore pcmcia_socket_list_rwsem;
extern struct list_head pcmcia_socket_list;
int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
-int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config);
+int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
int pccard_reset_card(struct pcmcia_socket *skt);
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status);
-int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg);
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status);
struct pcmcia_callback{
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bb96ce1db08c..48d3b3d30c21 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -10,10 +10,9 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2005 Dominik Brodowski
+ * (C) 2003 - 2006 Dominik Brodowski
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -23,6 +22,7 @@
#include <linux/workqueue.h>
#include <linux/crc32.h>
#include <linux/firmware.h>
+#include <linux/kref.h>
#define IN_CARD_SERVICES
#include <pcmcia/cs_types.h>
@@ -236,11 +236,11 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
/**
* pcmcia_load_firmware - load CIS from userspace if device-provided is broken
* @dev - the pcmcia device which needs a CIS override
- * @filename - requested filename in /lib/firmware/cis/
+ * @filename - requested filename in /lib/firmware/
*
* This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
* the one provided by the card is broken. The firmware files reside in
- * /lib/firmware/cis/ in userspace.
+ * /lib/firmware/ in userspace.
*/
static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
@@ -298,9 +298,6 @@ static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filenam
*
* Registers a PCMCIA driver with the PCMCIA bus core.
*/
-static int pcmcia_device_probe(struct device *dev);
-static int pcmcia_device_remove(struct device * dev);
-
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
if (!driver)
@@ -343,12 +340,19 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev)
put_device(&p_dev->dev);
}
+static void pcmcia_release_function(struct kref *ref)
+{
+ struct config_t *c = container_of(ref, struct config_t, ref);
+ kfree(c);
+}
+
static void pcmcia_release_dev(struct device *dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
ds_dbg(1, "releasing dev %p\n", p_dev);
pcmcia_put_socket(p_dev->socket);
kfree(p_dev->devname);
+ kref_put(&p_dev->function_config->ref, pcmcia_release_function);
kfree(p_dev);
}
@@ -377,29 +381,12 @@ static int pcmcia_device_probe(struct device * dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
- if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
+ if ((!p_drv->probe) || (!p_dev->function_config) ||
+ (!try_module_get(p_drv->owner))) {
ret = -EINVAL;
goto put_dev;
}
- p_dev->state &= ~CLIENT_UNBOUND;
-
- /* set up the device configuration, if it hasn't been done before */
- if (!s->functions) {
- cistpl_longlink_mfc_t mfc;
- if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
- &mfc) == CS_SUCCESS)
- s->functions = mfc.nfn;
- else
- s->functions = 1;
- s->config = kzalloc(sizeof(config_t) * s->functions,
- GFP_KERNEL);
- if (!s->config) {
- ret = -ENOMEM;
- goto put_module;
- }
- }
-
ret = p_drv->probe(p_dev);
if (ret)
goto put_module;
@@ -410,7 +397,7 @@ static int pcmcia_device_probe(struct device * dev)
* call which will then check whether there are two
* pseudo devices, and if not, add the second one.
*/
- did = (struct pcmcia_device_id *) p_dev->dev.driver_data;
+ did = p_dev->dev.driver_data;
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_pseudo_device(p_dev->socket);
@@ -425,33 +412,79 @@ static int pcmcia_device_probe(struct device * dev)
}
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_device *tmp;
+ unsigned long flags;
+
+ ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+
+ if (!leftover)
+ s->device_count = 0;
+ else
+ s->device_count = 1;
+
+ /* unregister all pcmcia_devices registered with this socket, except leftover */
+ list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
+ if (p_dev == leftover)
+ continue;
+
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_del(&p_dev->socket_device_list);
+ p_dev->_removed=1;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ device_unregister(&p_dev->dev);
+ }
+
+ return;
+}
+
static int pcmcia_device_remove(struct device * dev)
{
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
+ struct pcmcia_device_id *did;
int i;
- /* detach the "instance" */
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
+
+ /* If we're removing the primary module driving a
+ * pseudo multi-function card, we need to unbind
+ * all devices
+ */
+ did = p_dev->dev.driver_data;
+ if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+ (p_dev->socket->device_count != 0) &&
+ (p_dev->device_no == 0))
+ pcmcia_card_remove(p_dev->socket, p_dev);
+
+ /* detach the "instance" */
if (!p_drv)
return 0;
if (p_drv->remove)
p_drv->remove(p_dev);
+ p_dev->dev_node = NULL;
+
/* check for proper unloading */
- if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+ if (p_dev->_irq || p_dev->_io || p_dev->_locked)
printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
p_drv->drv.name);
for (i = 0; i < MAX_WIN; i++)
- if (p_dev->state & CLIENT_WIN_REQ(i))
+ if (p_dev->_win & CLIENT_WIN_REQ(i))
printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
p_drv->drv.name);
/* references from pcmcia_probe_device */
- p_dev->state = CLIENT_UNBOUND;
pcmcia_put_dev(p_dev);
module_put(p_drv->owner);
@@ -460,37 +493,6 @@ static int pcmcia_device_remove(struct device * dev)
/*
- * Removes a PCMCIA card from the device tree and socket list.
- */
-static void pcmcia_card_remove(struct pcmcia_socket *s)
-{
- struct pcmcia_device *p_dev;
- unsigned long flags;
-
- ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
- s->device_count = 0;
-
- for (;;) {
- /* unregister all pcmcia_devices registered with this socket*/
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- if (list_empty(&s->devices_list)) {
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- return;
- }
- p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
- list_del(&p_dev->socket_device_list);
- p_dev->state |= CLIENT_STALE;
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
- device_unregister(&p_dev->dev);
- }
-
- return;
-} /* unbind_request */
-
-
-/*
* pcmcia_device_query -- determine information about a pcmcia device
*/
static int pcmcia_device_query(struct pcmcia_device *p_dev)
@@ -546,7 +548,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
tmp = vers1->str + vers1->ofs[i];
length = strlen(tmp) + 1;
- if ((length < 3) || (length > 255))
+ if ((length < 2) || (length > 255))
continue;
p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
@@ -571,11 +573,11 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
* won't work, this doesn't matter much at the moment: the driver core doesn't
* support it either.
*/
-static DECLARE_MUTEX(device_add_lock);
+static DEFINE_MUTEX(device_add_lock);
struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
{
- struct pcmcia_device *p_dev;
+ struct pcmcia_device *p_dev, *tmp_dev;
unsigned long flags;
int bus_id_len;
@@ -583,7 +585,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
if (!s)
return NULL;
- down(&device_add_lock);
+ mutex_lock(&device_add_lock);
/* max of 2 devices per card */
if (s->device_count == 2)
@@ -596,6 +598,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
p_dev->socket = s;
p_dev->device_no = (s->device_count++);
p_dev->func = function;
+ if (s->functions <= function)
+ s->functions = function + 1;
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->dev.dev;
@@ -608,36 +612,55 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
/* compat */
- p_dev->state = CLIENT_UNBOUND;
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+
+ /*
+ * p_dev->function_config must be the same for all card functions.
+ * Note that this is serialized by the device_add_lock, so that
+ * only one such struct will be created.
+ */
+ list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
+ if (p_dev->func == tmp_dev->func) {
+ p_dev->function_config = tmp_dev->function_config;
+ kref_get(&p_dev->function_config->ref);
+ }
/* Add to the list in pcmcia_bus_socket */
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+ list_add(&p_dev->socket_device_list, &s->devices_list);
+
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ if (!p_dev->function_config) {
+ p_dev->function_config = kzalloc(sizeof(struct config_t),
+ GFP_KERNEL);
+ if (!p_dev->function_config)
+ goto err_unreg;
+ kref_init(&p_dev->function_config->ref);
+ }
+
printk(KERN_NOTICE "pcmcia: registering new device %s\n",
p_dev->devname);
pcmcia_device_query(p_dev);
- if (device_register(&p_dev->dev)) {
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- list_del(&p_dev->socket_device_list);
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
- goto err_free;
- }
+ if (device_register(&p_dev->dev))
+ goto err_unreg;
- up(&device_add_lock);
+ mutex_unlock(&device_add_lock);
return p_dev;
+ err_unreg:
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_del(&p_dev->socket_device_list);
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
err_free:
kfree(p_dev->devname);
kfree(p_dev);
s->device_count--;
err_put:
- up(&device_add_lock);
+ mutex_unlock(&device_add_lock);
pcmcia_put_socket(s);
return NULL;
@@ -696,7 +719,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt)
int no_devices=0;
unsigned long flags;
- /* must be called with skt_sem held */
+ /* must be called with skt_mutex held */
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&skt->devices_list))
no_devices=1;
@@ -819,9 +842,11 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
struct pcmcia_device_id *did = p_drv->id_table;
+#ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
if (p_dev->cardmgr == p_drv)
return 1;
+#endif
while (did && did->match_flags) {
if (pcmcia_devmatch(p_dev, did))
@@ -927,7 +952,7 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- if (p_dev->dev.power.power_state.event != PM_EVENT_ON)
+ if (p_dev->suspended)
return sprintf(buf, "off\n");
else
return sprintf(buf, "on\n");
@@ -942,11 +967,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
if (!count)
return -EINVAL;
- if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) &&
- (!strncmp(buf, "off", 3)))
+ if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
- else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) &&
- (!strncmp(buf, "on", 2)))
+ else if (p_dev->suspended && !strncmp(buf, "on", 2))
dpm_runtime_resume(dev);
return ret ? ret : count;
@@ -982,9 +1005,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
if (!count)
return -EINVAL;
- down(&p_dev->socket->skt_sem);
+ mutex_lock(&p_dev->socket->skt_mutex);
p_dev->allow_func_id_match = 1;
- up(&p_dev->socket->skt_sem);
+ mutex_unlock(&p_dev->socket->skt_mutex);
bus_rescan_devices(&pcmcia_bus_type);
@@ -1012,14 +1035,27 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = NULL;
+ int ret = 0;
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
- if (p_drv && p_drv->suspend)
- return p_drv->suspend(p_dev);
+ if (!p_drv)
+ goto out;
- return 0;
+ if (p_drv->suspend) {
+ ret = p_drv->suspend(p_dev);
+ if (ret)
+ goto out;
+ }
+
+ if (p_dev->device_no == p_dev->func)
+ pcmcia_release_configuration(p_dev);
+
+ out:
+ if (!ret)
+ p_dev->suspended = 1;
+ return ret;
}
@@ -1027,14 +1063,27 @@ static int pcmcia_dev_resume(struct device * dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = NULL;
+ int ret = 0;
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
- if (p_drv && p_drv->resume)
- return p_drv->resume(p_dev);
+ if (!p_drv)
+ goto out;
- return 0;
+ if (p_dev->device_no == p_dev->func) {
+ ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+ if (ret)
+ goto out;
+ }
+
+ if (p_drv->resume)
+ ret = p_drv->resume(p_dev);
+
+ out:
+ if (!ret)
+ p_dev->suspended = 0;
+ return ret;
}
@@ -1100,7 +1149,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
switch (event) {
case CS_EVENT_CARD_REMOVAL:
s->pcmcia_state.present = 0;
- pcmcia_card_remove(skt);
+ pcmcia_card_remove(skt, NULL);
handle_event(skt, event);
break;
@@ -1128,6 +1177,32 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
} /* ds_event */
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_device *ret = NULL;
+
+ p_dev = pcmcia_get_dev(_p_dev);
+ if (!p_dev)
+ return NULL;
+
+ if (!p_dev->socket->pcmcia_state.present)
+ goto out;
+
+ if (p_dev->_removed)
+ goto out;
+
+ if (p_dev->suspended)
+ goto out;
+
+ ret = p_dev;
+ out:
+ pcmcia_put_dev(p_dev);
+ return ret;
+}
+EXPORT_SYMBOL(pcmcia_dev_present);
+
+
static struct pcmcia_callback pcmcia_bus_callback = {
.owner = THIS_MODULE,
.event = ds_event,
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h
index d359bd25a51c..3a2b25e6ed73 100644
--- a/drivers/pcmcia/ds_internal.h
+++ b/drivers/pcmcia/ds_internal.h
@@ -8,6 +8,8 @@ extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function);
+extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+
#ifdef CONFIG_PCMCIA_IOCTL
extern void __init pcmcia_setup_ioctl(void);
extern void __exit pcmcia_cleanup_ioctl(void);
@@ -15,7 +17,7 @@ extern void handle_event(struct pcmcia_socket *s, event_t event);
extern int handle_request(struct pcmcia_socket *s, event_t event);
#else
static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __init pcmcia_cleanup_ioctl(void) { return; }
+static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; }
static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; }
#endif
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 7979c85df3dc..d5f03a338c6c 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -10,7 +10,6 @@
*/
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 35a92d1e4945..a2f05f485156 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -34,7 +34,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/string.h>
@@ -510,7 +509,8 @@ static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs)
static u_int __init test_irq(u_short sock, int irq)
{
debug(2, " testing ISA irq %d\n", irq);
- if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
+ if (request_irq(irq, i365_count_irq, SA_PROBEIRQ, "scan",
+ i365_count_irq) != 0)
return 1;
irq_hits = 0; irq_sock = sock;
msleep(10);
@@ -562,7 +562,7 @@ static u_int __init isa_scan(u_short sock, u_int mask0)
} else {
/* Fallback: just find interrupts that aren't in use */
for (i = 0; i < 16; i++)
- if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))
+ if ((mask0 & (1 << i)) && (_check_irq(i, SA_PROBEIRQ) == 0))
mask1 |= (1 << i);
printk("default");
/* If scan failed, default to polled status */
@@ -726,7 +726,7 @@ static void __init add_pcic(int ns, int type)
u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
for (cs_irq = 15; cs_irq > 0; cs_irq--)
if ((cs_mask & (1 << cs_irq)) &&
- (_check_irq(cs_irq, 0) == 0))
+ (_check_irq(cs_irq, SA_PROBEIRQ) == 0))
break;
if (cs_irq) {
grab_irq = 1;
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c
deleted file mode 100644
index ebb161c4f819..000000000000
--- a/drivers/pcmcia/pcmcia_compat.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * PCMCIA 16-bit compatibility functions
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Copyright (C) 2004 Dominik Brodowski
- *
- * 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/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#define IN_CARD_SERVICES
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/ss.h>
-
-#include "cs_internal.h"
-
-int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
- return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_first_tuple);
-
-int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
- return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_next_tuple);
-
-int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
- return pccard_get_tuple_data(p_dev->socket, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_tuple_data);
-
-int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse)
-{
- return pccard_parse_tuple(tuple, parse);
-}
-EXPORT_SYMBOL(pcmcia_parse_tuple);
-
-int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info)
-{
- return pccard_validate_cis(p_dev->socket, p_dev->func, info);
-}
-EXPORT_SYMBOL(pcmcia_validate_cis);
-
-
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req)
-{
- return pccard_reset_card(p_dev->socket);
-}
-EXPORT_SYMBOL(pcmcia_reset_card);
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 80969f7e7a0b..c53db7ceda5e 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -18,7 +18,6 @@
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -70,10 +69,26 @@ extern int ds_pc_debug;
#define ds_dbg(lvl, fmt, arg...) do { } while (0)
#endif
+static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
+ unsigned int function)
+{
+ struct pcmcia_device *p_dev = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+ if (p_dev->func == function) {
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return pcmcia_get_dev(p_dev);
+ }
+ }
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return NULL;
+}
/* backwards-compatible accessing of driver --- by name! */
-static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
+static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
{
struct device_driver *drv;
struct pcmcia_driver *p_drv;
@@ -214,7 +229,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
* by userspace before, we need to
* return the "instance". */
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- bind_info->instance = p_dev->instance;
+ bind_info->instance = p_dev;
ret = -EBUSY;
goto err_put_module;
} else {
@@ -253,9 +268,9 @@ rescan:
/*
* Prevent this racing with a card insertion.
*/
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
bus_rescan_devices(&pcmcia_bus_type);
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
/* check whether the driver indeed matched. I don't care if this
* is racy or not, because it can only happen on cardmgr access
@@ -289,6 +304,7 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int
{
dev_node_t *node;
struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
unsigned long flags;
int ret = 0;
@@ -343,16 +359,16 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int
found:
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- if ((!p_dev->instance) ||
- (p_dev->instance->state & DEV_CONFIG_PENDING)) {
+ p_drv = to_pcmcia_drv(p_dev->dev.driver);
+ if (p_drv && !p_dev->_locked) {
ret = -EAGAIN;
goto err_put;
}
if (first)
- node = p_dev->instance->dev;
+ node = p_dev->dev_node;
else
- for (node = p_dev->instance->dev; node; node = node->next)
+ for (node = p_dev->dev_node; node; node = node->next)
if (node == bind_info->next)
break;
if (!node) {
@@ -583,14 +599,16 @@ static int ds_ioctl(struct inode * inode, struct file * file,
if (buf->config.Function &&
(buf->config.Function >= s->functions))
ret = CS_BAD_ARGS;
- else
- ret = pccard_get_configuration_info(s,
- buf->config.Function, &buf->config);
+ else {
+ struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
+ ret = pccard_get_configuration_info(s, p_dev, &buf->config);
+ pcmcia_put_dev(p_dev);
+ }
break;
case DS_GET_FIRST_TUPLE:
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
pcmcia_validate_mem(s);
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_NEXT_TUPLE:
@@ -609,16 +627,19 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pccard_reset_card(s);
break;
case DS_GET_STATUS:
- if (buf->status.Function &&
- (buf->status.Function >= s->functions))
- ret = CS_BAD_ARGS;
- else
- ret = pccard_get_status(s, buf->status.Function, &buf->status);
- break;
+ if (buf->status.Function &&
+ (buf->status.Function >= s->functions))
+ ret = CS_BAD_ARGS;
+ else {
+ struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
+ ret = pccard_get_status(s, p_dev, &buf->status);
+ pcmcia_put_dev(p_dev);
+ }
+ break;
case DS_VALIDATE_CIS:
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
pcmcia_validate_mem(s);
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo);
break;
case DS_SUSPEND_CARD:
@@ -638,12 +659,16 @@ static int ds_ioctl(struct inode * inode, struct file * file,
err = -EPERM;
goto free_out;
}
- if (buf->conf_reg.Function &&
- (buf->conf_reg.Function >= s->functions))
- ret = CS_BAD_ARGS;
- else
- ret = pccard_access_configuration_register(s,
- buf->conf_reg.Function, &buf->conf_reg);
+
+ ret = CS_BAD_ARGS;
+
+ if (!(buf->conf_reg.Function &&
+ (buf->conf_reg.Function >= s->functions))) {
+ struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
+ if (p_dev)
+ ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
+ pcmcia_put_dev(p_dev);
+ }
break;
case DS_GET_FIRST_REGION:
case DS_GET_NEXT_REGION:
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 89022ad5b520..3131bb0a0095 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -14,7 +14,6 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@@ -89,7 +88,6 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
}
if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
*base = s->io_offset | (*base & 0x0fff);
- s->io[0].Attributes = attr;
return 0;
}
/* Check for an already-allocated window that must conflict with
@@ -97,38 +95,36 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
* potential conflicts, just the most obvious ones.
*/
for (i = 0; i < MAX_IO_WIN; i++)
- if ((s->io[i].NumPorts != 0) &&
- ((s->io[i].BasePort & (align-1)) == *base))
+ if ((s->io[i].res) &&
+ ((s->io[i].res->start & (align-1)) == *base))
return 1;
for (i = 0; i < MAX_IO_WIN; i++) {
- if (s->io[i].NumPorts == 0) {
+ if (!s->io[i].res) {
s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
if (s->io[i].res) {
- s->io[i].Attributes = attr;
- s->io[i].BasePort = *base = s->io[i].res->start;
- s->io[i].NumPorts = s->io[i].InUse = num;
+ *base = s->io[i].res->start;
+ s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
+ s->io[i].InUse = num;
break;
} else
return 1;
- } else if (s->io[i].Attributes != attr)
+ } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS))
continue;
/* Try to extend top of window */
- try = s->io[i].BasePort + s->io[i].NumPorts;
+ try = s->io[i].res->end + 1;
if ((*base == 0) || (*base == try))
if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
s->io[i].res->end + num, s) == 0) {
*base = try;
- s->io[i].NumPorts += num;
s->io[i].InUse += num;
break;
}
/* Try to extend bottom of window */
- try = s->io[i].BasePort - num;
+ try = s->io[i].res->start - num;
if ((*base == 0) || (*base == try))
if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
s->io[i].res->end, s) == 0) {
- s->io[i].BasePort = *base = try;
- s->io[i].NumPorts += num;
+ *base = try;
s->io[i].InUse += num;
break;
}
@@ -143,12 +139,13 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
int i;
for (i = 0; i < MAX_IO_WIN; i++) {
- if ((s->io[i].BasePort <= base) &&
- (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
+ if (!s->io[i].res)
+ continue;
+ if ((s->io[i].res->start <= base) &&
+ (s->io[i].res->end >= base+num-1)) {
s->io[i].InUse -= num;
/* Free the window if no one else is using it */
if (s->io[i].InUse == 0) {
- s->io[i].NumPorts = 0;
release_resource(s->io[i].res);
kfree(s->io[i].res);
s->io[i].res = NULL;
@@ -165,21 +162,19 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
* this and the tuple reading services.
*/
-int pccard_access_configuration_register(struct pcmcia_socket *s,
- unsigned int function,
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
conf_reg_t *reg)
{
+ struct pcmcia_socket *s;
config_t *c;
int addr;
u_char val;
- if (!s || !s->config)
+ if (!p_dev || !p_dev->function_config)
return CS_NO_CARD;
- c = &s->config[function];
-
- if (c == NULL)
- return CS_NO_CARD;
+ s = p_dev->socket;
+ c = p_dev->function_config;
if (!(c->state & CONFIG_LOCKED))
return CS_CONFIGURATION_LOCKED;
@@ -200,20 +195,12 @@ int pccard_access_configuration_register(struct pcmcia_socket *s,
break;
}
return CS_SUCCESS;
-} /* pccard_access_configuration_register */
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
- conf_reg_t *reg)
-{
- return pccard_access_configuration_register(p_dev->socket,
- p_dev->func, reg);
-}
+} /* pcmcia_access_configuration_register */
EXPORT_SYMBOL(pcmcia_access_configuration_register);
-
int pccard_get_configuration_info(struct pcmcia_socket *s,
- unsigned int function,
+ struct pcmcia_device *p_dev,
config_info_t *config)
{
config_t *c;
@@ -221,7 +208,6 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
- config->Function = function;
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) {
@@ -235,14 +221,22 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
config->AssignedIRQ = s->irq.AssignedIRQ;
if (config->AssignedIRQ)
config->Attributes |= CONF_ENABLE_IRQ;
- config->BasePort1 = s->io[0].BasePort;
- config->NumPorts1 = s->io[0].NumPorts;
+ if (s->io[0].res) {
+ config->BasePort1 = s->io[0].res->start;
+ config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
+ }
}
return CS_SUCCESS;
}
#endif
- c = (s->config != NULL) ? &s->config[function] : NULL;
+ if (p_dev) {
+ c = p_dev->function_config;
+ config->Function = p_dev->func;
+ } else {
+ c = NULL;
+ config->Function = 0;
+ }
if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
config->Attributes = 0;
@@ -271,7 +265,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
config_info_t *config)
{
- return pccard_get_configuration_info(p_dev->socket, p_dev->func,
+ return pccard_get_configuration_info(p_dev->socket, p_dev,
config);
}
EXPORT_SYMBOL(pcmcia_get_configuration_info);
@@ -317,7 +311,7 @@ EXPORT_SYMBOL(pcmcia_get_window);
* SocketState yet: I haven't seen any point for it.
*/
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev,
cs_status_t *status)
{
config_t *c;
@@ -334,11 +328,12 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
- c = (s->config != NULL) ? &s->config[function] : NULL;
+ c = (p_dev) ? p_dev->function_config : NULL;
+
if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
(c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
u_char reg;
- if (c->Present & PRESENT_PIN_REPLACE) {
+ if (c->CardValues & PRESENT_PIN_REPLACE) {
pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
status->CardState |=
(reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
@@ -352,7 +347,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
/* No PRR? Then assume we're always ready */
status->CardState |= CS_EVENT_READY_CHANGE;
}
- if (c->Present & PRESENT_EXT_STATUS) {
+ if (c->CardValues & PRESENT_EXT_STATUS) {
pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
status->CardState |=
(reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
@@ -370,11 +365,9 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
return CS_SUCCESS;
} /* pccard_get_status */
-int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
+int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status)
{
- struct pcmcia_socket *s;
- s = SOCKET(handle);
- return pccard_get_status(s, handle->func, status);
+ return pccard_get_status(p_dev->socket, p_dev, status);
}
EXPORT_SYMBOL(pcmcia_get_status);
@@ -422,7 +415,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
config_t *c;
s = p_dev->socket;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
+
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (!(c->state & CONFIG_LOCKED))
@@ -454,6 +448,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
(mod->Attributes & CONF_VPP2_CHANGE_VALID))
return CS_BAD_VPP;
+ if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
+ pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+ pccard_io_map io_on;
+ int i;
+
+ io_on.speed = io_speed;
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (!s->io[i].res)
+ continue;
+ io_off.map = i;
+ io_on.map = i;
+
+ io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+ io_on.start = s->io[i].res->start;
+ io_on.stop = s->io[i].res->end;
+
+ s->ops->set_io_map(s, &io_off);
+ mdelay(40);
+ s->ops->set_io_map(s, &io_on);
+ }
+ }
+
return CS_SUCCESS;
} /* modify_configuration */
EXPORT_SYMBOL(pcmcia_modify_configuration);
@@ -463,23 +479,23 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
{
pccard_io_map io = { 0, 0, 0, 0, 1 };
struct pcmcia_socket *s = p_dev->socket;
+ config_t *c = p_dev->function_config;
int i;
- if (!(p_dev->state & CLIENT_CONFIG_LOCKED))
- return CS_BAD_HANDLE;
- p_dev->state &= ~CLIENT_CONFIG_LOCKED;
-
- if (!(p_dev->state & CLIENT_STALE)) {
- config_t *c = CONFIG(p_dev);
+ if (p_dev->_locked) {
+ p_dev->_locked = 0;
if (--(s->lock_count) == 0) {
s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
s->socket.Vpp = 0;
s->socket.io_irq = 0;
s->ops->set_socket(s, &s->socket);
}
+ }
+ if (c->state & CONFIG_LOCKED) {
+ c->state &= ~CONFIG_LOCKED;
if (c->state & CONFIG_IO_REQ)
for (i = 0; i < MAX_IO_WIN; i++) {
- if (s->io[i].NumPorts == 0)
+ if (!s->io[i].res)
continue;
s->io[i].Config--;
if (s->io[i].Config != 0)
@@ -487,12 +503,10 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
io.map = i;
s->ops->set_io_map(s, &io);
}
- c->state &= ~CONFIG_LOCKED;
}
return CS_SUCCESS;
} /* pcmcia_release_configuration */
-EXPORT_SYMBOL(pcmcia_release_configuration);
/** pcmcia_release_io
@@ -503,25 +517,23 @@ EXPORT_SYMBOL(pcmcia_release_configuration);
* don't bother checking the port ranges against the current socket
* values.
*/
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
+static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
{
struct pcmcia_socket *s = p_dev->socket;
+ config_t *c = p_dev->function_config;
- if (!(p_dev->state & CLIENT_IO_REQ))
+ if (!p_dev->_io )
return CS_BAD_HANDLE;
- p_dev->state &= ~CLIENT_IO_REQ;
-
- if (!(p_dev->state & CLIENT_STALE)) {
- config_t *c = CONFIG(p_dev);
- if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if ((c->io.BasePort1 != req->BasePort1) ||
- (c->io.NumPorts1 != req->NumPorts1) ||
- (c->io.BasePort2 != req->BasePort2) ||
- (c->io.NumPorts2 != req->NumPorts2))
- return CS_BAD_ARGS;
- c->state &= ~CONFIG_IO_REQ;
- }
+
+ p_dev->_io = 0;
+
+ if ((c->io.BasePort1 != req->BasePort1) ||
+ (c->io.NumPorts1 != req->NumPorts1) ||
+ (c->io.BasePort2 != req->BasePort2) ||
+ (c->io.NumPorts2 != req->NumPorts2))
+ return CS_BAD_ARGS;
+
+ c->state &= ~CONFIG_IO_REQ;
release_io_space(s, req->BasePort1, req->NumPorts1);
if (req->NumPorts2)
@@ -529,28 +541,26 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
return CS_SUCCESS;
} /* pcmcia_release_io */
-EXPORT_SYMBOL(pcmcia_release_io);
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
+static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
{
struct pcmcia_socket *s = p_dev->socket;
- if (!(p_dev->state & CLIENT_IRQ_REQ))
+ config_t *c= p_dev->function_config;
+
+ if (!p_dev->_irq)
return CS_BAD_HANDLE;
- p_dev->state &= ~CLIENT_IRQ_REQ;
-
- if (!(p_dev->state & CLIENT_STALE)) {
- config_t *c = CONFIG(p_dev);
- if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if (c->irq.Attributes != req->Attributes)
- return CS_BAD_ATTRIBUTE;
- if (s->irq.AssignedIRQ != req->AssignedIRQ)
- return CS_BAD_IRQ;
- if (--s->irq.Config == 0) {
- c->state &= ~CONFIG_IRQ_REQ;
- s->irq.AssignedIRQ = 0;
- }
+ p_dev->_irq = 0;
+
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+ if (c->irq.Attributes != req->Attributes)
+ return CS_BAD_ATTRIBUTE;
+ if (s->irq.AssignedIRQ != req->AssignedIRQ)
+ return CS_BAD_IRQ;
+ if (--s->irq.Config == 0) {
+ c->state &= ~CONFIG_IRQ_REQ;
+ s->irq.AssignedIRQ = 0;
}
if (req->Attributes & IRQ_HANDLE_PRESENT) {
@@ -563,7 +573,6 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
return CS_SUCCESS;
} /* pcmcia_release_irq */
-EXPORT_SYMBOL(pcmcia_release_irq);
int pcmcia_release_window(window_handle_t win)
@@ -573,7 +582,7 @@ int pcmcia_release_window(window_handle_t win)
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
return CS_BAD_HANDLE;
s = win->sock;
- if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
+ if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
return CS_BAD_HANDLE;
/* Shut down memory window */
@@ -587,7 +596,7 @@ int pcmcia_release_window(window_handle_t win)
kfree(win->ctl.res);
win->ctl.res = NULL;
}
- win->handle->state &= ~CLIENT_WIN_REQ(win->index);
+ win->handle->_win &= ~CLIENT_WIN_REQ(win->index);
win->magic = 0;
@@ -610,16 +619,12 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
if (req->IntType & INT_CARDBUS)
return CS_UNSUPPORTED_MODE;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
return CS_CONFIGURATION_LOCKED;
/* Do power control. We don't allow changes in Vcc. */
- if (s->socket.Vcc != req->Vcc)
- return CS_BAD_VCC;
- if (req->Vpp1 != req->Vpp2)
- return CS_BAD_VPP;
- s->socket.Vpp = req->Vpp1;
+ s->socket.Vpp = req->Vpp;
if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
@@ -643,7 +648,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
/* Set up CIS configuration registers */
base = c->ConfigBase = req->ConfigBase;
- c->Present = c->CardValues = req->Present;
+ c->CardValues = req->Present;
if (req->Present & PRESENT_COPY) {
c->Copy = req->Copy;
pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
@@ -690,10 +695,10 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
if (c->state & CONFIG_IO_REQ) {
iomap.speed = io_speed;
for (i = 0; i < MAX_IO_WIN; i++)
- if (s->io[i].NumPorts != 0) {
+ if (s->io[i].res) {
iomap.map = i;
iomap.flags = MAP_ACTIVE;
- switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
+ switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
case IO_DATA_PATH_WIDTH_16:
iomap.flags |= MAP_16BIT; break;
case IO_DATA_PATH_WIDTH_AUTO:
@@ -701,15 +706,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
default:
break;
}
- iomap.start = s->io[i].BasePort;
- iomap.stop = iomap.start + s->io[i].NumPorts - 1;
+ iomap.start = s->io[i].res->start;
+ iomap.stop = s->io[i].res->end;
s->ops->set_io_map(s, &iomap);
s->io[i].Config++;
}
}
c->state |= CONFIG_LOCKED;
- p_dev->state |= CLIENT_CONFIG_LOCKED;
+ p_dev->_locked = 1;
return CS_SUCCESS;
} /* pcmcia_request_configuration */
EXPORT_SYMBOL(pcmcia_request_configuration);
@@ -730,7 +735,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
if (!req)
return CS_UNSUPPORTED_MODE;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
return CS_CONFIGURATION_LOCKED;
if (c->state & CONFIG_IO_REQ)
@@ -755,7 +760,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
c->io = *req;
c->state |= CONFIG_IO_REQ;
- p_dev->state |= CLIENT_IO_REQ;
+ p_dev->_io = 1;
return CS_SUCCESS;
} /* pcmcia_request_io */
EXPORT_SYMBOL(pcmcia_request_io);
@@ -786,7 +791,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
return CS_CONFIGURATION_LOCKED;
if (c->state & CONFIG_IRQ_REQ)
@@ -851,7 +856,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
s->irq.Config++;
c->state |= CONFIG_IRQ_REQ;
- p_dev->state |= CLIENT_IRQ_REQ;
+ p_dev->_irq = 1;
#ifdef CONFIG_PCMCIA_PROBE
pcmcia_used_irq[irq]++;
@@ -911,7 +916,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
if (!win->ctl.res)
return CS_IN_USE;
}
- (*p_dev)->state |= CLIENT_WIN_REQ(w);
+ (*p_dev)->_win |= CLIENT_WIN_REQ(w);
/* Configure the socket controller */
win->ctl.map = w+1;
@@ -941,3 +946,12 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
return CS_SUCCESS;
} /* pcmcia_request_window */
EXPORT_SYMBOL(pcmcia_request_window);
+
+void pcmcia_disable_device(struct pcmcia_device *p_dev) {
+ pcmcia_release_configuration(p_dev);
+ pcmcia_release_io(p_dev, &p_dev->io);
+ pcmcia_release_irq(p_dev, &p_dev->irq);
+ if (&p_dev->win)
+ pcmcia_release_window(p_dev->win);
+}
+EXPORT_SYMBOL(pcmcia_disable_device);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index f2789afb22b2..16d1ea7b0a18 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -8,7 +8,6 @@
*/
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index fd3647368955..b7b9e149c5b9 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -26,14 +26,6 @@
#include "soc_common.h"
#define NO_KEEP_VS 0x0001
-
-/* PCMCIA to Scoop linkage
-
- There is no easy way to link multiple scoop devices into one
- single entity for the pxa2xx_pcmcia device so this structure
- is used which is setup by the platform code
-*/
-struct scoop_pcmcia_config *platform_scoop_config;
#define SCOOP_DEV platform_scoop_config->devs
static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 514609369836..81dfc2cac2b4 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -12,7 +12,6 @@
* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -22,6 +21,8 @@
#include "cs_internal.h"
+#ifdef CONFIG_PCMCIA_IOCTL
+
#ifdef CONFIG_PCMCIA_PROBE
static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
@@ -98,6 +99,8 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
}
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
+#endif
+
int pcmcia_validate_mem(struct pcmcia_socket *s)
{
if (s->resource_ops->validate_mem)
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 5301ac60358f..0f8b157c9717 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -12,7 +12,6 @@
* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -61,7 +60,7 @@ struct socket_data {
unsigned int rsrc_mem_probe;
};
-static DECLARE_MUTEX(rsrc_sem);
+static DEFINE_MUTEX(rsrc_mutex);
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
@@ -484,7 +483,7 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
/*
- * Locking note: Must be called with skt_sem held!
+ * Locking note: Must be called with skt_mutex held!
*/
static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
{
@@ -495,7 +494,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
if (!probe_mem)
return 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
@@ -507,7 +506,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
s_data->rsrc_mem_probe |= probe_mask;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -585,7 +584,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
struct socket_data *s_data = s->resource_data;
int ret = -ENOMEM;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
unsigned long start = m->base;
unsigned long end = m->base + m->num - 1;
@@ -596,7 +595,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
ret = adjust_resource(res, r_start, r_end - r_start + 1);
break;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -630,7 +629,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
data.offset = base & data.mask;
data.map = &s_data->io_db;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -639,7 +638,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
#endif
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
1, pcmcia_align, &data);
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
if (ret != 0) {
kfree(res);
@@ -672,7 +671,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
min = 0x100000UL + base;
}
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -682,7 +681,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
#endif
ret = allocate_resource(&iomem_resource, res, num, min,
max, 1, pcmcia_align, &data);
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
if (ret == 0 || low)
break;
low = 1;
@@ -705,7 +704,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
if (end < start)
return -EINVAL;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
ret = add_interval(&data->mem_db, start, size);
@@ -723,7 +722,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
default:
ret = -EINVAL;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -741,7 +740,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
if (end > IO_SPACE_LIMIT)
return -EINVAL;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
if (add_interval(&data->io_db, start, size) != 0) {
@@ -760,7 +759,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
ret = -EINVAL;
break;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -867,7 +866,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
struct socket_data *data = s->resource_data;
struct resource_map *p, *q;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
for (p = data->mem_db.next; p != &data->mem_db; p = q) {
q = p->next;
kfree(p);
@@ -876,7 +875,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
q = p->next;
kfree(p);
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
}
@@ -901,7 +900,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
struct resource_map *p;
ssize_t ret = 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
data = s->resource_data;
for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -913,7 +912,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
((unsigned long) p->base + p->num - 1));
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return (ret);
}
@@ -953,7 +952,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
struct resource_map *p;
ssize_t ret = 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
data = s->resource_data;
for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -965,7 +964,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
((unsigned long) p->base + p->num - 1));
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return (ret);
}
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index 2b3c2895b43d..eb89928f2338 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -5,7 +5,6 @@
* Based off the Assabet.
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 5ab1cdef7c48..c5d7476da471 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -12,7 +12,6 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -25,6 +24,7 @@
#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include <asm/system.h>
#include <asm/irq.h>
@@ -183,7 +183,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
s->resource_setup_done = 1;
spin_unlock_irqrestore(&s->lock, flags);
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
if ((s->callback) &&
(s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_CARDBUS)) {
@@ -192,7 +192,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
module_put(s->callback->owner);
}
}
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
return count;
}
@@ -322,7 +322,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
kfree(cis);
if (!ret) {
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
if ((s->callback) && (s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_CARDBUS)) {
if (try_module_get(s->callback->owner)) {
@@ -330,7 +330,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
module_put(s->callback->owner);
}
}
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
}
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index d5b4ff74462e..7a3d1b8e16b9 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -30,7 +30,6 @@
#ifndef _LINUX_TI113X_H
#define _LINUX_TI113X_H
-#include <linux/config.h>
/* Register definitions for TI 113X PCI-to-CardBus bridges */
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index c4256aa32bcb..6fff109bdab6 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -479,7 +479,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int pnp_start_dev(struct pnp_dev *dev)
{
if (!pnp_can_write(dev)) {
- pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+ pnp_info("Device %s does not support activation.", dev->dev.bus_id);
return -EINVAL;
}
@@ -503,7 +503,7 @@ int pnp_start_dev(struct pnp_dev *dev)
int pnp_stop_dev(struct pnp_dev *dev)
{
if (!pnp_can_disable(dev)) {
- pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+ pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
return -EINVAL;
}
if (dev->protocol->disable(dev)<0) {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 929dd8090578..65d090dbef46 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -147,6 +147,16 @@ config RTC_DRV_SA1100
To compile this driver as a module, choose M here: the
module will be called rtc-sa1100.
+config RTC_DRV_VR41XX
+ tristate "NEC VR41XX"
+ depends on RTC_CLASS && CPU_VR41XX
+ help
+ If you say Y here you will get access to the real time clock
+ built into your NEC VR41XX CPU.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-vr41xx.
+
config RTC_DRV_TEST
tristate "Test driver/device"
depends on RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 8d4c7fe88d58..a9ca0f171686 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
+obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 8533936d50d8..413c7d54ea10 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -96,6 +96,8 @@ exit_idr:
idr_remove(&rtc_idr, id);
exit:
+ dev_err(dev, "rtc core: unable to register %s, err = %d\n",
+ name, err);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(rtc_device_register);
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 358695a416f3..9be81fd4737c 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -1,6 +1,8 @@
/*
* An rtc/i2c driver for the Dallas DS1672
- * Copyright 2005 Alessandro Zummo
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
*
* 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
@@ -11,7 +13,7 @@
#include <linux/i2c.h>
#include <linux/rtc.h>
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "0.3"
/* Addresses to scan: none. This chip cannot be detected. */
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
@@ -25,6 +27,7 @@ I2C_CLIENT_INSMOD;
#define DS1672_REG_CONTROL 4
#define DS1672_REG_TRICKLE 5
+#define DS1672_REG_CONTROL_EOSC 0x80
/* Prototypes */
static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
@@ -53,8 +56,7 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
dev_dbg(&client->dev,
"%s: raw read data - counters=%02x,%02x,%02x,%02x\n"
- __FUNCTION__,
- buf[0], buf[1], buf[2], buf[3]);
+ __FUNCTION__, buf[0], buf[1], buf[2], buf[3]);
time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
@@ -62,8 +64,7 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
- __FUNCTION__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
+ __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
return 0;
@@ -72,16 +73,17 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
{
int xfer;
- unsigned char buf[5];
+ unsigned char buf[6];
buf[0] = DS1672_REG_CNT_BASE;
buf[1] = secs & 0x000000FF;
buf[2] = (secs & 0x0000FF00) >> 8;
buf[3] = (secs & 0x00FF0000) >> 16;
buf[4] = (secs & 0xFF000000) >> 24;
+ buf[5] = 0; /* set control reg to enable counting */
- xfer = i2c_master_send(client, buf, 5);
- if (xfer != 5) {
+ xfer = i2c_master_send(client, buf, 6);
+ if (xfer != 6) {
dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
return -EIO;
}
@@ -120,6 +122,40 @@ static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs)
return ds1672_set_mmss(to_i2c_client(dev), secs);
}
+static int ds1672_get_control(struct i2c_client *client, u8 *status)
+{
+ unsigned char addr = DS1672_REG_CONTROL;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, status }, /* read control */
+ };
+
+ /* read control register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 control;
+ int err;
+
+ err = ds1672_get_control(client, &control);
+ if (err)
+ return err;
+
+ return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
+ ? "disabled" : "enabled");
+}
+static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
+
static struct rtc_class_ops ds1672_rtc_ops = {
.read_time = ds1672_rtc_read_time,
.set_time = ds1672_rtc_set_time,
@@ -128,7 +164,6 @@ static struct rtc_class_ops ds1672_rtc_ops = {
static int ds1672_attach(struct i2c_adapter *adapter)
{
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
return i2c_probe(adapter, &addr_data, ds1672_probe);
}
@@ -137,8 +172,6 @@ static int ds1672_detach(struct i2c_client *client)
int err;
struct rtc_device *rtc = i2c_get_clientdata(client);
- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
if (rtc)
rtc_device_unregister(rtc);
@@ -162,6 +195,7 @@ static struct i2c_driver ds1672_driver = {
static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
{
int err = 0;
+ u8 control;
struct i2c_client *client;
struct rtc_device *rtc;
@@ -195,13 +229,23 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
if (IS_ERR(rtc)) {
err = PTR_ERR(rtc);
- dev_err(&client->dev,
- "unable to register the class device\n");
goto exit_detach;
}
i2c_set_clientdata(client, rtc);
+ /* read control register */
+ err = ds1672_get_control(client, &control);
+ if (err)
+ goto exit_detach;
+
+ if (control & DS1672_REG_CONTROL_EOSC)
+ dev_warn(&client->dev, "Oscillator not enabled. "
+ "Set time to enable.\n");
+
+ /* Register sysfs hooks */
+ device_create_file(&client->dev, &dev_attr_control);
+
return 0;
exit_detach:
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 0dd80ea686a9..e1a1169e4664 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -67,7 +67,6 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
ep93xx_get_swcomp(dev, &preload, &delete);
- seq_printf(seq, "24hr\t\t: yes\n");
seq_printf(seq, "preload\t\t: %d\n", preload);
seq_printf(seq, "delete\t\t: %d\n", delete);
@@ -110,7 +109,6 @@ static int __devinit ep93xx_rtc_probe(struct platform_device *dev)
&dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
- dev_err(&dev->dev, "unable to register\n");
return PTR_ERR(rtc);
}
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index db445c872b1b..f6e7ee04f3dc 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -23,7 +23,7 @@
#define M48T86_REG_SECALRM 0x01
#define M48T86_REG_MIN 0x02
#define M48T86_REG_MINALRM 0x03
-#define M48T86_REG_HOUR 0x04
+#define M48T86_REG_HOUR 0x04
#define M48T86_REG_HOURALRM 0x05
#define M48T86_REG_DOW 0x06 /* 1 = sunday */
#define M48T86_REG_DOM 0x07
@@ -127,9 +127,6 @@ static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
reg = ops->readb(M48T86_REG_B);
- seq_printf(seq, "24hr\t\t: %s\n",
- (reg & M48T86_REG_B_H24) ? "yes" : "no");
-
seq_printf(seq, "mode\t\t: %s\n",
(reg & M48T86_REG_B_DM) ? "binary" : "bcd");
@@ -154,10 +151,8 @@ static int __devinit m48t86_rtc_probe(struct platform_device *dev)
struct rtc_device *rtc = rtc_device_register("m48t86",
&dev->dev, &m48t86_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- dev_err(&dev->dev, "unable to register\n");
+ if (IS_ERR(rtc))
return PTR_ERR(rtc);
- }
platform_set_drvdata(dev, rtc);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index d857d45bdbe8..ba9a583b7b68 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -227,14 +227,7 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
return pcf8563_set_datetime(to_i2c_client(dev), tm);
}
-static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq)
-{
- seq_printf(seq, "24hr\t\t: yes\n");
- return 0;
-}
-
static struct rtc_class_ops pcf8563_rtc_ops = {
- .proc = pcf8563_rtc_proc,
.read_time = pcf8563_rtc_read_time,
.set_time = pcf8563_rtc_set_time,
};
@@ -297,8 +290,6 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
if (IS_ERR(rtc)) {
err = PTR_ERR(rtc);
- dev_err(&client->dev,
- "unable to register the class device\n");
goto exit_detach;
}
@@ -321,8 +312,6 @@ static int pcf8563_detach(struct i2c_client *client)
int err;
struct rtc_device *rtc = i2c_get_clientdata(client);
- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
if (rtc)
rtc_device_unregister(rtc);
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index 90b8a97a0919..cef5f5a3bbf9 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -71,6 +71,8 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
alrm.pending ? "yes" : "no");
}
+ seq_printf(seq, "24hr\t\t: yes\n");
+
if (ops->proc)
ops->proc(class_dev->dev, seq);
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 396c8681f66c..7553d797603f 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -151,9 +151,8 @@ static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
{
int err, osc, trim;
- seq_printf(seq, "24hr\t\t: yes\n");
-
- if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) {
+ err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim);
+ if (err == 0) {
seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000);
seq_printf(seq, "trim\t: %d\n", trim);
}
@@ -170,30 +169,31 @@ static struct rtc_class_ops rs5c372_rtc_ops = {
static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int trim;
+ int err, trim;
- if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0)
- return sprintf(buf, "0x%2x\n", trim);
+ err = rs5c372_get_trim(to_i2c_client(dev), NULL, &trim);
+ if (err)
+ return err;
- return 0;
+ return sprintf(buf, "0x%2x\n", trim);
}
static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL);
static ssize_t rs5c372_sysfs_show_osc(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int osc;
+ int err, osc;
- if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0)
- return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+ err = rs5c372_get_trim(to_i2c_client(dev), &osc, NULL);
+ if (err)
+ return err;
- return 0;
+ return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
}
static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL);
static int rs5c372_attach(struct i2c_adapter *adapter)
{
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
return i2c_probe(adapter, &addr_data, rs5c372_probe);
}
@@ -233,8 +233,6 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
if (IS_ERR(rtc)) {
err = PTR_ERR(rtc);
- dev_err(&client->dev,
- "unable to register the class device\n");
goto exit_detach;
}
@@ -260,8 +258,6 @@ static int rs5c372_detach(struct i2c_client *client)
int err;
struct rtc_device *rtc = i2c_get_clientdata(client);
- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
if (rtc)
rtc_device_unregister(rtc);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 83b2bb480a16..a23ec54989f6 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -160,19 +160,19 @@ static int sa1100_rtc_open(struct device *dev)
ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT,
"rtc 1Hz", dev);
if (ret) {
- printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
goto fail_ui;
}
ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT,
"rtc Alrm", dev);
if (ret) {
- printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
goto fail_ai;
}
ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT,
"rtc timer", dev);
if (ret) {
- printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
goto fail_pi;
}
return 0;
@@ -332,7 +332,7 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
*/
if (RTTR == 0) {
RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
- printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
+ dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
/* The current RTC value probably doesn't make sense either */
RCNR = 0;
}
@@ -340,15 +340,11 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
THIS_MODULE);
- if (IS_ERR(rtc)) {
- dev_err(&pdev->dev, "Unable to register the RTC device\n");
+ if (IS_ERR(rtc))
return PTR_ERR(rtc);
- }
platform_set_drvdata(pdev, rtc);
- dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n");
-
return 0;
}
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index 43d107487820..e1f7e8e86daf 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -49,7 +49,6 @@ static int test_rtc_proc(struct device *dev, struct seq_file *seq)
{
struct platform_device *plat_dev = to_platform_device(dev);
- seq_printf(seq, "24hr\t\t: yes\n");
seq_printf(seq, "test\t\t: yes\n");
seq_printf(seq, "id\t\t: %d\n", plat_dev->id);
@@ -120,8 +119,6 @@ static int test_probe(struct platform_device *plat_dev)
&test_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
err = PTR_ERR(rtc);
- dev_err(&plat_dev->dev,
- "unable to register the class device\n");
return err;
}
device_create_file(&plat_dev->dev, &dev_attr_irq);
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/rtc/rtc-vr41xx.c
index b109d9a502d6..4d49fd501198 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -1,7 +1,7 @@
/*
- * Driver for NEC VR4100 series Real Time Clock unit.
+ * Driver for NEC VR4100 series Real Time Clock unit.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2006 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
@@ -17,23 +17,18 @@
* 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/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irq.h>
-#include <linux/mc146818rtc.h>
-#include <linux/miscdevice.h>
#include <linux/module.h>
-#include <linux/poll.h>
+#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <linux/wait.h>
#include <asm/div64.h>
#include <asm/io.h>
-#include <asm/time.h>
#include <asm/uaccess.h>
#include <asm/vr41xx/vr41xx.h>
@@ -99,27 +94,11 @@ static void __iomem *rtc2_base;
static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
-static spinlock_t rtc_task_lock;
-static wait_queue_head_t rtc_wait;
-static unsigned long rtc_irq_data;
-static struct fasync_struct *rtc_async_queue;
-static rtc_task_t *rtc_callback;
+static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
static char rtc_name[] = "RTC";
static unsigned long periodic_frequency;
static unsigned long periodic_count;
-typedef enum {
- RTC_RELEASE,
- RTC_OPEN,
-} rtc_status_t;
-
-static rtc_status_t rtc_status;
-
-typedef enum {
- FUNCTION_RTC_IOCTL,
- FUNCTION_RTC_CONTROL,
-} rtc_callfrom_t;
-
struct resource rtc_resource[2] = {
{ .name = rtc_name,
.flags = IORESOURCE_MEM, },
@@ -129,7 +108,9 @@ struct resource rtc_resource[2] = {
static inline unsigned long read_elapsed_second(void)
{
+
unsigned long first_low, first_mid, first_high;
+
unsigned long second_low, second_mid, second_high;
do {
@@ -156,50 +137,36 @@ static inline void write_elapsed_second(unsigned long sec)
spin_unlock_irq(&rtc_lock);
}
-static void set_alarm(struct rtc_time *time)
+static void vr41xx_rtc_release(struct device *dev)
{
- unsigned long alarm_sec;
-
- alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
- time->tm_hour, time->tm_min, time->tm_sec);
-
- spin_lock_irq(&rtc_lock);
-
- rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
- rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
- rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
-
- spin_unlock_irq(&rtc_lock);
-}
-
-static void read_alarm(struct rtc_time *time)
-{
- unsigned long low, mid, high;
spin_lock_irq(&rtc_lock);
- low = rtc1_read(ECMPLREG);
- mid = rtc1_read(ECMPMREG);
- high = rtc1_read(ECMPHREG);
+ rtc1_write(ECMPLREG, 0);
+ rtc1_write(ECMPMREG, 0);
+ rtc1_write(ECMPHREG, 0);
+ rtc1_write(RTCL1LREG, 0);
+ rtc1_write(RTCL1HREG, 0);
spin_unlock_irq(&rtc_lock);
- to_tm((high << 17) | (mid << 1) | (low >> 15), time);
- time->tm_year -= 1900;
+ disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(RTCLONG1_IRQ);
}
-static void read_time(struct rtc_time *time)
+static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
{
unsigned long epoch_sec, elapsed_sec;
epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
elapsed_sec = read_elapsed_second();
- to_tm(epoch_sec + elapsed_sec, time);
- time->tm_year -= 1900;
+ rtc_time_to_tm(epoch_sec + elapsed_sec, time);
+
+ return 0;
}
-static void set_time(struct rtc_time *time)
+static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
{
unsigned long epoch_sec, current_sec;
@@ -208,73 +175,49 @@ static void set_time(struct rtc_time *time)
time->tm_hour, time->tm_min, time->tm_sec);
write_elapsed_second(current_sec - epoch_sec);
+
+ return 0;
}
-static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long irq_data;
- int retval = 0;
-
- if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
- return -EINVAL;
-
- add_wait_queue(&rtc_wait, &wait);
-
- do {
- __set_current_state(TASK_INTERRUPTIBLE);
+ unsigned long low, mid, high;
+ struct rtc_time *time = &wkalrm->time;
- spin_lock_irq(&rtc_lock);
- irq_data = rtc_irq_data;
- rtc_irq_data = 0;
- spin_unlock_irq(&rtc_lock);
+ spin_lock_irq(&rtc_lock);
- if (irq_data != 0)
- break;
+ low = rtc1_read(ECMPLREG);
+ mid = rtc1_read(ECMPMREG);
+ high = rtc1_read(ECMPHREG);
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
+ spin_unlock_irq(&rtc_lock);
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- } while (1);
+ rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
- if (retval == 0) {
- if (count == sizeof(unsigned int)) {
- retval = put_user(irq_data, (unsigned int __user *)buf);
- if (retval == 0)
- retval = sizeof(unsigned int);
- } else {
- retval = put_user(irq_data, (unsigned long __user *)buf);
- if (retval == 0)
- retval = sizeof(unsigned long);
- }
+ return 0;
+}
- }
+static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ unsigned long alarm_sec;
+ struct rtc_time *time = &wkalrm->time;
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&rtc_wait, &wait);
+ alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
- return retval;
-}
+ spin_lock_irq(&rtc_lock);
-static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table)
-{
- poll_wait(file, &rtc_wait, table);
+ 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 (rtc_irq_data != 0)
- return POLLIN | POLLRDNORM;
+ spin_unlock_irq(&rtc_lock);
return 0;
}
-static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from)
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- struct rtc_time time;
unsigned long count;
switch (cmd) {
@@ -290,33 +233,6 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
case RTC_PIE_OFF:
disable_irq(RTCLONG1_IRQ);
break;
- case RTC_ALM_SET:
- if (copy_from_user(&time, (struct rtc_time __user *)arg,
- sizeof(struct rtc_time)))
- return -EFAULT;
-
- set_alarm(&time);
- break;
- case RTC_ALM_READ:
- memset(&time, 0, sizeof(struct rtc_time));
- read_alarm(&time);
- break;
- case RTC_RD_TIME:
- memset(&time, 0, sizeof(struct rtc_time));
- read_time(&time);
- if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time)))
- return -EFAULT;
- break;
- case RTC_SET_TIME:
- if (capable(CAP_SYS_TIME) == 0)
- return -EACCES;
-
- if (copy_from_user(&time, (struct rtc_time __user *)arg,
- sizeof(struct rtc_time)))
- return -EFAULT;
-
- set_time(&time);
- break;
case RTC_IRQP_READ:
return put_user(periodic_frequency, (unsigned long __user *)arg);
break;
@@ -324,8 +240,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
if (arg > MAX_PERIODIC_RATE)
return -EINVAL;
- if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE &&
- capable(CAP_SYS_RESOURCE) == 0)
+ if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
return -EACCES;
periodic_frequency = arg;
@@ -361,205 +276,46 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
return 0;
}
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL);
-}
-
-static int rtc_open(struct inode *inode, struct file *file)
-{
- spin_lock_irq(&rtc_lock);
-
- if (rtc_status == RTC_OPEN) {
- spin_unlock_irq(&rtc_lock);
- return -EBUSY;
- }
-
- rtc_status = RTC_OPEN;
- rtc_irq_data = 0;
-
- spin_unlock_irq(&rtc_lock);
-
- return 0;
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
- if (file->f_flags & FASYNC)
- (void)fasync_helper(-1, file, 0, &rtc_async_queue);
-
- spin_lock_irq(&rtc_lock);
-
- rtc1_write(ECMPLREG, 0);
- rtc1_write(ECMPMREG, 0);
- rtc1_write(ECMPHREG, 0);
- rtc1_write(RTCL1LREG, 0);
- rtc1_write(RTCL1HREG, 0);
-
- rtc_status = RTC_RELEASE;
-
- spin_unlock_irq(&rtc_lock);
-
- disable_irq(ELAPSEDTIME_IRQ);
- disable_irq(RTCLONG1_IRQ);
-
- return 0;
-}
-
-static int rtc_fasync(int fd, struct file *file, int on)
-{
- return fasync_helper(fd, file, on, &rtc_async_queue);
-}
-
-static struct file_operations rtc_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = rtc_read,
- .poll = rtc_poll,
- .ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
- .fasync = rtc_fasync,
-};
-
static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- spin_lock(&rtc_lock);
- rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
-
- rtc_irq_data += 0x100;
- rtc_irq_data &= ~0xff;
- rtc_irq_data |= RTC_AF;
- spin_unlock(&rtc_lock);
+ struct platform_device *pdev = (struct platform_device *)dev_id;
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
- spin_lock(&rtc_lock);
- if (rtc_callback)
- rtc_callback->func(rtc_callback->private_data);
- spin_unlock(&rtc_lock);
-
- wake_up_interruptible(&rtc_wait);
+ rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
- kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+ rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
return IRQ_HANDLED;
}
static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct platform_device *pdev = (struct platform_device *)dev_id;
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
unsigned long count = periodic_count;
- spin_lock(&rtc_lock);
rtc2_write(RTCINTREG, RTCLONG1_INT);
rtc1_write(RTCL1LREG, count);
rtc1_write(RTCL1HREG, count >> 16);
- rtc_irq_data += 0x100;
- rtc_irq_data &= ~0xff;
- rtc_irq_data |= RTC_PF;
- spin_unlock(&rtc_lock);
-
- spin_lock(&rtc_task_lock);
- if (rtc_callback)
- rtc_callback->func(rtc_callback->private_data);
- spin_unlock(&rtc_task_lock);
-
- wake_up_interruptible(&rtc_wait);
-
- kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+ rtc_update_irq(&rtc->class_dev, 1, RTC_PF);
return IRQ_HANDLED;
}
-int rtc_register(rtc_task_t *task)
-{
- if (task == NULL || task->func == NULL)
- return -EINVAL;
-
- spin_lock_irq(&rtc_lock);
- if (rtc_status == RTC_OPEN) {
- spin_unlock_irq(&rtc_lock);
- return -EBUSY;
- }
-
- spin_lock(&rtc_task_lock);
- if (rtc_callback != NULL) {
- spin_unlock(&rtc_task_lock);
- spin_unlock_irq(&rtc_task_lock);
- return -EBUSY;
- }
-
- rtc_callback = task;
- spin_unlock(&rtc_task_lock);
-
- rtc_status = RTC_OPEN;
-
- spin_unlock_irq(&rtc_lock);
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_register);
-
-int rtc_unregister(rtc_task_t *task)
-{
- spin_lock_irq(&rtc_task_lock);
- if (task == NULL || rtc_callback != task) {
- spin_unlock_irq(&rtc_task_lock);
- return -ENXIO;
- }
-
- spin_lock(&rtc_lock);
-
- rtc1_write(ECMPLREG, 0);
- rtc1_write(ECMPMREG, 0);
- rtc1_write(ECMPHREG, 0);
- rtc1_write(RTCL1LREG, 0);
- rtc1_write(RTCL1HREG, 0);
-
- rtc_status = RTC_RELEASE;
-
- spin_unlock(&rtc_lock);
-
- rtc_callback = NULL;
-
- spin_unlock_irq(&rtc_task_lock);
-
- disable_irq(ELAPSEDTIME_IRQ);
- disable_irq(RTCLONG1_IRQ);
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_unregister);
-
-int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
-
- spin_lock_irq(&rtc_task_lock);
-
- if (rtc_callback != task)
- retval = -ENXIO;
- else
- rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL);
-
- spin_unlock_irq(&rtc_task_lock);
-
- return retval;
-}
-
-EXPORT_SYMBOL_GPL(rtc_control);
-
-static struct miscdevice rtc_miscdevice = {
- .minor = RTC_MINOR,
- .name = rtc_name,
- .fops = &rtc_fops,
+static struct rtc_class_ops vr41xx_rtc_ops = {
+ .release = vr41xx_rtc_release,
+ .ioctl = vr41xx_rtc_ioctl,
+ .read_time = vr41xx_rtc_read_time,
+ .set_time = vr41xx_rtc_set_time,
+ .read_alarm = vr41xx_rtc_read_alarm,
+ .set_alarm = vr41xx_rtc_set_alarm,
};
static int __devinit rtc_probe(struct platform_device *pdev)
{
+ struct rtc_device *rtc;
unsigned int irq;
int retval;
@@ -577,13 +333,13 @@ static int __devinit rtc_probe(struct platform_device *pdev)
return -EBUSY;
}
- retval = misc_register(&rtc_miscdevice);
- if (retval < 0) {
+ 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 retval;
+ return PTR_ERR(rtc);
}
spin_lock_irq(&rtc_lock);
@@ -594,24 +350,20 @@ static int __devinit rtc_probe(struct platform_device *pdev)
rtc1_write(RTCL1LREG, 0);
rtc1_write(RTCL1HREG, 0);
- rtc_status = RTC_RELEASE;
- rtc_irq_data = 0;
-
spin_unlock_irq(&rtc_lock);
- init_waitqueue_head(&rtc_wait);
-
irq = ELAPSEDTIME_IRQ;
retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
- "elapsed_time", NULL);
+ "elapsed_time", pdev);
if (retval == 0) {
irq = RTCLONG1_IRQ;
retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
- "rtclong1", NULL);
+ "rtclong1", pdev);
}
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);
@@ -621,23 +373,25 @@ static int __devinit rtc_probe(struct platform_device *pdev)
return retval;
}
+ platform_set_drvdata(pdev, rtc);
+
disable_irq(ELAPSEDTIME_IRQ);
disable_irq(RTCLONG1_IRQ);
- spin_lock_init(&rtc_task_lock);
-
printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
return 0;
}
-static int __devexit rtc_remove(struct platform_device *dev)
+static int __devexit rtc_remove(struct platform_device *pdev)
{
- int retval;
+ struct rtc_device *rtc;
- retval = misc_deregister(&rtc_miscdevice);
- if (retval < 0)
- return retval;
+ rtc = platform_get_drvdata(pdev);
+ if (rtc != NULL)
+ rtc_device_unregister(rtc);
+
+ platform_set_drvdata(pdev, NULL);
free_irq(ELAPSEDTIME_IRQ, NULL);
free_irq(RTCLONG1_IRQ, NULL);
@@ -651,7 +405,7 @@ static int __devexit rtc_remove(struct platform_device *dev)
static struct platform_device *rtc_platform_device;
-static struct platform_driver rtc_device_driver = {
+static struct platform_driver rtc_platform_driver = {
.probe = rtc_probe,
.remove = __devexit_p(rtc_remove),
.driver = {
@@ -686,7 +440,7 @@ static int __init vr41xx_rtc_init(void)
}
rtc_platform_device = platform_device_alloc("RTC", -1);
- if (!rtc_platform_device)
+ if (rtc_platform_device == NULL)
return -ENOMEM;
retval = platform_device_add_resources(rtc_platform_device,
@@ -700,7 +454,7 @@ static int __init vr41xx_rtc_init(void)
return retval;
}
- retval = platform_driver_register(&rtc_device_driver);
+ retval = platform_driver_register(&rtc_platform_driver);
if (retval < 0)
platform_device_unregister(rtc_platform_device);
@@ -709,7 +463,7 @@ static int __init vr41xx_rtc_init(void)
static void __exit vr41xx_rtc_exit(void)
{
- platform_driver_unregister(&rtc_device_driver);
+ platform_driver_unregister(&rtc_platform_driver);
platform_device_unregister(rtc_platform_device);
}
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 621d17afc0d9..788b6d1f8f2f 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -19,7 +19,7 @@
#include <linux/rtc.h>
#include <linux/delay.h>
-#define DRV_VERSION "1.0.6"
+#define DRV_VERSION "1.0.7"
/* Addresses to scan: none. This chip is located at
* 0x6f and uses a two bytes register addressing.
@@ -451,8 +451,6 @@ static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
{
int err, dtrim, atrim;
- seq_printf(seq, "24hr\t\t: yes\n");
-
if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
@@ -473,30 +471,31 @@ static struct rtc_class_ops x1205_rtc_ops = {
static ssize_t x1205_sysfs_show_atrim(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int atrim;
+ int err, atrim;
- if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0)
- return sprintf(buf, "%d.%02d pF\n",
- atrim / 1000, atrim % 1000);
- return 0;
+ err = x1205_get_atrim(to_i2c_client(dev), &atrim);
+ if (err)
+ return err;
+
+ return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000);
}
static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int dtrim;
+ int err, dtrim;
- if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0)
- return sprintf(buf, "%d ppm\n", dtrim);
+ err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
+ if (err)
+ return err;
- return 0;
+ return sprintf(buf, "%d ppm\n", dtrim);
}
static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
static int x1205_attach(struct i2c_adapter *adapter)
{
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
return i2c_probe(adapter, &addr_data, x1205_probe);
}
@@ -545,8 +544,6 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
if (IS_ERR(rtc)) {
err = PTR_ERR(rtc);
- dev_err(&client->dev,
- "unable to register the class device\n");
goto exit_detach;
}
@@ -585,8 +582,6 @@ static int x1205_detach(struct i2c_client *client)
int err;
struct rtc_device *rtc = i2c_get_clientdata(client);
- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
if (rtc)
rtc_device_unregister(rtc);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0a9f12c4e911..cfb1fff3787c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -315,6 +315,11 @@ dasd_increase_state(struct dasd_device *device)
rc = dasd_state_basic_to_ready(device);
if (!rc &&
+ device->state == DASD_STATE_UNFMT &&
+ device->target > DASD_STATE_UNFMT)
+ rc = -EPERM;
+
+ if (!rc &&
device->state == DASD_STATE_READY &&
device->target >= DASD_STATE_ONLINE)
rc = dasd_state_ready_to_online(device);
@@ -1257,25 +1262,28 @@ __dasd_start_head(struct dasd_device * device)
if (list_empty(&device->ccw_queue))
return;
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
- /* check FAILFAST */
+ if (cqr->status != DASD_CQR_QUEUED)
+ return;
+ /* Non-temporary stop condition will trigger fail fast */
if (device->stopped & ~DASD_STOPPED_PENDING &&
test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
(!dasd_eer_enabled(device))) {
cqr->status = DASD_CQR_FAILED;
dasd_schedule_bh(device);
+ return;
}
- if ((cqr->status == DASD_CQR_QUEUED) &&
- (!device->stopped)) {
- /* try to start the first I/O that can be started */
- rc = device->discipline->start_IO(cqr);
- if (rc == 0)
- dasd_set_timer(device, cqr->expires);
- else if (rc == -EACCES) {
- dasd_schedule_bh(device);
- } else
- /* Hmpf, try again in 1/2 sec */
- dasd_set_timer(device, 50);
- }
+ /* Don't try to start requests if device is stopped */
+ if (device->stopped)
+ return;
+
+ rc = device->discipline->start_IO(cqr);
+ if (rc == 0)
+ dasd_set_timer(device, cqr->expires);
+ else if (rc == -EACCES) {
+ dasd_schedule_bh(device);
+ } else
+ /* Hmpf, try again in 1/2 sec */
+ dasd_set_timer(device, 50);
}
/*
@@ -1968,7 +1976,7 @@ int
dasd_generic_set_offline (struct ccw_device *cdev)
{
struct dasd_device *device;
- int max_count;
+ int max_count, open_count;
device = dasd_device_from_cdev(cdev);
if (IS_ERR(device))
@@ -1985,10 +1993,16 @@ dasd_generic_set_offline (struct ccw_device *cdev)
* in the other openers.
*/
max_count = device->bdev ? 0 : -1;
- if (atomic_read(&device->open_count) > max_count) {
- printk (KERN_WARNING "Can't offline dasd device with open"
- " count = %i.\n",
- atomic_read(&device->open_count));
+ open_count = (int) atomic_read(&device->open_count);
+ if (open_count > max_count) {
+ if (open_count > 0)
+ printk (KERN_WARNING "Can't offline dasd device with "
+ "open count = %i.\n",
+ open_count);
+ else
+ printk (KERN_WARNING "%s",
+ "Can't offline dasd device due to internal "
+ "use\n");
clear_bit(DASD_FLAG_OFFLINE, &device->flags);
dasd_put_device(device);
return -EBUSY;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index c1c6f1381150..216bc4fba199 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -45,6 +45,7 @@ struct dasd_devmap {
unsigned int devindex;
unsigned short features;
struct dasd_device *device;
+ struct dasd_uid uid;
};
/*
@@ -716,6 +717,68 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *bu
static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
+static ssize_t
+dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ int alias;
+
+ devmap = dasd_find_busid(dev->bus_id);
+ spin_lock(&dasd_devmap_lock);
+ if (!IS_ERR(devmap))
+ alias = devmap->uid.alias;
+ else
+ alias = 0;
+ spin_unlock(&dasd_devmap_lock);
+
+ return sprintf(buf, alias ? "1\n" : "0\n");
+}
+
+static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
+
+static ssize_t
+dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ char *vendor;
+
+ devmap = dasd_find_busid(dev->bus_id);
+ spin_lock(&dasd_devmap_lock);
+ if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
+ vendor = devmap->uid.vendor;
+ else
+ vendor = "";
+ spin_unlock(&dasd_devmap_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
+}
+
+static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
+
+#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
+ /* SSID */ 4 + 1 + /* unit addr */ 2 + 1)
+
+static ssize_t
+dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ char uid[UID_STRLEN];
+
+ devmap = dasd_find_busid(dev->bus_id);
+ spin_lock(&dasd_devmap_lock);
+ if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
+ snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
+ devmap->uid.vendor, devmap->uid.serial,
+ devmap->uid.ssid, devmap->uid.unit_addr);
+ else
+ uid[0] = 0;
+ spin_unlock(&dasd_devmap_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", uid);
+}
+
+static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
+
/*
* extended error-reporting
*/
@@ -759,6 +822,9 @@ static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
static struct attribute * dasd_attrs[] = {
&dev_attr_readonly.attr,
&dev_attr_discipline.attr,
+ &dev_attr_alias.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_uid.attr,
&dev_attr_use_diag.attr,
&dev_attr_eer_enabled.attr,
NULL,
@@ -768,6 +834,42 @@ static struct attribute_group dasd_attr_group = {
.attrs = dasd_attrs,
};
+
+/*
+ * Return copy of the device unique identifier.
+ */
+int
+dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
+{
+ struct dasd_devmap *devmap;
+
+ devmap = dasd_find_busid(cdev->dev.bus_id);
+ if (IS_ERR(devmap))
+ return PTR_ERR(devmap);
+ spin_lock(&dasd_devmap_lock);
+ *uid = devmap->uid;
+ spin_unlock(&dasd_devmap_lock);
+ return 0;
+}
+
+/*
+ * Register the given device unique identifier into devmap struct.
+ */
+int
+dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
+{
+ struct dasd_devmap *devmap;
+
+ devmap = dasd_find_busid(cdev->dev.bus_id);
+ if (IS_ERR(devmap))
+ return PTR_ERR(devmap);
+ spin_lock(&dasd_devmap_lock);
+ devmap->uid = *uid;
+ spin_unlock(&dasd_devmap_lock);
+ return 0;
+}
+EXPORT_SYMBOL(dasd_set_uid);
+
/*
* Return value of the specified feature.
*/
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index ee09ef33d08d..7d5a6cee4bd8 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -446,6 +446,39 @@ dasd_eckd_cdl_reclen(int recid)
return LABEL_SIZE;
}
+/*
+ * Generate device unique id that specifies the physical device.
+ */
+static int
+dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
+{
+ struct dasd_eckd_private *private;
+ struct dasd_eckd_confdata *confdata;
+
+ private = (struct dasd_eckd_private *) device->private;
+ if (!private)
+ return -ENODEV;
+ confdata = &private->conf_data;
+ if (!confdata)
+ return -ENODEV;
+
+ memset(uid, 0, sizeof(struct dasd_uid));
+ strncpy(uid->vendor, confdata->ned1.HDA_manufacturer,
+ sizeof(uid->vendor) - 1);
+ EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
+ strncpy(uid->serial, confdata->ned1.HDA_location,
+ sizeof(uid->serial) - 1);
+ EBCASC(uid->serial, sizeof(uid->serial) - 1);
+ uid->ssid = confdata->neq.subsystemID;
+ if (confdata->ned2.sneq.flags == 0x40) {
+ uid->alias = 1;
+ uid->unit_addr = confdata->ned2.sneq.base_unit_addr;
+ } else
+ uid->unit_addr = confdata->ned1.unit_addr;
+
+ return 0;
+}
+
static int
dasd_eckd_read_conf(struct dasd_device *device)
{
@@ -507,11 +540,15 @@ dasd_eckd_read_conf(struct dasd_device *device)
return 0;
}
-
+/*
+ * Check device characteristics.
+ * If the device is accessible using ECKD discipline, the device is enabled.
+ */
static int
dasd_eckd_check_characteristics(struct dasd_device *device)
{
struct dasd_eckd_private *private;
+ struct dasd_uid uid;
void *rdc_data;
int rc;
@@ -536,6 +573,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
+ memset(rdc_data, 0, sizeof(rdc_data));
rc = read_dev_chars(device->cdev, &rdc_data, 64);
if (rc) {
DEV_MESSAGE(KERN_WARNING, device,
@@ -556,8 +594,17 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Configuration Data */
rc = dasd_eckd_read_conf (device);
- return rc;
+ if (rc)
+ return rc;
+
+ /* Generate device unique id and register in devmap */
+ rc = dasd_eckd_generate_uid(device, &uid);
+ if (rc)
+ return rc;
+ rc = dasd_set_uid(device->cdev, &uid);
+
+ return rc;
}
static struct dasd_ccw_req *
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index ad8524bb7bb3..d5734e976e1c 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -228,26 +228,36 @@ struct dasd_eckd_confdata {
unsigned char HDA_manufacturer[3];
unsigned char HDA_location[2];
unsigned char HDA_seqno[12];
- __u16 ID;
+ __u8 ID;
+ __u8 unit_addr;
} __attribute__ ((packed)) ned1;
- struct {
+ union {
struct {
- unsigned char identifier:2;
- unsigned char token_id:1;
- unsigned char sno_valid:1;
- unsigned char subst_sno:1;
- unsigned char recNED:1;
- unsigned char emuNED:1;
- unsigned char reserved:1;
- } __attribute__ ((packed)) flags;
- __u8 descriptor;
- __u8 reserved[2];
- unsigned char dev_type[6];
- unsigned char dev_model[3];
- unsigned char DASD_manufacturer[3];
- unsigned char DASD_location[2];
- unsigned char DASD_seqno[12];
- __u16 ID;
+ struct {
+ unsigned char identifier:2;
+ unsigned char token_id:1;
+ unsigned char sno_valid:1;
+ unsigned char subst_sno:1;
+ unsigned char recNED:1;
+ unsigned char emuNED:1;
+ unsigned char reserved:1;
+ } __attribute__ ((packed)) flags;
+ __u8 descriptor;
+ __u8 reserved[2];
+ unsigned char dev_type[6];
+ unsigned char dev_model[3];
+ unsigned char DASD_manufacturer[3];
+ unsigned char DASD_location[2];
+ unsigned char DASD_seqno[12];
+ __u16 ID;
+ } __attribute__ ((packed)) ned;
+ struct {
+ unsigned char flags; /* byte 0 */
+ unsigned char res2[7]; /* byte 1- 7 */
+ unsigned char sua_flags; /* byte 8 */
+ __u8 base_unit_addr; /* byte 9 */
+ unsigned char res3[22]; /* byte 10-31 */
+ } __attribute__ ((packed)) sneq;
} __attribute__ ((packed)) ned2;
struct {
struct {
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 8fd71ab02ef0..b842377cb0c6 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -32,9 +32,8 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
int size;
/* Sanity checks */
- if ( magic == NULL || datasize > PAGE_SIZE ||
- (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
- BUG();
+ BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+ (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
if (cplength > 0)
@@ -125,8 +124,7 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr)
struct dasd_device *device;
int success;
- if (cqr->refers == NULL || cqr->function == NULL)
- BUG();
+ BUG_ON(cqr->refers == NULL || cqr->function == NULL);
device = cqr->device;
success = cqr->status == DASD_CQR_DONE;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 4293ba827523..d4b13e300a76 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -268,6 +268,16 @@ struct dasd_discipline {
extern struct dasd_discipline *dasd_diag_discipline_pointer;
+/*
+ * Unique identifier for dasd device.
+ */
+struct dasd_uid {
+ __u8 alias;
+ char vendor[4];
+ char serial[15];
+ __u16 ssid;
+ __u8 unit_addr;
+};
/*
* Notification numbers for extended error reporting notifications:
@@ -516,6 +526,8 @@ void dasd_devmap_exit(void);
struct dasd_device *dasd_create_device(struct ccw_device *);
void dasd_delete_device(struct dasd_device *);
+int dasd_get_uid(struct ccw_device *, struct dasd_uid *);
+int dasd_set_uid(struct ccw_device *, struct dasd_uid *);
int dasd_get_feature(struct ccw_device *, int);
int dasd_set_feature(struct ccw_device *, int, int);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 1aa3c261718a..ad23aede356c 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -294,23 +294,40 @@ out_error:
#endif /* CONFIG_DASD_PROFILE */
}
+/*
+ * Create dasd proc-fs entries.
+ * In case creation failed, cleanup and return -ENOENT.
+ */
int
dasd_proc_init(void)
{
dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
+ if (!dasd_proc_root_entry)
+ goto out_nodasd;
dasd_proc_root_entry->owner = THIS_MODULE;
dasd_devices_entry = create_proc_entry("devices",
S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry);
+ if (!dasd_devices_entry)
+ goto out_nodevices;
dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
dasd_devices_entry->owner = THIS_MODULE;
dasd_statistics_entry = create_proc_entry("statistics",
S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry);
+ if (!dasd_statistics_entry)
+ goto out_nostatistics;
dasd_statistics_entry->read_proc = dasd_statistics_read;
dasd_statistics_entry->write_proc = dasd_statistics_write;
dasd_statistics_entry->owner = THIS_MODULE;
return 0;
+
+ out_nostatistics:
+ remove_proc_entry("devices", dasd_proc_root_entry);
+ out_nodevices:
+ remove_proc_entry("dasd", &proc_root);
+ out_nodasd:
+ return -ENOENT;
}
void
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 6badd8403409..d4d2ff0a9da2 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -54,7 +54,7 @@ kbd_alloc(void) {
if (!kbd)
goto out;
kbd->key_maps = kzalloc(sizeof(key_maps), GFP_KERNEL);
- if (!key_maps)
+ if (!kbd->key_maps)
goto out_kbd;
for (i = 0; i < ARRAY_SIZE(key_maps); i++) {
if (key_maps[i]) {
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index ac10dfb20a62..91e93c78f57a 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -24,7 +24,7 @@
/*
* The room for the SCCB (only for writing) is not equal to a pages size
- * (as it is specified as the maximum size in the the SCLP ducumentation)
+ * (as it is specified as the maximum size in the the SCLP documentation)
* because of the additional data structure described above.
*/
#define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index c3915f60a3aa..d71ef1adea59 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -230,14 +230,16 @@ tape_3590_read_attmsg(struct tape_device *device)
* These functions are used to schedule follow-up actions from within an
* interrupt context (like unsolicited interrupts).
*/
+struct work_handler_data {
+ struct tape_device *device;
+ enum tape_op op;
+ struct work_struct work;
+};
+
static void
tape_3590_work_handler(void *data)
{
- struct {
- struct tape_device *device;
- enum tape_op op;
- struct work_struct work;
- } *p = data;
+ struct work_handler_data *p = data;
switch (p->op) {
case TO_MSEN:
@@ -257,11 +259,7 @@ tape_3590_work_handler(void *data)
static int
tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
{
- struct {
- struct tape_device *device;
- enum tape_op op;
- struct work_struct work;
- } *p;
+ struct work_handler_data *p;
if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;
@@ -316,7 +314,7 @@ tape_3590_bread(struct tape_device *device, struct request *req)
rq_for_each_bio(bio, req) {
bio_for_each_segment(bv, bio, i) {
- dst = kmap(bv->bv_page) + bv->bv_offset;
+ dst = page_address(bv->bv_page) + bv->bv_offset;
for (off = 0; off < bv->bv_len;
off += TAPEBLOCK_HSEC_SIZE) {
ccw->flags = CCW_FLAG_CC;
@@ -1168,6 +1166,7 @@ tape_3590_setup_device(struct tape_device *device)
static void
tape_3590_cleanup_device(struct tape_device *device)
{
+ flush_scheduled_work();
tape_std_unassign(device);
kfree(device->discdata);
@@ -1234,6 +1233,7 @@ static struct tape_discipline tape_discipline_3590 = {
static struct ccw_device_id tape_3590_ids[] = {
{CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590},
+ {CCW_DEVICE_DEVTYPE(0x3592, 0, 0x3592, 0), .driver_info = tape_3592},
{ /* end of list */ }
};
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 5ced2725d6c7..b70d92690242 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -198,9 +198,7 @@ tapeblock_request_fn(request_queue_t *queue)
device = (struct tape_device *) queue->queuedata;
DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device);
- if (device == NULL)
- BUG();
-
+ BUG_ON(device == NULL);
tapeblock_trigger_requeue(device);
}
@@ -307,8 +305,7 @@ tapeblock_revalidate_disk(struct gendisk *disk)
int rc;
device = (struct tape_device *) disk->private_data;
- if (!device)
- BUG();
+ BUG_ON(!device);
if (!device->blk_data.medium_changed)
return 0;
@@ -435,16 +432,14 @@ tapeblock_ioctl(
) {
int rc;
int minor;
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct tape_device *device = disk->private_data;
+ struct gendisk *disk;
+ struct tape_device *device;
rc = 0;
disk = inode->i_bdev->bd_disk;
- if (!disk)
- BUG();
+ BUG_ON(!disk);
device = disk->private_data;
- if (!device)
- BUG();
+ BUG_ON(!device);
minor = iminor(inode);
DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 389ee2c0f443..e6e4086d3224 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -210,18 +210,14 @@ tape_state_set(struct tape_device *device, enum tape_state newstate)
return;
}
DBF_EVENT(4, "ts. dev: %x\n", device->first_minor);
- if (device->tape_state < TO_SIZE && device->tape_state >= 0)
- str = tape_state_verbose[device->tape_state];
- else
- str = "UNKNOWN TS";
- DBF_EVENT(4, "old ts: %s\n", str);
- if (device->tape_state < TO_SIZE && device->tape_state >=0 )
+ DBF_EVENT(4, "old ts:\t\n");
+ if (device->tape_state < TS_SIZE && device->tape_state >=0 )
str = tape_state_verbose[device->tape_state];
else
str = "UNKNOWN TS";
DBF_EVENT(4, "%s\n", str);
DBF_EVENT(4, "new ts:\t\n");
- if (newstate < TO_SIZE && newstate >= 0)
+ if (newstate < TS_SIZE && newstate >= 0)
str = tape_state_verbose[newstate];
else
str = "UNKNOWN TS";
diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h
index 2d311798edf4..1fc952359341 100644
--- a/drivers/s390/char/tape_std.h
+++ b/drivers/s390/char/tape_std.h
@@ -153,6 +153,7 @@ enum s390_tape_type {
tape_3480,
tape_3490,
tape_3590,
+ tape_3592,
};
#endif // _TAPE_STD_H
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index cb8e2e672b68..0960bef7b199 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -414,11 +414,11 @@ cio_ignore_proc_init (void)
entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR,
&proc_root);
if (!entry)
- return 0;
+ return -ENOENT;
entry->proc_fops = &cio_ignore_proc_fops;
- return 1;
+ return 0;
}
__initcall (cio_ignore_proc_init);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 6412b2c3edd3..72187e54dcac 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -242,28 +242,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if (sch->vpm == mask)
goto out_unreg;
- if ((sch->schib.scsw.actl & (SCSW_ACTL_CLEAR_PEND |
- SCSW_ACTL_HALT_PEND |
- SCSW_ACTL_START_PEND |
- SCSW_ACTL_RESUME_PEND)) &&
- (sch->schib.pmcw.lpum == mask)) {
- int cc = cio_cancel(sch);
-
- if (cc == -ENODEV)
- goto out_unreg;
-
- if (cc == -EINVAL) {
- cc = cio_clear(sch);
- if (cc == -ENODEV)
- goto out_unreg;
- /* Call handler. */
- if (sch->driver && sch->driver->termination)
- sch->driver->termination(&sch->dev);
- goto out_unlock;
- }
- } else if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
- (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
- (sch->schib.pmcw.lpum == mask)) {
+ if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
+ (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
+ (sch->schib.pmcw.lpum == mask) &&
+ (sch->vpm == 0)) {
int cc;
cc = cio_clear(sch);
@@ -653,13 +635,13 @@ __chp_add(struct subchannel_id schid, void *data)
if (sch->schib.pmcw.chpid[i] == chp->id) {
if (stsch(sch->schid, &sch->schib) != 0) {
/* Endgame. */
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return -ENXIO;
}
break;
}
if (i==8) {
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
}
sch->lpm = ((sch->schib.pmcw.pim &
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index cbb86fa5f293..5b20d8c9c025 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -67,7 +67,7 @@ cio_debug_init (void)
goto out_unregister;
debug_register_view (cio_debug_msg_id, &debug_sprintf_view);
debug_set_level (cio_debug_msg_id, 2);
- cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8);
+ cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 16);
if (!cio_debug_trace_id)
goto out_unregister;
debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view);
diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h
index 6af8b27d366b..f88844adae1b 100644
--- a/drivers/s390/cio/cio_debug.h
+++ b/drivers/s390/cio/cio_debug.h
@@ -3,6 +3,11 @@
#include <asm/debug.h>
+/* for use of debug feature */
+extern debug_info_t *cio_debug_msg_id;
+extern debug_info_t *cio_debug_trace_id;
+extern debug_info_t *cio_debug_crw_id;
+
#define CIO_TRACE_EVENT(imp, txt) do { \
debug_text_event(cio_debug_trace_id, imp, txt); \
} while (0)
@@ -15,18 +20,19 @@
debug_sprintf_event(cio_debug_crw_id, imp , ##args); \
} while (0)
-#define CIO_HEX_EVENT(imp, args...) do { \
- debug_event(cio_debug_trace_id, imp, ##args); \
- } while (0)
+static inline void
+CIO_HEX_EVENT(int level, void *data, int length)
+{
+ while (length > 0) {
+ debug_event(cio_debug_trace_id, level, data, length);
+ length -= cio_debug_trace_id->buf_size;
+ data += cio_debug_trace_id->buf_size;
+ }
+}
#define CIO_DEBUG(printk_level,event_level,msg...) ({ \
if (cio_show_msg) printk(printk_level msg); \
CIO_MSG_EVENT (event_level, msg); \
})
-/* for use of debug feature */
-extern debug_info_t *cio_debug_msg_id;
-extern debug_info_t *cio_debug_trace_id;
-extern debug_info_t *cio_debug_crw_id;
-
#endif
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 814f9258ce00..96f519281d92 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -38,6 +38,7 @@
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/timer.h>
+#include <linux/mempool.h>
#include <asm/ccwdev.h>
#include <asm/io.h>
@@ -80,6 +81,8 @@ static int indicator_used[INDICATORS_PER_CACHELINE];
static __u32 * volatile indicators;
static __u32 volatile spare_indicator;
static atomic_t spare_indicator_usecount;
+#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
+static mempool_t *qdio_mempool_scssc;
static debug_info_t *qdio_dbf_setup;
static debug_info_t *qdio_dbf_sbal;
@@ -1637,7 +1640,7 @@ next:
}
kfree(irq_ptr->qdr);
- kfree(irq_ptr);
+ free_page((unsigned long) irq_ptr);
}
static void
@@ -2304,7 +2307,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
QDIO_DBF_TEXT0(0,setup,"getssqd");
qdioac = 0;
- ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
if (!ssqd_area) {
QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
"SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
@@ -2364,7 +2367,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
out:
qdio_check_subchannel_qebsm(irq_ptr, qdioac,
ssqd_area->sch_token);
- free_page ((unsigned long) ssqd_area);
+ mempool_free(ssqd_area, qdio_mempool_scssc);
irq_ptr->qdioac = qdioac;
}
@@ -2458,7 +2461,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
}
- scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ scssc_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
if (!scssc_area) {
QDIO_PRINT_WARN("No memory for setting indicators on " \
"subchannel 0.%x.%x.\n",
@@ -2514,7 +2517,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));
result = 0;
out:
- free_page ((unsigned long) scssc_area);
+ mempool_free(scssc_area, qdio_mempool_scssc);
return result;
}
@@ -2543,7 +2546,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
if (!irq_ptr->is_thinint_irq)
return -ENODEV;
- scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ scsscf_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
if (!scsscf_area) {
QDIO_PRINT_WARN("No memory for setting delay target on " \
"subchannel 0.%x.%x.\n",
@@ -2581,7 +2584,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));
result = 0; /* not critical */
out:
- free_page ((unsigned long) scsscf_area);
+ mempool_free(scsscf_area, qdio_mempool_scssc);
return result;
}
@@ -2980,7 +2983,7 @@ qdio_allocate(struct qdio_initialize *init_data)
qdio_allocate_do_dbf(init_data);
/* create irq */
- irq_ptr = kzalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA);
+ irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
QDIO_DBF_TEXT0(0,setup,"irq_ptr:");
QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
@@ -2995,7 +2998,7 @@ qdio_allocate(struct qdio_initialize *init_data)
/* QDR must be in DMA area since CCW data address is only 32 bit */
irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
if (!(irq_ptr->qdr)) {
- kfree(irq_ptr);
+ free_page((unsigned long) irq_ptr);
QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
return -ENOMEM;
}
@@ -3780,6 +3783,16 @@ oom:
return -ENOMEM;
}
+static void *qdio_mempool_alloc(gfp_t gfp_mask, void *size)
+{
+ return (void *) get_zeroed_page(gfp_mask|GFP_DMA);
+}
+
+static void qdio_mempool_free(void *element, void *size)
+{
+ free_page((unsigned long) element);
+}
+
static int __init
init_QDIO(void)
{
@@ -3809,6 +3822,10 @@ init_QDIO(void)
qdio_add_procfs_entry();
+ qdio_mempool_scssc = mempool_create(QDIO_MEMPOOL_SCSSC_ELEMENTS,
+ qdio_mempool_alloc,
+ qdio_mempool_free, NULL);
+
if (tiqdio_check_chsc_availability())
QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
@@ -3824,6 +3841,7 @@ cleanup_QDIO(void)
qdio_remove_procfs_entry();
qdio_release_qdio_memory();
qdio_unregister_dbf_views();
+ mempool_destroy(qdio_mempool_scssc);
printk("qdio: %s: module removed\n",version);
}
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index edcf05d5d568..5d6b7a57b02f 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -675,9 +675,8 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
int index, rc;
LCS_DBF_TEXT(5, trace, "rdybuff");
- if (buffer->state != BUF_STATE_LOCKED &&
- buffer->state != BUF_STATE_PROCESSED)
- BUG();
+ BUG_ON(buffer->state != BUF_STATE_LOCKED &&
+ buffer->state != BUF_STATE_PROCESSED);
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
buffer->state = BUF_STATE_READY;
index = buffer - channel->iob;
@@ -701,8 +700,7 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
int index, prev, next;
LCS_DBF_TEXT(5, trace, "prcsbuff");
- if (buffer->state != BUF_STATE_READY)
- BUG();
+ BUG_ON(buffer->state != BUF_STATE_READY);
buffer->state = BUF_STATE_PROCESSED;
index = buffer - channel->iob;
prev = (index - 1) & (LCS_NUM_BUFFS - 1);
@@ -734,9 +732,8 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
unsigned long flags;
LCS_DBF_TEXT(5, trace, "relbuff");
- if (buffer->state != BUF_STATE_LOCKED &&
- buffer->state != BUF_STATE_PROCESSED)
- BUG();
+ BUG_ON(buffer->state != BUF_STATE_LOCKED &&
+ buffer->state != BUF_STATE_PROCESSED);
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
buffer->state = BUF_STATE_EMPTY;
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 3bf466603512..5ae14803091f 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -362,12 +362,19 @@ s390_revalidate_registers(struct mci *mci)
return kill_task;
}
+#define MAX_IPD_COUNT 29
+#define MAX_IPD_TIME (5 * 60 * 100 * 1000) /* 5 minutes */
+
/*
* machine check handler.
*/
void
s390_do_machine_check(struct pt_regs *regs)
{
+ static DEFINE_SPINLOCK(ipd_lock);
+ static unsigned long long last_ipd;
+ static int ipd_count;
+ unsigned long long tmp;
struct mci *mci;
struct mcck_struct *mcck;
int umode;
@@ -404,11 +411,27 @@ s390_do_machine_check(struct pt_regs *regs)
s390_handle_damage("processing backup machine "
"check with damage.");
}
- if (!umode)
- s390_handle_damage("processing backup machine "
- "check in kernel mode.");
- mcck->kill_task = 1;
- mcck->mcck_code = *(unsigned long long *) mci;
+
+ /*
+ * Nullifying exigent condition, therefore we might
+ * retry this instruction.
+ */
+
+ spin_lock(&ipd_lock);
+
+ tmp = get_clock();
+
+ if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
+ ipd_count++;
+ else
+ ipd_count = 1;
+
+ last_ipd = tmp;
+
+ if (ipd_count == MAX_IPD_COUNT)
+ s390_handle_damage("too many ipd retries.");
+
+ spin_unlock(&ipd_lock);
}
else {
/* Processing damage -> stopping machine */
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 0d2b447c50ed..caeb6d246e57 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -65,6 +65,7 @@
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
2.26.02.006 - Fix 9550SX pchip reset timeout.
Add big endian support.
+ 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
*/
#include <linux/module.h>
@@ -88,7 +89,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.006"
+#define TW_DRIVER_VERSION "2.26.02.007"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -1942,9 +1943,13 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
}
if (tw_dev->srb[request_id]->use_sg == 1) {
struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
- char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ char *buf;
+ unsigned long flags = 0;
+ local_irq_save(flags);
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
}
}
} /* End twa_scsiop_execute_scsi_complete() */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 25f678d0780b..e8e41e6eb42a 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1508,10 +1508,12 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
struct scsi_cmnd *cmd = tw_dev->srb[request_id];
void *buf;
unsigned int transfer_len;
+ unsigned long flags = 0;
if (cmd->use_sg) {
struct scatterlist *sg =
(struct scatterlist *)cmd->request_buffer;
+ local_irq_save(flags);
buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
transfer_len = min(sg->length, len);
} else {
@@ -1526,6 +1528,7 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
sg = (struct scatterlist *)cmd->request_buffer;
kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
}
}
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4035920ce3d8..3e7302692dbe 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1079,7 +1079,7 @@ config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
memory using PCI DAC cycles.
config SCSI_SYM53C8XX_DEFAULT_TAGS
- int "default tagged command queue depth"
+ int "Default tagged command queue depth"
depends on SCSI_SYM53C8XX_2
default "16"
help
@@ -1090,7 +1090,7 @@ config SCSI_SYM53C8XX_DEFAULT_TAGS
exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS.
config SCSI_SYM53C8XX_MAX_TAGS
- int "maximum number of queued commands"
+ int "Maximum number of queued commands"
depends on SCSI_SYM53C8XX_2
default "64"
help
@@ -1099,13 +1099,14 @@ config SCSI_SYM53C8XX_MAX_TAGS
possible. The driver supports up to 256 queued commands per device.
This value is used as a compiled-in hard limit.
-config SCSI_SYM53C8XX_IOMAPPED
- bool "use port IO"
+config SCSI_SYM53C8XX_MMIO
+ bool "Use memory mapped IO"
depends on SCSI_SYM53C8XX_2
+ default y
help
- If you say Y here, the driver will use port IO to access
- the card. This is significantly slower then using memory
- mapped IO. Most people should answer N.
+ Memory mapped IO is faster than Port IO. Most people should
+ answer Y here, but some machines may have problems. If you have
+ to answer N here, please report the problem to the maintainer.
config SCSI_IPR
tristate "IBM Power Linux RAID adapter support"
@@ -1309,15 +1310,6 @@ config SCSI_QLOGIC_FAS
To compile this driver as a module, choose M here: the
module will be called qlogicfas.
-config SCSI_QLOGIC_FC
- tristate "Qlogic ISP FC SCSI support"
- depends on PCI && SCSI
- help
- This is a driver for the QLogic ISP2100 SCSI-FCP host adapter.
-
- To compile this driver as a module, choose M here: the
- module will be called qlogicfc.
-
config SCSI_QLOGIC_FC_FIRMWARE
bool "Include loadable firmware in driver"
depends on SCSI_QLOGIC_FC
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index e513c3158ad9..81803a16f986 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -78,7 +78,6 @@ obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o
obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o
obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
-obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
obj-$(CONFIG_SCSI_LPFC) += lpfc/
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 8df4a0ea3761..642a3b4e5937 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -149,20 +149,20 @@ static int dacmode = -1;
static int commit = -1;
-module_param(nondasd, int, 0);
+module_param(nondasd, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
-module_param(dacmode, int, 0);
+module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
-module_param(commit, int, 0);
+module_param(commit, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
int numacb = -1;
module_param(numacb, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid values are 512 and down. Default is to use suggestion from Firmware.");
int acbsize = -1;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
/**
* aac_get_config_status - check the adapter configuration
* @common: adapter to query
@@ -387,6 +387,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
struct scsi_cmnd * scsicmd;
scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
if (fibptr == NULL)
@@ -453,8 +454,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
+ }
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
@@ -907,9 +910,10 @@ static void io_callback(void *context, struct fib * fibptr)
u32 cid;
scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+ cid = scmd_id(scsicmd);
if (nblank(dprintk(x))) {
u64 lba;
@@ -1151,8 +1155,10 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
+ }
printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
/*
@@ -1318,8 +1324,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
- {
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
}
@@ -1341,6 +1347,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
struct scsi_cmnd *cmd;
cmd = context;
+ cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n",
smp_processor_id(), jiffies));
@@ -1354,7 +1361,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
else {
struct scsi_device *sdev = cmd->device;
struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
- u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
+ u32 cid = sdev_id(sdev);
printk(KERN_WARNING
"synchronize_callback: synchronize failed, status = %d\n",
le32_to_cpu(synchronizereply->status));
@@ -1386,12 +1393,12 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
unsigned long flags;
/*
- * Wait for all commands to complete to this specific
- * target (block).
+ * Wait for all outstanding queued commands to complete to this
+ * specific target (block).
*/
spin_lock_irqsave(&sdev->list_lock, flags);
list_for_each_entry(cmd, &sdev->cmd_list, list)
- if (cmd != scsicmd && cmd->serial_number != 0) {
+ if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
++active;
break;
}
@@ -1434,8 +1441,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
+ }
printk(KERN_WARNING
"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
@@ -1458,7 +1467,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
struct Scsi_Host *host = scsicmd->device->host;
struct aac_dev *dev = (struct aac_dev *)host->hostdata;
struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
- int ret;
/*
* If the bus, id or lun is out of range, return fail
@@ -1466,13 +1474,14 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* itself.
*/
if (scmd_id(scsicmd) != host->this_id) {
- if ((scsicmd->device->channel == CONTAINER_CHANNEL)) {
- if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){
+ if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
+ if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
+ (scsicmd->device->lun != 0)) {
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
return 0;
}
- cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+ cid = scmd_id(scsicmd);
/*
* If the target container doesn't exist, it may have
@@ -1548,7 +1557,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
{
struct inquiry_data inq_data;
- dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
+ dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
memset(&inq_data, 0, sizeof (struct inquiry_data));
inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
@@ -1598,13 +1607,14 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
cp[11] = 0;
cp[12] = 0;
aac_internal_transfer(scsicmd, cp, 0,
- min((unsigned int)scsicmd->cmnd[13], sizeof(cp)));
+ min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
if (sizeof(cp) < scsicmd->cmnd[13]) {
unsigned int len, offset = sizeof(cp);
memset(cp, 0, offset);
do {
- len = min(scsicmd->cmnd[13]-offset, sizeof(cp));
+ len = min_t(size_t, scsicmd->cmnd[13] - offset,
+ sizeof(cp));
aac_internal_transfer(scsicmd, cp, offset, len);
} while ((offset += len) < scsicmd->cmnd[13]);
}
@@ -1728,24 +1738,19 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* containers to /dev/sd device names
*/
- spin_unlock_irq(host->host_lock);
if (scsicmd->request->rq_disk)
strlcpy(fsa_dev_ptr[cid].devname,
scsicmd->request->rq_disk->disk_name,
min(sizeof(fsa_dev_ptr[cid].devname),
sizeof(scsicmd->request->rq_disk->disk_name) + 1));
- ret = aac_read(scsicmd, cid);
- spin_lock_irq(host->host_lock);
- return ret;
+
+ return aac_read(scsicmd, cid);
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_16:
- spin_unlock_irq(host->host_lock);
- ret = aac_write(scsicmd, cid);
- spin_lock_irq(host->host_lock);
- return ret;
+ return aac_write(scsicmd, cid);
case SYNCHRONIZE_CACHE:
/* Issue FIB to tell Firmware to flush it's cache */
@@ -1778,7 +1783,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
return -EFAULT;
if (qd.cnum == -1)
- qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);
+ qd.cnum = qd.id;
else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1))
{
if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)
@@ -1890,6 +1895,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
struct scsi_cmnd *scsicmd;
scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (fibptr == NULL)
@@ -2068,14 +2074,13 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
u32 timeout;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- if (scsicmd->device->id >= dev->maximum_num_physicals ||
+ if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
scsicmd->device->lun > 7) {
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
return 0;
}
- dev = (struct aac_dev *)scsicmd->device->host->hostdata;
switch(scsicmd->sc_data_direction){
case DMA_TO_DEVICE:
flag = SRB_DataOut;
@@ -2103,8 +2108,8 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
- srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel));
- srbcmd->id = cpu_to_le32(scsicmd->device->id);
+ srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd)));
+ srbcmd->id = cpu_to_le32(scmd_id(scsicmd));
srbcmd->lun = cpu_to_le32(scsicmd->device->lun);
srbcmd->flags = cpu_to_le32(flag);
timeout = scsicmd->timeout_per_command/HZ;
@@ -2161,7 +2166,8 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS){
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
}
@@ -2192,8 +2198,6 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
scsicmd->sc_data_direction);
psg->count = cpu_to_le32(sg_count);
- byte_count = 0;
-
for (i = 0; i < sg_count; i++) {
psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
@@ -2249,18 +2253,17 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
scsicmd->sc_data_direction);
- psg->count = cpu_to_le32(sg_count);
-
- byte_count = 0;
for (i = 0; i < sg_count; i++) {
+ int count = sg_dma_len(sg);
addr = sg_dma_address(sg);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
- psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
- byte_count += sg_dma_len(sg);
+ psg->sg[i].count = cpu_to_le32(count);
+ byte_count += count;
sg++;
}
+ psg->count = cpu_to_le32(sg_count);
/* hba wants the size to be exact */
if(byte_count > scsicmd->request_bufflen){
u32 temp = le32_to_cpu(psg->sg[i-1].count) -
@@ -2275,16 +2278,15 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
}
}
else if(scsicmd->request_bufflen) {
- u64 addr;
- addr = pci_map_single(dev->pdev,
+ scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
scsicmd->request_buffer,
scsicmd->request_bufflen,
scsicmd->sc_data_direction);
+ addr = scsicmd->SCp.dma_handle;
psg->count = cpu_to_le32(1);
psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);
- scsicmd->SCp.dma_handle = addr;
byte_count = scsicmd->request_bufflen;
}
return byte_count;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 9ce7002bd070..f773b0dcfc95 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -10,6 +10,10 @@
* D E F I N E S
*----------------------------------------------------------------------------*/
+#ifndef AAC_DRIVER_BUILD
+# define AAC_DRIVER_BUILD 2409
+# define AAC_DRIVER_BRANCH "-mh1"
+#endif
#define MAXIMUM_NUM_CONTAINERS 32
#define AAC_NUM_MGT_FIB 8
@@ -25,7 +29,6 @@
* These macros convert from physical channels to virtual channels
*/
#define CONTAINER_CHANNEL (0)
-#define ID_LUN_TO_CONTAINER(id, lun) (id)
#define CONTAINER_TO_CHANNEL(cont) (CONTAINER_CHANNEL)
#define CONTAINER_TO_ID(cont) (cont)
#define CONTAINER_TO_LUN(cont) (0)
@@ -789,6 +792,7 @@ struct fsa_dev_info {
u64 size;
u32 type;
u32 config_waiting_on;
+ unsigned long config_waiting_stamp;
u16 queue_depth;
u8 config_needed;
u8 valid;
@@ -1771,6 +1775,11 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
}
struct scsi_cmnd;
+/* SCp.phase values */
+#define AAC_OWNER_MIDLEVEL 0x101
+#define AAC_OWNER_LOWLEVEL 0x102
+#define AAC_OWNER_ERROR_HANDLER 0x103
+#define AAC_OWNER_FIRMWARE 0x106
const char *aac_driverinfo(struct Scsi_Host *);
struct fib *aac_fib_alloc(struct aac_dev *dev);
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 47fefca72695..9f75144e5247 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -38,6 +38,8 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -293,6 +295,16 @@ return_fib:
status = 0;
} else {
spin_unlock_irqrestore(&dev->fib_lock, flags);
+ /* If someone killed the AIF aacraid thread, restart it */
+ status = !dev->aif_thread;
+ if (status && dev->queues && dev->fsa_dev) {
+ /* Be paranoid, be very paranoid! */
+ kthread_stop(dev->thread);
+ ssleep(1);
+ dev->aif_thread = 0;
+ dev->thread = kthread_run(aac_command_thread, dev, dev->name);
+ ssleep(1);
+ }
if (f.wait) {
if(down_interruptible(&fibctx->wait_sem) < 0) {
status = -EINTR;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index c7f80ec7abde..9f9f4aae23c0 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -767,9 +767,9 @@ void aac_printf(struct aac_dev *dev, u32 val)
if (cp[length] != 0)
cp[length] = 0;
if (level == LOG_AAC_HIGH_ERROR)
- printk(KERN_WARNING "aacraid:%s", cp);
+ printk(KERN_WARNING "%s:%s", dev->name, cp);
else
- printk(KERN_INFO "aacraid:%s", cp);
+ printk(KERN_INFO "%s:%s", dev->name, cp);
}
memset(cp, 0, 256);
}
@@ -784,6 +784,7 @@ void aac_printf(struct aac_dev *dev, u32 val)
* dispatches it to the appropriate routine for handling.
*/
+#define AIF_SNIFF_TIMEOUT (30*HZ)
static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -837,6 +838,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (device) {
dev->fsa_dev[container].config_needed = CHANGE;
dev->fsa_dev[container].config_waiting_on = AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
scsi_device_put(device);
}
}
@@ -849,13 +851,15 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (container != (u32)-1) {
if (container >= dev->maximum_num_containers)
break;
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
} else for (container = 0;
container < dev->maximum_num_containers; ++container) {
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
}
break;
@@ -872,6 +876,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_needed = ADD;
dev->fsa_dev[container].config_waiting_on =
AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
break;
/*
@@ -884,6 +889,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_needed = DELETE;
dev->fsa_dev[container].config_waiting_on =
AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
break;
/*
@@ -894,11 +900,13 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
if (container >= dev->maximum_num_containers)
break;
- if (dev->fsa_dev[container].config_waiting_on)
+ if (dev->fsa_dev[container].config_waiting_on &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
break;
dev->fsa_dev[container].config_needed = CHANGE;
dev->fsa_dev[container].config_waiting_on =
AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
break;
case AifEnConfigChange:
@@ -913,13 +921,15 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (container != (u32)-1) {
if (container >= dev->maximum_num_containers)
break;
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
} else for (container = 0;
container < dev->maximum_num_containers; ++container) {
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
}
break;
@@ -946,6 +956,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_waiting_on =
AifEnContainerChange;
dev->fsa_dev[container].config_needed = ADD;
+ dev->fsa_dev[container].config_waiting_stamp =
+ jiffies;
}
}
if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
@@ -961,6 +973,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_waiting_on =
AifEnContainerChange;
dev->fsa_dev[container].config_needed = DELETE;
+ dev->fsa_dev[container].config_waiting_stamp =
+ jiffies;
}
}
break;
@@ -969,8 +983,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
device_config_needed = NOTHING;
for (container = 0; container < dev->maximum_num_containers;
++container) {
- if ((dev->fsa_dev[container].config_waiting_on == 0)
- && (dev->fsa_dev[container].config_needed != NOTHING)) {
+ if ((dev->fsa_dev[container].config_waiting_on == 0) &&
+ (dev->fsa_dev[container].config_needed != NOTHING) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) {
device_config_needed =
dev->fsa_dev[container].config_needed;
dev->fsa_dev[container].config_needed = NOTHING;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 720330778648..6ef89c99dd12 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -27,12 +27,6 @@
* Abstract: Linux Driver entry module for Adaptec RAID Array Controller
*/
-#define AAC_DRIVER_VERSION "1.1-4"
-#ifndef AAC_DRIVER_BRANCH
-#define AAC_DRIVER_BRANCH ""
-#endif
-#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
-#define AAC_DRIVERNAME "aacraid"
#include <linux/compat.h>
#include <linux/blkdev.h>
@@ -62,6 +56,13 @@
#include "aacraid.h"
+#define AAC_DRIVER_VERSION "1.1-5"
+#ifndef AAC_DRIVER_BRANCH
+#define AAC_DRIVER_BRANCH ""
+#endif
+#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
+#define AAC_DRIVERNAME "aacraid"
+
#ifdef AAC_DRIVER_BUILD
#define _str(x) #x
#define str(x) _str(x)
@@ -73,7 +74,7 @@
MODULE_AUTHOR("Red Hat Inc and Adaptec");
MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
"Adaptec Advanced Raid Products, "
- "and HP NetRAID-4M SCSI driver");
+ "HP NetRAID-4M, IBM ServeRAID & ICP SCSI driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
@@ -243,6 +244,7 @@ static struct aac_driver_ident aac_drivers[] = {
static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
cmd->scsi_done = done;
+ cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
return (aac_scsi_cmd(cmd) ? FAILED : 0);
}
@@ -471,7 +473,8 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
__shost_for_each_device(dev, host) {
spin_lock_irqsave(&dev->list_lock, flags);
list_for_each_entry(command, &dev->cmd_list, list) {
- if (command->serial_number) {
+ if ((command != cmd) &&
+ (command->SCp.phase == AAC_OWNER_FIRMWARE)) {
active++;
break;
}
@@ -569,12 +572,12 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
f = compat_alloc_user_space(sizeof(*f));
ret = 0;
- if (clear_user(f, sizeof(*f) != sizeof(*f)))
+ if (clear_user(f, sizeof(*f)) != sizeof(*f))
ret = -EFAULT;
if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
ret = -EFAULT;
if (!ret)
- ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+ ret = aac_do_ioctl(dev, cmd, f);
break;
}
@@ -687,6 +690,18 @@ static ssize_t aac_show_serial_number(struct class_device *class_dev,
return len;
}
+static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ class_to_shost(class_dev)->max_channel);
+}
+
+static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ class_to_shost(class_dev)->max_id);
+}
+
static struct class_device_attribute aac_model = {
.attr = {
@@ -730,6 +745,20 @@ static struct class_device_attribute aac_serial_number = {
},
.show = aac_show_serial_number,
};
+static struct class_device_attribute aac_max_channel = {
+ .attr = {
+ .name = "max_channel",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_channel,
+};
+static struct class_device_attribute aac_max_id = {
+ .attr = {
+ .name = "max_id",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_id,
+};
static struct class_device_attribute *aac_attrs[] = {
&aac_model,
@@ -738,6 +767,8 @@ static struct class_device_attribute *aac_attrs[] = {
&aac_monitor_version,
&aac_bios_version,
&aac_serial_number,
+ &aac_max_channel,
+ &aac_max_id,
NULL
};
@@ -775,6 +806,7 @@ static struct scsi_host_template aac_driver_template = {
.cmd_per_lun = AAC_NUM_IO_FIB,
#endif
.use_clustering = ENABLE_CLUSTERING,
+ .emulated = 1,
};
@@ -798,10 +830,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
error = pci_enable_device(pdev);
if (error)
goto out;
+ error = -ENODEV;
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
- goto out;
+ goto out_disable_pdev;
/*
* If the quirk31 bit is set, the adapter needs adapter
* to driver communication memory to be allocated below 2gig
@@ -809,7 +842,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) ||
pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK))
- goto out;
+ goto out_disable_pdev;
pci_set_master(pdev);
@@ -904,9 +937,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* physical channels are address by their actual physical number+1
*/
if (aac->nondasd_support == 1)
- shost->max_channel = aac->maximum_num_channels + 1;
+ shost->max_channel = aac->maximum_num_channels;
else
- shost->max_channel = 1;
+ shost->max_channel = 0;
aac_get_config_status(aac);
aac_get_containers(aac);
@@ -1020,7 +1053,8 @@ static int __init aac_init(void)
static void __exit aac_exit(void)
{
- unregister_chrdev(aac_cfg_major, "aac");
+ if (aac_cfg_major > -1)
+ unregister_chrdev(aac_cfg_major, "aac");
pci_unregister_driver(&aac_pci_driver);
}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index e9b775d6bec9..7a23e027eb78 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -183,7 +183,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Yield the processor in case we are slow
*/
- schedule_timeout_uninterruptible(1);
+ msleep(1);
}
if (ok != 1) {
/*
@@ -343,7 +343,7 @@ static int aac_rkt_check_health(struct aac_dev *dev)
NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
- if ((buffer[0] == '0') && (buffer[1] == 'x')) {
+ if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
ret <<= 4;
ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 6998bc877dd6..729b9eb268c2 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -183,7 +183,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Yield the processor in case we are slow
*/
- schedule_timeout_uninterruptible(1);
+ msleep(1);
}
if (ok != 1) {
/*
@@ -342,7 +342,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
- if ((buffer[0] == '0') && (buffer[1] == 'x')) {
+ if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
ret <<= 4;
ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 466f05cfbf0c..a53454908205 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -189,7 +189,7 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
ok = 1;
break;
}
- schedule_timeout_uninterruptible(1);
+ msleep(1);
}
if (ok != 1)
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 1bd82c4e52a0..b4f8fb1d628b 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = AHCI_MAX_SG,
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 6c2c395554ff..5517da5855f0 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -86,7 +86,7 @@ config AIC7XXX_DEBUG_MASK
default "0"
help
Bit mask of debug options that is only valid if the
- CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled. The bits in this mask
+ CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled. The bits in this mask
are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the
variable ahc_debug in that file to find them.
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 1d11f7e77564..bb5166da4358 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -372,7 +372,7 @@ typedef enum {
AHD_CURRENT_SENSING = 0x40000,
AHD_SCB_CONFIG_USED = 0x80000,/* No SEEPROM but SCB had info. */
AHD_HP_BOARD = 0x100000,
- AHD_RESET_POLL_ACTIVE = 0x200000,
+ AHD_BUS_RESET_ACTIVE = 0x200000,
AHD_UPDATE_PEND_CMDS = 0x400000,
AHD_RUNNING_QOUTFIFO = 0x800000,
AHD_HAD_FIRST_SEL = 0x1000000
@@ -589,7 +589,7 @@ typedef enum {
SCB_PACKETIZED = 0x00800,
SCB_EXPECT_PPR_BUSFREE = 0x01000,
SCB_PKT_SENSE = 0x02000,
- SCB_CMDPHASE_ABORT = 0x04000,
+ SCB_EXTERNAL_RESET = 0x04000,/* Device was reset externally */
SCB_ON_COL_LIST = 0x08000,
SCB_SILENT = 0x10000 /*
* Be quiet about transmission type
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 326a62226235..08771f6f6859 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -207,7 +207,6 @@ static void ahd_add_scb_to_free_list(struct ahd_softc *ahd,
static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
u_int prev, u_int next, u_int tid);
static void ahd_reset_current_bus(struct ahd_softc *ahd);
-static ahd_callback_t ahd_reset_poll;
static ahd_callback_t ahd_stat_timer;
#ifdef AHD_DUMP_SEQ
static void ahd_dumpseq(struct ahd_softc *ahd);
@@ -1054,12 +1053,10 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
* If a target takes us into the command phase
* assume that it has been externally reset and
* has thus lost our previous packetized negotiation
- * agreement. Since we have not sent an identify
- * message and may not have fully qualified the
- * connection, we change our command to TUR, assert
- * ATN and ABORT the task when we go to message in
- * phase. The OSM will see the REQUEUE_REQUEST
- * status and retry the command.
+ * agreement.
+ * Revert to async/narrow transfers until we
+ * can renegotiate with the device and notify
+ * the OSM about the reset.
*/
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
@@ -1086,31 +1083,15 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_set_syncrate(ahd, &devinfo, /*period*/0,
/*offset*/0, /*ppr_options*/0,
AHD_TRANS_ACTIVE, /*paused*/TRUE);
- ahd_outb(ahd, SCB_CDB_STORE, 0);
- ahd_outb(ahd, SCB_CDB_STORE+1, 0);
- ahd_outb(ahd, SCB_CDB_STORE+2, 0);
- ahd_outb(ahd, SCB_CDB_STORE+3, 0);
- ahd_outb(ahd, SCB_CDB_STORE+4, 0);
- ahd_outb(ahd, SCB_CDB_STORE+5, 0);
- ahd_outb(ahd, SCB_CDB_LEN, 6);
- scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
- scb->hscb->control |= MK_MESSAGE;
- ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
- ahd_outb(ahd, MSG_OUT, HOST_MSG);
- ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
- /*
- * The lun is 0, regardless of the SCB's lun
- * as we have not sent an identify message.
- */
- ahd_outb(ahd, SAVED_LUN, 0);
- ahd_outb(ahd, SEQ_FLAGS, 0);
- ahd_assert_atn(ahd);
- scb->flags &= ~SCB_PACKETIZED;
- scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
+ scb->flags |= SCB_EXTERNAL_RESET;
ahd_freeze_devq(ahd, scb);
ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
ahd_freeze_scb(scb);
+ /* Notify XPT */
+ ahd_send_async(ahd, devinfo.channel, devinfo.target,
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+
/*
* Allow the sequencer to continue with
* non-pack processing.
@@ -1534,6 +1515,18 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
lqistat1 = ahd_inb(ahd, LQISTAT1);
lqostat0 = ahd_inb(ahd, LQOSTAT0);
busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
+
+ /*
+ * Ignore external resets after a bus reset.
+ */
+ if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE))
+ return;
+
+ /*
+ * Clear bus reset flag
+ */
+ ahd->flags &= ~AHD_BUS_RESET_ACTIVE;
+
if ((status0 & (SELDI|SELDO)) != 0) {
u_int simode0;
@@ -2207,22 +2200,6 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
if (sent_msg == MSG_ABORT_TAG)
tag = SCB_GET_TAG(scb);
- if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) {
- /*
- * This abort is in response to an
- * unexpected switch to command phase
- * for a packetized connection. Since
- * the identify message was never sent,
- * "saved lun" is 0. We really want to
- * abort only the SCB that encountered
- * this error, which could have a different
- * lun. The SCB will be retried so the OS
- * will see the UA after renegotiating to
- * packetized.
- */
- tag = SCB_GET_TAG(scb);
- saved_lun = scb->hscb->lun;
- }
found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
tag, ROLE_INITIATOR,
CAM_REQ_ABORTED);
@@ -7847,6 +7824,17 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
int found;
u_int fifo;
u_int next_fifo;
+ uint8_t scsiseq;
+
+ /*
+ * Check if the last bus reset is cleared
+ */
+ if (ahd->flags & AHD_BUS_RESET_ACTIVE) {
+ printf("%s: bus reset still active\n",
+ ahd_name(ahd));
+ return 0;
+ }
+ ahd->flags |= AHD_BUS_RESET_ACTIVE;
ahd->pending_device = NULL;
@@ -7860,6 +7848,12 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
/* Make sure the sequencer is in a safe location. */
ahd_clear_critical_section(ahd);
+ /*
+ * Run our command complete fifos to ensure that we perform
+ * completion processing on any commands that 'completed'
+ * before the reset occurred.
+ */
+ ahd_run_qoutfifo(ahd);
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0) {
ahd_run_tqinfifo(ahd, /*paused*/TRUE);
@@ -7924,30 +7918,14 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
ahd_clear_fifo(ahd, 1);
/*
- * Revert to async/narrow transfers until we renegotiate.
+ * Reenable selections
*/
- max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
- for (target = 0; target <= max_scsiid; target++) {
-
- if (ahd->enabled_targets[target] == NULL)
- continue;
- for (initiator = 0; initiator <= max_scsiid; initiator++) {
- struct ahd_devinfo devinfo;
-
- ahd_compile_devinfo(&devinfo, target, initiator,
- CAM_LUN_WILDCARD,
- 'A', ROLE_UNKNOWN);
- ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHD_TRANS_CUR, /*paused*/TRUE);
- ahd_set_syncrate(ahd, &devinfo, /*period*/0,
- /*offset*/0, /*ppr_options*/0,
- AHD_TRANS_CUR, /*paused*/TRUE);
- }
- }
+ ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
+ scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE);
+ ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
-#ifdef AHD_TARGET_MODE
max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
-
+#ifdef AHD_TARGET_MODE
/*
* Send an immediate notify ccb to all target more peripheral
* drivers affected by this action.
@@ -7975,51 +7953,31 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
/* Notify the XPT that a bus reset occurred */
ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
- ahd_restart(ahd);
+
/*
- * Freeze the SIMQ until our poller can determine that
- * the bus reset has really gone away. We set the initial
- * timer to 0 to have the check performed as soon as possible
- * from the timer context.
+ * Revert to async/narrow transfers until we renegotiate.
*/
- if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
- ahd->flags |= AHD_RESET_POLL_ACTIVE;
- ahd_freeze_simq(ahd);
- ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
- }
- return (found);
-}
+ for (target = 0; target <= max_scsiid; target++) {
+ if (ahd->enabled_targets[target] == NULL)
+ continue;
+ for (initiator = 0; initiator <= max_scsiid; initiator++) {
+ struct ahd_devinfo devinfo;
-#define AHD_RESET_POLL_US 1000
-static void
-ahd_reset_poll(void *arg)
-{
- struct ahd_softc *ahd = arg;
- u_int scsiseq1;
- u_long s;
-
- ahd_lock(ahd, &s);
- ahd_pause(ahd);
- ahd_update_modes(ahd);
- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
- if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
- ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US,
- ahd_reset_poll, ahd);
- ahd_unpause(ahd);
- ahd_unlock(ahd, &s);
- return;
+ ahd_compile_devinfo(&devinfo, target, initiator,
+ CAM_LUN_WILDCARD,
+ 'A', ROLE_UNKNOWN);
+ ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+ AHD_TRANS_CUR, /*paused*/TRUE);
+ ahd_set_syncrate(ahd, &devinfo, /*period*/0,
+ /*offset*/0, /*ppr_options*/0,
+ AHD_TRANS_CUR, /*paused*/TRUE);
+ }
}
- /* Reset is now low. Complete chip reinitialization. */
- ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
- scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
- ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
- ahd_unpause(ahd);
- ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
- ahd_unlock(ahd, &s);
- ahd_release_simq(ahd);
+ ahd_restart(ahd);
+
+ return (found);
}
/**************************** Statistics Processing ***************************/
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index bcced0a417e6..66e4a47bb9ee 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -782,6 +782,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
{
struct ahd_softc *ahd;
int found;
+ unsigned long flags;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
#ifdef AHD_DEBUG
@@ -789,8 +790,11 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
printf("%s: Bus reset called for cmd %p\n",
ahd_name(ahd), cmd);
#endif
+ ahd_lock(ahd, &flags);
+
found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
/*initiate reset*/TRUE);
+ ahd_unlock(ahd, &flags);
if (bootverbose)
printf("%s: SCSI bus reset delivered. "
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 24e71b555172..6dc88149f9f1 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ef57f253031c..dfcb96f3e60c 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -294,18 +294,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
if (sht->unchecked_isa_dma && privsize)
gfp_mask |= __GFP_DMA;
- /* Check to see if this host has any error handling facilities */
- if (!sht->eh_strategy_handler && !sht->eh_abort_handler &&
- !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler &&
- !sht->eh_host_reset_handler) {
- printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n"
- "ERROR: This is not a safe way to run your "
- "SCSI host\n"
- "ERROR: The error handling must be added to "
- "this driver\n", sht->proc_name);
- dump_stack();
- }
-
shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
if (!shost)
return NULL;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index eaefeddb2b4a..0a8ad37ae899 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -168,7 +168,7 @@ static void release_event_pool(struct event_pool *pool,
++in_use;
if (pool->events[i].ext_list) {
dma_free_coherent(hostdata->dev,
- SG_ALL * sizeof(struct memory_descriptor),
+ SG_ALL * sizeof(struct srp_direct_buf),
pool->events[i].ext_list,
pool->events[i].ext_list_token);
}
@@ -284,40 +284,37 @@ static void set_srp_direction(struct scsi_cmnd *cmd,
struct srp_cmd *srp_cmd,
int numbuf)
{
+ u8 fmt;
+
if (numbuf == 0)
return;
- if (numbuf == 1) {
+ if (numbuf == 1)
+ fmt = SRP_DATA_DESC_DIRECT;
+ else {
+ fmt = SRP_DATA_DESC_INDIRECT;
+ numbuf = min(numbuf, MAX_INDIRECT_BUFS);
+
if (cmd->sc_data_direction == DMA_TO_DEVICE)
- srp_cmd->data_out_format = SRP_DIRECT_BUFFER;
- else
- srp_cmd->data_in_format = SRP_DIRECT_BUFFER;
- } else {
- if (cmd->sc_data_direction == DMA_TO_DEVICE) {
- srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_out_count =
- numbuf < MAX_INDIRECT_BUFS ?
- numbuf: MAX_INDIRECT_BUFS;
- } else {
- srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_in_count =
- numbuf < MAX_INDIRECT_BUFS ?
- numbuf: MAX_INDIRECT_BUFS;
- }
+ srp_cmd->data_out_desc_cnt = numbuf;
+ else
+ srp_cmd->data_in_desc_cnt = numbuf;
}
+
+ if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ srp_cmd->buf_fmt = fmt << 4;
+ else
+ srp_cmd->buf_fmt = fmt;
}
-static void unmap_sg_list(int num_entries,
+static void unmap_sg_list(int num_entries,
struct device *dev,
- struct memory_descriptor *md)
-{
+ struct srp_direct_buf *md)
+{
int i;
- for (i = 0; i < num_entries; ++i) {
- dma_unmap_single(dev,
- md[i].virtual_address,
- md[i].length, DMA_BIDIRECTIONAL);
- }
+ for (i = 0; i < num_entries; ++i)
+ dma_unmap_single(dev, md[i].va, md[i].len, DMA_BIDIRECTIONAL);
}
/**
@@ -330,23 +327,26 @@ static void unmap_cmd_data(struct srp_cmd *cmd,
struct srp_event_struct *evt_struct,
struct device *dev)
{
- if ((cmd->data_out_format == SRP_NO_BUFFER) &&
- (cmd->data_in_format == SRP_NO_BUFFER))
+ u8 out_fmt, in_fmt;
+
+ out_fmt = cmd->buf_fmt >> 4;
+ in_fmt = cmd->buf_fmt & ((1U << 4) - 1);
+
+ if (out_fmt == SRP_NO_DATA_DESC && in_fmt == SRP_NO_DATA_DESC)
return;
- else if ((cmd->data_out_format == SRP_DIRECT_BUFFER) ||
- (cmd->data_in_format == SRP_DIRECT_BUFFER)) {
- struct memory_descriptor *data =
- (struct memory_descriptor *)cmd->additional_data;
- dma_unmap_single(dev, data->virtual_address, data->length,
- DMA_BIDIRECTIONAL);
+ else if (out_fmt == SRP_DATA_DESC_DIRECT ||
+ in_fmt == SRP_DATA_DESC_DIRECT) {
+ struct srp_direct_buf *data =
+ (struct srp_direct_buf *) cmd->add_data;
+ dma_unmap_single(dev, data->va, data->len, DMA_BIDIRECTIONAL);
} else {
- struct indirect_descriptor *indirect =
- (struct indirect_descriptor *)cmd->additional_data;
- int num_mapped = indirect->head.length /
- sizeof(indirect->list[0]);
+ struct srp_indirect_buf *indirect =
+ (struct srp_indirect_buf *) cmd->add_data;
+ int num_mapped = indirect->table_desc.len /
+ sizeof(struct srp_direct_buf);
if (num_mapped <= MAX_INDIRECT_BUFS) {
- unmap_sg_list(num_mapped, dev, &indirect->list[0]);
+ unmap_sg_list(num_mapped, dev, &indirect->desc_list[0]);
return;
}
@@ -356,17 +356,17 @@ static void unmap_cmd_data(struct srp_cmd *cmd,
static int map_sg_list(int num_entries,
struct scatterlist *sg,
- struct memory_descriptor *md)
+ struct srp_direct_buf *md)
{
int i;
u64 total_length = 0;
for (i = 0; i < num_entries; ++i) {
- struct memory_descriptor *descr = md + i;
+ struct srp_direct_buf *descr = md + i;
struct scatterlist *sg_entry = &sg[i];
- descr->virtual_address = sg_dma_address(sg_entry);
- descr->length = sg_dma_len(sg_entry);
- descr->memory_handle = 0;
+ descr->va = sg_dma_address(sg_entry);
+ descr->len = sg_dma_len(sg_entry);
+ descr->key = 0;
total_length += sg_dma_len(sg_entry);
}
return total_length;
@@ -389,10 +389,10 @@ static int map_sg_data(struct scsi_cmnd *cmd,
int sg_mapped;
u64 total_length = 0;
struct scatterlist *sg = cmd->request_buffer;
- struct memory_descriptor *data =
- (struct memory_descriptor *)srp_cmd->additional_data;
- struct indirect_descriptor *indirect =
- (struct indirect_descriptor *)data;
+ struct srp_direct_buf *data =
+ (struct srp_direct_buf *) srp_cmd->add_data;
+ struct srp_indirect_buf *indirect =
+ (struct srp_indirect_buf *) data;
sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
@@ -403,9 +403,9 @@ static int map_sg_data(struct scsi_cmnd *cmd,
/* special case; we can use a single direct descriptor */
if (sg_mapped == 1) {
- data->virtual_address = sg_dma_address(&sg[0]);
- data->length = sg_dma_len(&sg[0]);
- data->memory_handle = 0;
+ data->va = sg_dma_address(&sg[0]);
+ data->len = sg_dma_len(&sg[0]);
+ data->key = 0;
return 1;
}
@@ -416,25 +416,26 @@ static int map_sg_data(struct scsi_cmnd *cmd,
return 0;
}
- indirect->head.virtual_address = 0;
- indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
- indirect->head.memory_handle = 0;
+ indirect->table_desc.va = 0;
+ indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf);
+ indirect->table_desc.key = 0;
if (sg_mapped <= MAX_INDIRECT_BUFS) {
- total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]);
- indirect->total_length = total_length;
+ total_length = map_sg_list(sg_mapped, sg,
+ &indirect->desc_list[0]);
+ indirect->len = total_length;
return 1;
}
/* get indirect table */
if (!evt_struct->ext_list) {
- evt_struct->ext_list =(struct memory_descriptor*)
+ evt_struct->ext_list = (struct srp_direct_buf *)
dma_alloc_coherent(dev,
- SG_ALL * sizeof(struct memory_descriptor),
- &evt_struct->ext_list_token, 0);
+ SG_ALL * sizeof(struct srp_direct_buf),
+ &evt_struct->ext_list_token, 0);
if (!evt_struct->ext_list) {
- printk(KERN_ERR
- "ibmvscsi: Can't allocate memory for indirect table\n");
+ printk(KERN_ERR
+ "ibmvscsi: Can't allocate memory for indirect table\n");
return 0;
}
@@ -442,11 +443,11 @@ static int map_sg_data(struct scsi_cmnd *cmd,
total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list);
- indirect->total_length = total_length;
- indirect->head.virtual_address = evt_struct->ext_list_token;
- indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
- memcpy(indirect->list, evt_struct->ext_list,
- MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor));
+ indirect->len = total_length;
+ indirect->table_desc.va = evt_struct->ext_list_token;
+ indirect->table_desc.len = sg_mapped * sizeof(indirect->desc_list[0]);
+ memcpy(indirect->desc_list, evt_struct->ext_list,
+ MAX_INDIRECT_BUFS * sizeof(struct srp_direct_buf));
return 1;
}
@@ -463,20 +464,20 @@ static int map_sg_data(struct scsi_cmnd *cmd,
static int map_single_data(struct scsi_cmnd *cmd,
struct srp_cmd *srp_cmd, struct device *dev)
{
- struct memory_descriptor *data =
- (struct memory_descriptor *)srp_cmd->additional_data;
+ struct srp_direct_buf *data =
+ (struct srp_direct_buf *) srp_cmd->add_data;
- data->virtual_address =
+ data->va =
dma_map_single(dev, cmd->request_buffer,
cmd->request_bufflen,
DMA_BIDIRECTIONAL);
- if (dma_mapping_error(data->virtual_address)) {
+ if (dma_mapping_error(data->va)) {
printk(KERN_ERR
"ibmvscsi: Unable to map request_buffer for command!\n");
return 0;
}
- data->length = cmd->request_bufflen;
- data->memory_handle = 0;
+ data->len = cmd->request_bufflen;
+ data->key = 0;
set_srp_direction(cmd, srp_cmd, 1);
@@ -548,7 +549,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
/* Copy the IU into the transfer area */
*evt_struct->xfer_iu = evt_struct->iu;
- evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;
+ evt_struct->xfer_iu->srp.rsp.tag = (u64)evt_struct;
/* Add this to the sent list. We need to do this
* before we actually send
@@ -586,27 +587,27 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
struct scsi_cmnd *cmnd = evt_struct->cmnd;
- if (unlikely(rsp->type != SRP_RSP_TYPE)) {
+ if (unlikely(rsp->opcode != SRP_RSP)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: bad SRP RSP type %d\n",
- rsp->type);
+ rsp->opcode);
}
if (cmnd) {
cmnd->result = rsp->status;
if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
memcpy(cmnd->sense_buffer,
- rsp->sense_and_response_data,
- rsp->sense_data_list_length);
+ rsp->data,
+ rsp->sense_data_len);
unmap_cmd_data(&evt_struct->iu.srp.cmd,
evt_struct,
evt_struct->hostdata->dev);
- if (rsp->doover)
- cmnd->resid = rsp->data_out_residual_count;
- else if (rsp->diover)
- cmnd->resid = rsp->data_in_residual_count;
+ if (rsp->flags & SRP_RSP_FLAG_DOOVER)
+ cmnd->resid = rsp->data_out_res_cnt;
+ else if (rsp->flags & SRP_RSP_FLAG_DIOVER)
+ cmnd->resid = rsp->data_in_res_cnt;
}
if (evt_struct->cmnd_done)
@@ -633,10 +634,11 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
{
struct srp_cmd *srp_cmd;
struct srp_event_struct *evt_struct;
- struct indirect_descriptor *indirect;
+ struct srp_indirect_buf *indirect;
struct ibmvscsi_host_data *hostdata =
(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
u16 lun = lun_from_dev(cmnd->device);
+ u8 out_fmt, in_fmt;
evt_struct = get_event_struct(&hostdata->pool);
if (!evt_struct)
@@ -644,8 +646,8 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
/* Set up the actual SRP IU */
srp_cmd = &evt_struct->iu.srp.cmd;
- memset(srp_cmd, 0x00, sizeof(*srp_cmd));
- srp_cmd->type = SRP_CMD_TYPE;
+ memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
+ srp_cmd->opcode = SRP_CMD;
memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
srp_cmd->lun = ((u64) lun) << 48;
@@ -664,13 +666,15 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
evt_struct->cmnd_done = done;
/* Fix up dma address of the buffer itself */
- indirect = (struct indirect_descriptor *)srp_cmd->additional_data;
- if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
- (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) &&
- (indirect->head.virtual_address == 0)) {
- indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
- offsetof(struct srp_cmd, additional_data) +
- offsetof(struct indirect_descriptor, list);
+ indirect = (struct srp_indirect_buf *) srp_cmd->add_data;
+ out_fmt = srp_cmd->buf_fmt >> 4;
+ in_fmt = srp_cmd->buf_fmt & ((1U << 4) - 1);
+ if ((in_fmt == SRP_DATA_DESC_INDIRECT ||
+ out_fmt == SRP_DATA_DESC_INDIRECT) &&
+ indirect->table_desc.va == 0) {
+ indirect->table_desc.va = evt_struct->crq.IU_data_ptr +
+ offsetof(struct srp_cmd, add_data) +
+ offsetof(struct srp_indirect_buf, desc_list);
}
return ibmvscsi_send_srp_event(evt_struct, hostdata);
@@ -780,10 +784,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
static void login_rsp(struct srp_event_struct *evt_struct)
{
struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
- switch (evt_struct->xfer_iu->srp.generic.type) {
- case SRP_LOGIN_RSP_TYPE: /* it worked! */
+ switch (evt_struct->xfer_iu->srp.login_rsp.opcode) {
+ case SRP_LOGIN_RSP: /* it worked! */
break;
- case SRP_LOGIN_REJ_TYPE: /* refused! */
+ case SRP_LOGIN_REJ: /* refused! */
printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
evt_struct->xfer_iu->srp.login_rej.reason);
/* Login failed. */
@@ -792,7 +796,7 @@ static void login_rsp(struct srp_event_struct *evt_struct)
default:
printk(KERN_ERR
"ibmvscsi: Invalid login response typecode 0x%02x!\n",
- evt_struct->xfer_iu->srp.generic.type);
+ evt_struct->xfer_iu->srp.login_rsp.opcode);
/* Login failed. */
atomic_set(&hostdata->request_limit, -1);
return;
@@ -800,17 +804,17 @@ static void login_rsp(struct srp_event_struct *evt_struct)
printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
- if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >
+ if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
(max_requests - 2))
- evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =
+ evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
max_requests - 2;
/* Now we know what the real request-limit is */
atomic_set(&hostdata->request_limit,
- evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);
+ evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
hostdata->host->can_queue =
- evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;
+ evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
if (hostdata->host->can_queue < 1) {
printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
@@ -849,18 +853,19 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
login = &evt_struct->iu.srp.login_req;
memset(login, 0x00, sizeof(struct srp_login_req));
- login->type = SRP_LOGIN_REQ_TYPE;
- login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
- login->required_buffer_formats = 0x0006;
+ login->opcode = SRP_LOGIN_REQ;
+ login->req_it_iu_len = sizeof(union srp_iu);
+ login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
/* Start out with a request limit of 1, since this is negotiated in
* the login request we are just sending
*/
atomic_set(&hostdata->request_limit, 1);
- spin_lock_irqsave(hostdata->host->host_lock, flags);
rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ printk("ibmvscsic: sent SRP login\n");
return rc;
};
@@ -928,13 +933,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
/* Set up an abort SRP command */
memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
- tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = ((u64) lun) << 48;
- tsk_mgmt->task_mgmt_flags = 0x01; /* ABORT TASK */
- tsk_mgmt->managed_task_tag = (u64) found_evt;
+ tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
+ tsk_mgmt->task_tag = (u64) found_evt;
printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
- tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+ tsk_mgmt->lun, tsk_mgmt->task_tag);
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
@@ -948,25 +953,25 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
/* make sure we got a good response */
- if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: abort bad SRP RSP type %d\n",
- srp_rsp.srp.generic.type);
+ srp_rsp.srp.rsp.opcode);
return FAILED;
}
- if (srp_rsp.srp.rsp.rspvalid)
- rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.data);
else
rsp_rc = srp_rsp.srp.rsp.status;
if (rsp_rc) {
if (printk_ratelimit())
printk(KERN_WARNING
- "ibmvscsi: abort code %d for task tag 0x%lx\n",
+ "ibmvscsi: abort code %d for task tag 0x%lx\n",
rsp_rc,
- tsk_mgmt->managed_task_tag);
+ tsk_mgmt->task_tag);
return FAILED;
}
@@ -987,13 +992,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_INFO
"ibmvscsi: aborted task tag 0x%lx completed\n",
- tsk_mgmt->managed_task_tag);
+ tsk_mgmt->task_tag);
return SUCCESS;
}
printk(KERN_INFO
"ibmvscsi: successfully aborted task tag 0x%lx\n",
- tsk_mgmt->managed_task_tag);
+ tsk_mgmt->task_tag);
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
@@ -1040,9 +1045,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
/* Set up a lun reset SRP command */
memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
- tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = ((u64) lun) << 48;
- tsk_mgmt->task_mgmt_flags = 0x08; /* LUN RESET */
+ tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
tsk_mgmt->lun);
@@ -1059,16 +1064,16 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
/* make sure we got a good response */
- if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: reset bad SRP RSP type %d\n",
- srp_rsp.srp.generic.type);
+ srp_rsp.srp.rsp.opcode);
return FAILED;
}
- if (srp_rsp.srp.rsp.rspvalid)
- rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.data);
else
rsp_rc = srp_rsp.srp.rsp.status;
@@ -1076,8 +1081,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: reset code %d for task tag 0x%lx\n",
- rsp_rc,
- tsk_mgmt->managed_task_tag);
+ rsp_rc, tsk_mgmt->task_tag);
return FAILED;
}
@@ -1179,6 +1183,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
/* We need to re-setup the interpartition connection */
printk(KERN_INFO
"ibmvscsi: Re-enabling adapter!\n");
+ atomic_set(&hostdata->request_limit, -1);
purge_requests(hostdata, DID_REQUEUE);
if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
hostdata) == 0)
@@ -1226,7 +1231,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
}
if (crq->format == VIOSRP_SRP_FORMAT)
- atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
+ atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta,
&hostdata->request_limit);
if (evt_struct->done)
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 4550d71e4744..5c6d93582929 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -68,7 +68,7 @@ struct srp_event_struct {
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
union viosrp_iu *sync_srp;
- struct memory_descriptor *ext_list;
+ struct srp_direct_buf *ext_list;
dma_addr_t ext_list_token;
};
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index f47dd87c05e7..1a9992bdfef8 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -34,7 +34,6 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include "ibmvscsi.h"
-#include "srp.h"
static char partition_name[97] = "UNKNOWN";
static unsigned int partition_number = -1;
@@ -80,7 +79,7 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
tasklet_kill(&hostdata->srp_task);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
- } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
dma_unmap_single(hostdata->dev,
queue->msg_token,
queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
@@ -230,7 +229,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
- if (rc == H_Resource)
+ if (rc == H_RESOURCE)
/* maybe kexecing and resource is busy. try a reset */
rc = ibmvscsi_reset_crq_queue(queue,
hostdata);
@@ -269,7 +268,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
req_irq_failed:
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
- } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
reg_crq_failed:
dma_unmap_single(hostdata->dev,
queue->msg_token,
@@ -295,7 +294,7 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
/* Re-enable the CRQ */
do {
rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
- } while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
if (rc)
printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
@@ -317,7 +316,7 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
/* Close the CRQ */
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
- } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
/* Clean out the queue */
memset(queue->msgs, 0x00, PAGE_SIZE);
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
deleted file mode 100644
index 7d8e4c4accb9..000000000000
--- a/drivers/scsi/ibmvscsi/srp.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*****************************************************************************/
-/* srp.h -- SCSI RDMA Protocol definitions */
-/* */
-/* Written By: Colin Devilbis, IBM Corporation */
-/* */
-/* Copyright (C) 2003 IBM Corporation */
-/* */
-/* This program is free software; you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation; 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 */
-/* */
-/* */
-/* This file contains structures and definitions for the SCSI RDMA Protocol */
-/* (SRP) as defined in the T10 standard available at www.t10.org. This */
-/* file was based on the 16a version of the standard */
-/* */
-/*****************************************************************************/
-#ifndef SRP_H
-#define SRP_H
-
-#define SRP_VERSION "16.a"
-
-#define PACKED __attribute__((packed))
-
-enum srp_types {
- SRP_LOGIN_REQ_TYPE = 0x00,
- SRP_LOGIN_RSP_TYPE = 0xC0,
- SRP_LOGIN_REJ_TYPE = 0xC2,
- SRP_I_LOGOUT_TYPE = 0x03,
- SRP_T_LOGOUT_TYPE = 0x80,
- SRP_TSK_MGMT_TYPE = 0x01,
- SRP_CMD_TYPE = 0x02,
- SRP_RSP_TYPE = 0xC1,
- SRP_CRED_REQ_TYPE = 0x81,
- SRP_CRED_RSP_TYPE = 0x41,
- SRP_AER_REQ_TYPE = 0x82,
- SRP_AER_RSP_TYPE = 0x42
-};
-
-enum srp_descriptor_formats {
- SRP_NO_BUFFER = 0x00,
- SRP_DIRECT_BUFFER = 0x01,
- SRP_INDIRECT_BUFFER = 0x02
-};
-
-struct memory_descriptor {
- u64 virtual_address;
- u32 memory_handle;
- u32 length;
-};
-
-struct indirect_descriptor {
- struct memory_descriptor head;
- u32 total_length;
- struct memory_descriptor list[1] PACKED;
-};
-
-struct srp_generic {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-struct srp_login_req {
- u8 type;
- u8 reserved1[7];
- u64 tag;
- u32 max_requested_initiator_to_target_iulen;
- u32 reserved2;
- u16 required_buffer_formats;
- u8 reserved3:6;
- u8 multi_channel_action:2;
- u8 reserved4;
- u32 reserved5;
- u8 initiator_port_identifier[16];
- u8 target_port_identifier[16];
-};
-
-struct srp_login_rsp {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
- u32 max_initiator_to_target_iulen;
- u32 max_target_to_initiator_iulen;
- u16 supported_buffer_formats;
- u8 reserved2:6;
- u8 multi_channel_result:2;
- u8 reserved3;
- u8 reserved4[24];
-};
-
-struct srp_login_rej {
- u8 type;
- u8 reserved1[3];
- u32 reason;
- u64 tag;
- u64 reserved2;
- u16 supported_buffer_formats;
- u8 reserved3[6];
-};
-
-struct srp_i_logout {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-struct srp_t_logout {
- u8 type;
- u8 reserved1[3];
- u32 reason;
- u64 tag;
-};
-
-struct srp_tsk_mgmt {
- u8 type;
- u8 reserved1[7];
- u64 tag;
- u32 reserved2;
- u64 lun PACKED;
- u8 reserved3;
- u8 reserved4;
- u8 task_mgmt_flags;
- u8 reserved5;
- u64 managed_task_tag;
- u64 reserved6;
-};
-
-struct srp_cmd {
- u8 type;
- u32 reserved1 PACKED;
- u8 data_out_format:4;
- u8 data_in_format:4;
- u8 data_out_count;
- u8 data_in_count;
- u64 tag;
- u32 reserved2;
- u64 lun PACKED;
- u8 reserved3;
- u8 reserved4:5;
- u8 task_attribute:3;
- u8 reserved5;
- u8 additional_cdb_len;
- u8 cdb[16];
- u8 additional_data[0x100 - 0x30];
-};
-
-struct srp_rsp {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
- u16 reserved2;
- u8 reserved3:2;
- u8 diunder:1;
- u8 diover:1;
- u8 dounder:1;
- u8 doover:1;
- u8 snsvalid:1;
- u8 rspvalid:1;
- u8 status;
- u32 data_in_residual_count;
- u32 data_out_residual_count;
- u32 sense_data_list_length;
- u32 response_data_list_length;
- u8 sense_and_response_data[18];
-};
-
-struct srp_cred_req {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
-};
-
-struct srp_cred_rsp {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-struct srp_aer_req {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
- u32 reserved2;
- u64 lun;
- u32 sense_data_list_length;
- u32 reserved3;
- u8 sense_data[20];
-};
-
-struct srp_aer_rsp {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-union srp_iu {
- struct srp_generic generic;
- struct srp_login_req login_req;
- struct srp_login_rsp login_rsp;
- struct srp_login_rej login_rej;
- struct srp_i_logout i_logout;
- struct srp_t_logout t_logout;
- struct srp_tsk_mgmt tsk_mgmt;
- struct srp_cmd cmd;
- struct srp_rsp rsp;
- struct srp_cred_req cred_req;
- struct srp_cred_rsp cred_rsp;
- struct srp_aer_req aer_req;
- struct srp_aer_rsp aer_rsp;
-};
-
-#endif
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
index 6a6bba8a2f34..90f1a61283ad 100644
--- a/drivers/scsi/ibmvscsi/viosrp.h
+++ b/drivers/scsi/ibmvscsi/viosrp.h
@@ -33,7 +33,22 @@
/*****************************************************************************/
#ifndef VIOSRP_H
#define VIOSRP_H
-#include "srp.h"
+#include <scsi/srp.h>
+
+#define SRP_VERSION "16.a"
+#define SRP_MAX_IU_LEN 256
+
+union srp_iu {
+ struct srp_login_req login_req;
+ struct srp_login_rsp login_rsp;
+ struct srp_login_rej login_rej;
+ struct srp_i_logout i_logout;
+ struct srp_t_logout t_logout;
+ struct srp_tsk_mgmt tsk_mgmt;
+ struct srp_cmd cmd;
+ struct srp_rsp rsp;
+ u8 reserved[SRP_MAX_IU_LEN];
+};
enum viosrp_crq_formats {
VIOSRP_SRP_FORMAT = 0x01,
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5890e5f92d82..8b80e59c8c52 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -164,29 +164,6 @@ MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when init
MODULE_LICENSE("GPL");
MODULE_VERSION(IPR_DRIVER_VERSION);
-static const char *ipr_gpdd_dev_end_states[] = {
- "Command complete",
- "Terminated by host",
- "Terminated by device reset",
- "Terminated by bus reset",
- "Unknown",
- "Command not started"
-};
-
-static const char *ipr_gpdd_dev_bus_phases[] = {
- "Bus free",
- "Arbitration",
- "Selection",
- "Message out",
- "Command",
- "Message in",
- "Data out",
- "Data in",
- "Status",
- "Reselection",
- "Unknown"
-};
-
/* A constant array of IOASCs/URCs/Error Messages */
static const
struct ipr_error_table_t ipr_error_table[] = {
@@ -869,8 +846,8 @@ static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg,
if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) {
if (res->sdev) {
- res->sdev->hostdata = NULL;
res->del_from_ml = 1;
+ res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
if (ioa_cfg->allow_ml_add_del)
schedule_work(&ioa_cfg->work_q);
} else
@@ -1356,8 +1333,8 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
return;
if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) {
- ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
- "%s\n", ipr_error_table[error_index].error);
+ ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
+ "%s\n", ipr_error_table[error_index].error);
} else {
dev_err(&ioa_cfg->pdev->dev, "%s\n",
ipr_error_table[error_index].error);
@@ -2107,7 +2084,6 @@ restart:
did_work = 1;
sdev = res->sdev;
if (!scsi_device_get(sdev)) {
- res->sdev = NULL;
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_remove_device(sdev);
@@ -2124,6 +2100,7 @@ restart:
bus = res->cfgte.res_addr.bus;
target = res->cfgte.res_addr.target;
lun = res->cfgte.res_addr.lun;
+ res->add_to_ml = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_add_device(ioa_cfg->host, bus, target, lun);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -3214,7 +3191,7 @@ static int ipr_slave_configure(struct scsi_device *sdev)
sdev->timeout = IPR_VSET_RW_TIMEOUT;
blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
}
- if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+ if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
sdev->allow_restart = 1;
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
}
@@ -3304,6 +3281,44 @@ static int ipr_eh_host_reset(struct scsi_cmnd * cmd)
}
/**
+ * ipr_device_reset - Reset the device
+ * @ioa_cfg: ioa config struct
+ * @res: resource entry struct
+ *
+ * This function issues a device reset to the affected device.
+ * If the device is a SCSI device, a LUN reset will be sent
+ * to the device first. If that does not work, a target reset
+ * will be sent.
+ *
+ * Return value:
+ * 0 on success / non-zero on failure
+ **/
+static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
+ struct ipr_resource_entry *res)
+{
+ struct ipr_cmnd *ipr_cmd;
+ struct ipr_ioarcb *ioarcb;
+ struct ipr_cmd_pkt *cmd_pkt;
+ u32 ioasc;
+
+ ENTER;
+ ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
+ ioarcb = &ipr_cmd->ioarcb;
+ cmd_pkt = &ioarcb->cmd_pkt;
+
+ ioarcb->res_handle = res->cfgte.res_handle;
+ cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
+ cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
+
+ ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
+ ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+ list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+
+ LEAVE;
+ return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
+}
+
+/**
* ipr_eh_dev_reset - Reset the device
* @scsi_cmd: scsi command struct
*
@@ -3319,8 +3334,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
struct ipr_cmnd *ipr_cmd;
struct ipr_ioa_cfg *ioa_cfg;
struct ipr_resource_entry *res;
- struct ipr_cmd_pkt *cmd_pkt;
- u32 ioasc;
+ int rc;
ENTER;
ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
@@ -3347,25 +3361,12 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
}
res->resetting_device = 1;
-
- ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
-
- ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
- cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
- cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
- cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
-
- ipr_sdev_err(scsi_cmd->device, "Resetting device\n");
- ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
-
- ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
-
+ scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n");
+ rc = ipr_device_reset(ioa_cfg, res);
res->resetting_device = 0;
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-
LEAVE;
- return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS);
+ return (rc ? FAILED : SUCCESS);
}
static int ipr_eh_dev_reset(struct scsi_cmnd * cmd)
@@ -3440,7 +3441,7 @@ static void ipr_abort_timeout(struct ipr_cmnd *ipr_cmd)
return;
}
- ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n");
+ sdev_printk(KERN_ERR, ipr_cmd->u.sdev, "Abort timed out. Resetting bus.\n");
reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
ipr_cmd->sibling = reset_cmd;
reset_cmd->sibling = ipr_cmd;
@@ -3504,7 +3505,8 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
ipr_cmd->u.sdev = scsi_cmd->device;
- ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
+ scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n",
+ scsi_cmd->cmnd[0]);
ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
@@ -3815,8 +3817,8 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
scsi_cmd->result |= (DID_ERROR << 16);
- ipr_sdev_err(scsi_cmd->device,
- "Request Sense failed with IOASC: 0x%08X\n", ioasc);
+ scmd_printk(KERN_ERR, scsi_cmd,
+ "Request Sense failed with IOASC: 0x%08X\n", ioasc);
} else {
memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer,
SCSI_SENSE_BUFFERSIZE);
@@ -3938,6 +3940,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd)
* ipr_dump_ioasa - Dump contents of IOASA
* @ioa_cfg: ioa config struct
* @ipr_cmd: ipr command struct
+ * @res: resource entry struct
*
* This function is invoked by the interrupt handler when ops
* fail. It will log the IOASA if appropriate. Only called
@@ -3947,7 +3950,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd)
* none
**/
static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
- struct ipr_cmnd *ipr_cmd)
+ struct ipr_cmnd *ipr_cmd, struct ipr_resource_entry *res)
{
int i;
u16 data_len;
@@ -3975,16 +3978,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
return;
}
- ipr_sdev_err(ipr_cmd->scsi_cmd->device, "%s\n",
- ipr_error_table[error_index].error);
-
- if ((ioasa->u.gpdd.end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) &&
- (ioasa->u.gpdd.bus_phase <= ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) {
- ipr_sdev_err(ipr_cmd->scsi_cmd->device,
- "Device End state: %s Phase: %s\n",
- ipr_gpdd_dev_end_states[ioasa->u.gpdd.end_state],
- ipr_gpdd_dev_bus_phases[ioasa->u.gpdd.bus_phase]);
- }
+ ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error);
if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len))
data_len = sizeof(struct ipr_ioasa);
@@ -4141,7 +4135,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
}
if (ipr_is_gscsi(res))
- ipr_dump_ioasa(ioa_cfg, ipr_cmd);
+ ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
else
ipr_gen_sense(ipr_cmd);
@@ -4540,7 +4534,7 @@ static int ipr_set_supported_devs(struct ipr_cmnd *ipr_cmd)
ipr_cmd->job_step = ipr_ioa_reset_done;
list_for_each_entry_continue(res, &ioa_cfg->used_res_q, queue) {
- if (!IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+ if (!ipr_is_scsi_disk(res))
continue;
ipr_cmd->u.res = res;
@@ -4980,7 +4974,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
list_for_each_entry_safe(res, temp, &old_res, queue) {
if (res->sdev) {
res->del_from_ml = 1;
- res->sdev->hostdata = NULL;
+ res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
list_move_tail(&res->queue, &ioa_cfg->used_res_q);
} else {
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index fd360bfe56dd..1ad24df69d70 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.2"
-#define IPR_DRIVER_DATE "(February 8, 2006)"
+#define IPR_DRIVER_VERSION "2.1.3"
+#define IPR_DRIVER_DATE "(March 29, 2006)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -133,6 +133,7 @@
#define IPR_MAX_SCSI_RATE(width) ((320 * 10) / ((width) / 8))
#define IPR_IOA_RES_HANDLE 0xffffffff
+#define IPR_INVALID_RES_HANDLE 0
#define IPR_IOA_RES_ADDR 0x00ffffff
/*
@@ -1191,30 +1192,17 @@ struct ipr_ucode_image_header {
*/
#define ipr_err(...) printk(KERN_ERR IPR_NAME ": "__VA_ARGS__)
#define ipr_info(...) printk(KERN_INFO IPR_NAME ": "__VA_ARGS__)
-#define ipr_crit(...) printk(KERN_CRIT IPR_NAME ": "__VA_ARGS__)
-#define ipr_warn(...) printk(KERN_WARNING IPR_NAME": "__VA_ARGS__)
#define ipr_dbg(...) IPR_DBG_CMD(printk(KERN_INFO IPR_NAME ": "__VA_ARGS__))
-#define ipr_sdev_printk(level, sdev, fmt, args...) \
- sdev_printk(level, sdev, fmt, ## args)
+#define ipr_ra_printk(level, ioa_cfg, ra, fmt, ...) \
+ printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, (ioa_cfg)->host->host_no, \
+ (ra).bus, (ra).target, (ra).lun, ##__VA_ARGS__)
-#define ipr_sdev_err(sdev, fmt, ...) \
- ipr_sdev_printk(KERN_ERR, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_info(sdev, fmt, ...) \
- ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_dbg(sdev, fmt, ...) \
- IPR_DBG_CMD(ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__))
-
-#define ipr_res_printk(level, ioa_cfg, res, fmt, ...) \
- printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, ioa_cfg->host->host_no, \
- res.bus, res.target, res.lun, ##__VA_ARGS__)
+#define ipr_ra_err(ioa_cfg, ra, fmt, ...) \
+ ipr_ra_printk(KERN_ERR, ioa_cfg, ra, fmt, ##__VA_ARGS__)
#define ipr_res_err(ioa_cfg, res, fmt, ...) \
- ipr_res_printk(KERN_ERR, ioa_cfg, res, fmt, ##__VA_ARGS__)
-#define ipr_res_dbg(ioa_cfg, res, fmt, ...) \
- IPR_DBG_CMD(ipr_res_printk(KERN_INFO, ioa_cfg, res, fmt, ##__VA_ARGS__))
+ ipr_ra_err(ioa_cfg, (res)->cfgte.res_addr, fmt, ##__VA_ARGS__)
#define ipr_phys_res_err(ioa_cfg, res, fmt, ...) \
{ \
@@ -1304,6 +1292,22 @@ static inline int ipr_is_gscsi(struct ipr_resource_entry *res)
}
/**
+ * ipr_is_scsi_disk - Determine if a resource is a SCSI disk
+ * @res: resource entry struct
+ *
+ * Return value:
+ * 1 if SCSI disk / 0 if not SCSI disk
+ **/
+static inline int ipr_is_scsi_disk(struct ipr_resource_entry *res)
+{
+ if (ipr_is_af_dasd_device(res) ||
+ (ipr_is_gscsi(res) && IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)))
+ return 1;
+ else
+ return 0;
+}
+
+/**
* ipr_is_naca_model - Determine if a resource is using NACA queueing model
* @res: resource entry struct
*
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index e63c1ff1e102..bd147207f25d 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4938,7 +4938,6 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
-EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 53f5b0d9161c..a0289ec3e283 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -53,6 +53,7 @@
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+static void ata_scsi_error(struct Scsi_Host *host);
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
#define RW_RECOVERY_MPAGE 0x1
@@ -99,6 +100,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
* It just needs the eh_timed_out hook.
*/
struct scsi_transport_template ata_scsi_transport_template = {
+ .eh_strategy_handler = ata_scsi_error,
.eh_timed_out = ata_scsi_timed_out,
};
@@ -772,12 +774,9 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
*
* LOCKING:
* Inherited from SCSI layer (none, can sleep)
- *
- * RETURNS:
- * Zero.
*/
-int ata_scsi_error(struct Scsi_Host *host)
+static void ata_scsi_error(struct Scsi_Host *host)
{
struct ata_port *ap;
unsigned long flags;
@@ -805,7 +804,6 @@ int ata_scsi_error(struct Scsi_Host *host)
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT\n");
- return 0;
}
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 1c755b14521a..bac8cbae06fe 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct scsi_transport_template ata_scsi_transport_template;
extern void ata_scsi_scan_host(struct ata_port *ap);
-extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 5609847e254a..ee449b29fc82 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -89,29 +89,29 @@ MODULE_LICENSE("Dual MPL/GPL");
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
} scsi_info_t;
-static void aha152x_release_cs(dev_link_t *link);
+static void aha152x_release_cs(struct pcmcia_device *link);
static void aha152x_detach(struct pcmcia_device *p_dev);
-static void aha152x_config_cs(dev_link_t *link);
+static int aha152x_config_cs(struct pcmcia_device *link);
-static dev_link_t *dev_list;
+static struct pcmcia_device *dev_list;
-static int aha152x_attach(struct pcmcia_device *p_dev)
+static int aha152x_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
-
+
DEBUG(0, "aha152x_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link; link->priv = info;
+ info->p_dev = link;
+ link->priv = info;
link->io.NumPorts1 = 0x20;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -119,41 +119,22 @@ static int aha152x_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- aha152x_config_cs(link);
-
- return 0;
+ return aha152x_config_cs(link);
} /* aha152x_attach */
/*====================================================================*/
-static void aha152x_detach(struct pcmcia_device *p_dev)
+static void aha152x_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- dev_link_t **linkp;
-
DEBUG(0, "aha152x_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
- if (link->state & DEV_CONFIG)
- aha152x_release_cs(link);
+ aha152x_release_cs(link);
/* Unlink device structure, free bits */
- *linkp = link->next;
kfree(link->priv);
-
} /* aha152x_detach */
/*====================================================================*/
@@ -161,9 +142,8 @@ static void aha152x_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void aha152x_config_cs(dev_link_t *link)
+static int aha152x_config_cs(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
scsi_info_t *info = link->priv;
struct aha152x_setup s;
tuple_t tuple;
@@ -178,19 +158,16 @@ static void aha152x_config_cs(dev_link_t *link)
tuple.TupleData = tuple_data;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
/* For New Media T&J, look for a SCSI window */
if (parse.cftable_entry.io.win[0].len >= 0x20)
@@ -201,15 +178,15 @@ static void aha152x_config_cs(dev_link_t *link)
if ((parse.cftable_entry.io.nwin > 0) &&
(link->io.BasePort1 < 0xffff)) {
link->conf.ConfigIndex = parse.cftable_entry.index;
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/* Set configuration options for the aha152x driver */
memset(&s, 0, sizeof(s));
@@ -231,53 +208,30 @@ static void aha152x_config_cs(dev_link_t *link)
}
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
aha152x_release_cs(link);
- return;
+ return -ENODEV;
}
-static void aha152x_release_cs(dev_link_t *link)
+static void aha152x_release_cs(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
aha152x_release(info->host);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int aha152x_suspend(struct pcmcia_device *dev)
+static int aha152x_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int aha152x_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- aha152x_host_reset_host(info->host);
- }
+ aha152x_host_reset_host(info->host);
return 0;
}
@@ -297,10 +251,9 @@ static struct pcmcia_driver aha152x_cs_driver = {
.drv = {
.name = "aha152x_cs",
},
- .probe = aha152x_attach,
+ .probe = aha152x_probe,
.remove = aha152x_detach,
.id_table = aha152x_ids,
- .suspend = aha152x_suspend,
.resume = aha152x_resume,
};
@@ -317,4 +270,3 @@ static void __exit exit_aha152x_cs(void)
module_init(init_aha152x_cs);
module_exit(exit_aha152x_cs);
-
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 788c58d805f3..85f7ffac19a0 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -73,57 +73,48 @@ static char *version =
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
} scsi_info_t;
-static void fdomain_release(dev_link_t *link);
+static void fdomain_release(struct pcmcia_device *link);
static void fdomain_detach(struct pcmcia_device *p_dev);
-static void fdomain_config(dev_link_t *link);
+static int fdomain_config(struct pcmcia_device *link);
-static int fdomain_attach(struct pcmcia_device *p_dev)
+static int fdomain_probe(struct pcmcia_device *link)
{
- scsi_info_t *info;
- dev_link_t *link;
-
- DEBUG(0, "fdomain_attach()\n");
-
- /* Create new SCSI device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return -ENOMEM;
- memset(info, 0, sizeof(*info));
- link = &info->link; link->priv = info;
- link->io.NumPorts1 = 0x10;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- link->io.IOAddrLines = 10;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
-
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- fdomain_config(link);
-
- return 0;
+ scsi_info_t *info;
+
+ DEBUG(0, "fdomain_attach()\n");
+
+ /* Create new SCSI device */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+ link->io.NumPorts1 = 0x10;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ link->io.IOAddrLines = 10;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->conf.Attributes = CONF_ENABLE_IRQ;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+ link->conf.Present = PRESENT_OPTION;
+
+ return fdomain_config(link);
} /* fdomain_attach */
/*====================================================================*/
-static void fdomain_detach(struct pcmcia_device *p_dev)
+static void fdomain_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "fdomain_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- fdomain_release(link);
+ fdomain_release(link);
kfree(link->priv);
} /* fdomain_detach */
@@ -133,9 +124,8 @@ static void fdomain_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void fdomain_config(dev_link_t *link)
+static int fdomain_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -150,103 +140,75 @@ static void fdomain_config(dev_link_t *link)
tuple.TupleData = tuple_data;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
-
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
/* A bad hack... */
release_region(link->io.BasePort1, link->io.NumPorts1);
/* Set configuration options for the fdomain driver */
sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
fdomain_setup(str);
-
+
host = __fdomain_16x0_detect(&fdomain_driver_template);
if (!host) {
printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
goto cs_failed;
}
-
- scsi_add_host(host, NULL); /* XXX handle failure */
+
+ if (scsi_add_host(host, NULL))
+ goto cs_failed;
scsi_scan_host(host);
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
fdomain_release(link);
- return;
-
+ return -ENODEV;
} /* fdomain_config */
/*====================================================================*/
-static void fdomain_release(dev_link_t *link)
+static void fdomain_release(struct pcmcia_device *link)
{
- scsi_info_t *info = link->priv;
+ scsi_info_t *info = link->priv;
- DEBUG(0, "fdomain_release(0x%p)\n", link);
+ DEBUG(0, "fdomain_release(0x%p)\n", link);
- scsi_remove_host(info->host);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- scsi_unregister(info->host);
-
- link->state &= ~DEV_CONFIG;
+ scsi_remove_host(info->host);
+ pcmcia_disable_device(link);
+ scsi_unregister(info->host);
}
/*====================================================================*/
-static int fdomain_suspend(struct pcmcia_device *dev)
+static int fdomain_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int fdomain_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- fdomain_16x0_bus_reset(NULL);
- }
+ fdomain_16x0_bus_reset(NULL);
return 0;
}
@@ -264,10 +226,9 @@ static struct pcmcia_driver fdomain_cs_driver = {
.drv = {
.name = "fdomain_cs",
},
- .probe = fdomain_attach,
+ .probe = fdomain_probe,
.remove = fdomain_detach,
.id_table = fdomain_ids,
- .suspend = fdomain_suspend,
.resume = fdomain_resume,
};
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 9e3ab3fd5355..231f9c311c69 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1593,11 +1593,11 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
configure the card at this point -- we wait until we receive a
card insertion event.
======================================================================*/
-static int nsp_cs_attach(struct pcmcia_device *p_dev)
+static int nsp_cs_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
nsp_hw_data *data = &nsp_data_base;
+ int ret;
nsp_dbg(NSP_DEBUG_INIT, "in");
@@ -1605,7 +1605,7 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) { return -ENOMEM; }
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
data->ScsiInfo = info;
@@ -1627,18 +1627,13 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- nsp_cs_config(link);
+ ret = nsp_cs_config(link);
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
- return 0;
+ return ret;
} /* nsp_cs_attach */
@@ -1648,16 +1643,12 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
structures are freed. Otherwise, the structures will be freed
when the device is released.
======================================================================*/
-static void nsp_cs_detach(struct pcmcia_device *p_dev)
+static void nsp_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
- if (link->state & DEV_CONFIG) {
- ((scsi_info_t *)link->priv)->stop = 1;
- nsp_cs_release(link);
- }
+ ((scsi_info_t *)link->priv)->stop = 1;
+ nsp_cs_release(link);
kfree(link->priv);
link->priv = NULL;
@@ -1672,9 +1663,9 @@ static void nsp_cs_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
/*====================================================================*/
-static void nsp_cs_config(dev_link_t *link)
+static int nsp_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
+ int ret;
scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -1698,26 +1689,22 @@ static void nsp_cs_config(dev_link_t *link)
tuple.TupleData = tuple_data;
tuple.TupleDataMax = sizeof(tuple_data);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
@@ -1743,10 +1730,10 @@ static void nsp_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
} else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
}
@@ -1773,7 +1760,7 @@ static void nsp_cs_config(dev_link_t *link)
link->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
@@ -1788,7 +1775,7 @@ static void nsp_cs_config(dev_link_t *link)
req.Size = 0x1000;
}
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -1802,17 +1789,14 @@ static void nsp_cs_config(dev_link_t *link)
next_entry:
nsp_dbg(NSP_DEBUG_INIT, "next");
-
- if (link->io.NumPorts1) {
- pcmcia_release_io(link->handle, &link->io);
- }
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ pcmcia_disable_device(link);
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (free_ports) {
if (link->io.BasePort1) {
@@ -1854,16 +1838,19 @@ static void nsp_cs_config(dev_link_t *link)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
- scsi_add_host (host, NULL);
+ ret = scsi_add_host (host, NULL);
+ if (ret)
+ goto cs_failed;
+
scsi_scan_host(host);
snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
#else
nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
- tail = &link->dev;
+ tail = &link->dev_node;
info->ndev = 0;
nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
@@ -1908,11 +1895,10 @@ static void nsp_cs_config(dev_link_t *link)
#endif
/* Finally, report what we've done */
- printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d",
- link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1) {
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "nsp_cs: index 0x%02x: ",
+ link->conf.ConfigIndex);
+ if (link->conf.Vpp) {
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
}
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
printk(", irq %d", link->irq.AssignedIRQ);
@@ -1929,15 +1915,14 @@ static void nsp_cs_config(dev_link_t *link)
req.Base+req.Size-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail");
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
nsp_cs_release(link);
- return;
+ return -ENODEV;
} /* nsp_cs_config */
#undef CS_CHECK
@@ -1947,7 +1932,7 @@ static void nsp_cs_config(dev_link_t *link)
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
======================================================================*/
-static void nsp_cs_release(dev_link_t *link)
+static void nsp_cs_release(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
nsp_hw_data *data = NULL;
@@ -1968,22 +1953,15 @@ static void nsp_cs_release(dev_link_t *link)
#else
scsi_unregister_host(&nsp_driver_template);
#endif
- link->dev = NULL;
+ link->dev_node = NULL;
if (link->win) {
if (data != NULL) {
iounmap((void *)(data->MmioAddress));
}
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1) {
- pcmcia_release_io(link->handle, &link->io);
}
- if (link->irq.AssignedIRQ) {
- pcmcia_release_irq(link->handle, &link->irq);
- }
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
if (info->host != NULL) {
scsi_host_put(info->host);
@@ -1991,14 +1969,11 @@ static void nsp_cs_release(dev_link_t *link)
#endif
} /* nsp_cs_release */
-static int nsp_cs_suspend(struct pcmcia_device *dev)
+static int nsp_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
- link->state |= DEV_SUSPEND;
-
nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
if (info->host != NULL) {
@@ -2011,25 +1986,16 @@ static int nsp_cs_suspend(struct pcmcia_device *dev)
info->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
return 0;
}
-static int nsp_cs_resume(struct pcmcia_device *dev)
+static int nsp_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
nsp_dbg(NSP_DEBUG_INIT, "event: resume");
- link->state &= ~DEV_SUSPEND;
-
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
info->stop = 0;
if (info->host != NULL) {
@@ -2065,7 +2031,7 @@ static struct pcmcia_driver nsp_driver = {
.drv = {
.name = "nsp_cs",
},
- .probe = nsp_cs_attach,
+ .probe = nsp_cs_probe,
.remove = nsp_cs_detach,
.id_table = nsp_cs_ids,
.suspend = nsp_cs_suspend,
@@ -2098,19 +2064,7 @@ static int __init nsp_cs_init(void)
static void __exit nsp_cs_exit(void)
{
nsp_msg(KERN_INFO, "unloading...");
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver);
-#else
- unregister_pcmcia_driver(&dev_info);
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG) {
- nsp_cs_release(dev_list);
- }
- nsp_cs_detach(dev_list);
- }
-#endif
}
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index b66b140a745e..8908b8e5b78a 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -225,7 +225,7 @@
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
struct Scsi_Host *host;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
dev_node_t node;
@@ -297,8 +297,8 @@ typedef struct _nsp_hw_data {
/* Card service functions */
static void nsp_cs_detach (struct pcmcia_device *p_dev);
-static void nsp_cs_release(dev_link_t *link);
-static void nsp_cs_config (dev_link_t *link);
+static void nsp_cs_release(struct pcmcia_device *link);
+static int nsp_cs_config (struct pcmcia_device *link);
/* Linux SCSI subsystem specific functions */
static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht);
@@ -450,7 +450,7 @@ static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
return host;
}
-static void cs_error(client_handle_t handle, int func, int ret)
+static void cs_error(struct pcmcia_device *handle, int func, int ret)
{
error_info_t err = { func, ret };
pcmcia_report_error(handle, &err);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index dce7e687fd4a..86c2ac6ae623 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -91,18 +91,18 @@ static struct scsi_host_template qlogicfas_driver_template = {
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
unsigned short manf_id;
} scsi_info_t;
-static void qlogic_release(dev_link_t *link);
+static void qlogic_release(struct pcmcia_device *link);
static void qlogic_detach(struct pcmcia_device *p_dev);
-static void qlogic_config(dev_link_t * link);
+static int qlogic_config(struct pcmcia_device * link);
static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
- dev_link_t *link, int qbase, int qlirq)
+ struct pcmcia_device *link, int qbase, int qlirq)
{
int qltyp; /* type of chip */
int qinitid;
@@ -156,10 +156,9 @@ free_scsi_host:
err:
return NULL;
}
-static int qlogic_attach(struct pcmcia_device *p_dev)
+static int qlogic_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
DEBUG(0, "qlogic_attach()\n");
@@ -168,7 +167,7 @@ static int qlogic_attach(struct pcmcia_device *p_dev)
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -176,30 +175,19 @@ static int qlogic_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- qlogic_config(link);
-
- return 0;
+ return qlogic_config(link);
} /* qlogic_attach */
/*====================================================================*/
-static void qlogic_detach(struct pcmcia_device *p_dev)
+static void qlogic_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "qlogic_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- qlogic_release(link);
-
+ qlogic_release(link);
kfree(link->priv);
} /* qlogic_detach */
@@ -209,9 +197,8 @@ static void qlogic_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void qlogic_config(dev_link_t * link)
+static int qlogic_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -225,38 +212,35 @@ static void qlogic_config(dev_link_t * link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
tuple.DesiredTuple = CISTPL_MANFID;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
/* set ATAcmd */
@@ -275,82 +259,54 @@ static void qlogic_config(dev_link_t * link)
if (!host) {
printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
- goto out;
+ goto cs_failed;
}
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
-out:
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
- link->dev = NULL;
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
- return;
+ cs_error(link, last_fn, last_ret);
+ pcmcia_disable_device(link);
+ return -ENODEV;
} /* qlogic_config */
/*====================================================================*/
-static void qlogic_release(dev_link_t *link)
+static void qlogic_release(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
DEBUG(0, "qlogic_release(0x%p)\n", link);
scsi_remove_host(info->host);
- link->dev = NULL;
free_irq(link->irq.AssignedIRQ, info->host);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ pcmcia_disable_device(link);
scsi_host_put(info->host);
-
- link->state &= ~DEV_CONFIG;
}
/*====================================================================*/
-static int qlogic_suspend(struct pcmcia_device *dev)
+static int qlogic_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
+ scsi_info_t *info = link->priv;
-static int qlogic_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- scsi_info_t *info = link->priv;
-
- pcmcia_request_configuration(link->handle, &link->conf);
- if ((info->manf_id == MANFID_MACNICA) ||
- (info->manf_id == MANFID_PIONEER) ||
- (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /* Ugggglllyyyy!!! */
- qlogicfas408_bus_reset(NULL);
+ pcmcia_request_configuration(link, &link->conf);
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
+ /* Ugggglllyyyy!!! */
+ qlogicfas408_bus_reset(NULL);
return 0;
}
@@ -382,10 +338,9 @@ static struct pcmcia_driver qlogic_cs_driver = {
.drv = {
.name = "qlogic_cs",
},
- .probe = qlogic_attach,
+ .probe = qlogic_probe,
.remove = qlogic_detach,
.id_table = qlogic_ids,
- .suspend = qlogic_suspend,
.resume = qlogic_resume,
};
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 3a4dd6f5b81f..9f59827707f0 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -202,7 +202,7 @@ static char *version =
/* ================================================================== */
struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
unsigned short manf_id;
@@ -527,7 +527,7 @@ idle_out:
}
static void
-SYM53C500_release(dev_link_t *link)
+SYM53C500_release(struct pcmcia_device *link)
{
struct scsi_info_t *info = link->priv;
struct Scsi_Host *shost = info->host;
@@ -550,13 +550,7 @@ SYM53C500_release(dev_link_t *link)
if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
scsi_host_put(shost);
} /* SYM53C500_release */
@@ -713,10 +707,9 @@ static struct scsi_host_template sym53c500_driver_template = {
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void
-SYM53C500_config(dev_link_t *link)
+static int
+SYM53C500_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -733,40 +726,37 @@ SYM53C500_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
tuple.DesiredTuple = CISTPL_MANFID;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
* That's the trouble with copying liberally from another driver.
@@ -835,7 +825,7 @@ next_entry:
data->fast_pio = USE_FAST_PIO;
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
if (scsi_add_host(host, NULL))
@@ -843,7 +833,7 @@ next_entry:
scsi_scan_host(host);
- goto out; /* SUCCESS */
+ return 0;
err_free_irq:
free_irq(irq_level, host);
@@ -852,74 +842,50 @@ err_free_scsi:
err_release:
release_region(port_base, 0x10);
printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");
-
-out:
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
SYM53C500_release(link);
- return;
+ return -ENODEV;
} /* SYM53C500_config */
-static int sym53c500_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int sym53c500_resume(struct pcmcia_device *dev)
+static int sym53c500_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct scsi_info_t *info = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
-
- /* See earlier comment about manufacturer IDs. */
- if ((info->manf_id == MANFID_MACNICA) ||
- (info->manf_id == MANFID_PIONEER) ||
- (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /*
- * If things don't work after a "resume",
- * this is a good place to start looking.
- */
- SYM53C500_int_host_reset(link->io.BasePort1);
+ /* See earlier comment about manufacturer IDs. */
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
+ /*
+ * If things don't work after a "resume",
+ * this is a good place to start looking.
+ */
+ SYM53C500_int_host_reset(link->io.BasePort1);
return 0;
}
static void
-SYM53C500_detach(struct pcmcia_device *p_dev)
+SYM53C500_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- SYM53C500_release(link);
+ SYM53C500_release(link);
kfree(link->priv);
link->priv = NULL;
} /* SYM53C500_detach */
static int
-SYM53C500_attach(struct pcmcia_device *p_dev)
+SYM53C500_probe(struct pcmcia_device *link)
{
struct scsi_info_t *info;
- dev_link_t *link;
DEBUG(0, "SYM53C500_attach()\n");
@@ -928,7 +894,7 @@ SYM53C500_attach(struct pcmcia_device *p_dev)
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -936,17 +902,10 @@ SYM53C500_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- SYM53C500_config(link);
-
- return 0;
+ return SYM53C500_config(link);
} /* SYM53C500_attach */
MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@@ -966,10 +925,9 @@ static struct pcmcia_driver sym53c500_cs_driver = {
.drv = {
.name = "sym53c500_cs",
},
- .probe = SYM53C500_attach,
+ .probe = SYM53C500_probe,
.remove = SYM53C500_detach,
.id_table = sym53c500_ids,
- .suspend = sym53c500_suspend,
.resume = sym53c500_resume,
};
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index 3c85c4b66e19..5cda16cfacb0 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
deleted file mode 100644
index 52b224a5d6fd..000000000000
--- a/drivers/scsi/qlogicfc.c
+++ /dev/null
@@ -1,2228 +0,0 @@
-/*
- * QLogic ISP2x00 SCSI-FCP
- * Written by Erik H. Moe, ehm@cris.com
- * Copyright 1995, Erik H. Moe
- *
- * This program is free software; you can redistribute 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.
- */
-
-/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
-
-/* This is a version of the isp1020 driver which was modified by
- * Chris Loveland <cwl@iol.unh.edu> to support the isp2100 and isp2200
- *
- * Big endian support and dynamic DMA mapping added
- * by Jakub Jelinek <jakub@redhat.com>.
- *
- * Conversion to final pci64 DMA interfaces
- * by David S. Miller <davem@redhat.com>.
- */
-
-/*
- * $Date: 1995/09/22 02:23:15 $
- * $Revision: 0.5 $
- *
- * $Log: isp1020.c,v $
- * Revision 0.5 1995/09/22 02:23:15 root
- * do auto request sense
- *
- * Revision 0.4 1995/08/07 04:44:33 root
- * supply firmware with driver.
- * numerous bug fixes/general cleanup of code.
- *
- * Revision 0.3 1995/07/16 16:15:39 root
- * added reset/abort code.
- *
- * Revision 0.2 1995/06/29 03:14:19 root
- * fixed biosparam.
- * added queue protocol.
- *
- * Revision 0.1 1995/06/25 01:55:45 root
- * Initial release.
- *
- */
-
-#include <linux/blkdev.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/unistd.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-
-#define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32)))
-#define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a)))))
-#define pci64_dma_build(hi,lo) \
- ((dma_addr_t)(((u64)(lo))|(((u64)(hi))<<32)))
-
-/*
- * With the qlogic interface, every queue slot can hold a SCSI
- * command with up to 2 scatter/gather entries. If we need more
- * than 2 entries, continuation entries can be used that hold
- * another 5 entries each. Unlike for other drivers, this means
- * that the maximum number of scatter/gather entries we can
- * support at any given time is a function of the number of queue
- * slots available. That is, host->can_queue and host->sg_tablesize
- * are dynamic and _not_ independent. This all works fine because
- * requests are queued serially and the scatter/gather limit is
- * determined for each queue request anew.
- */
-
-#define DATASEGS_PER_COMMAND 2
-#define DATASEGS_PER_CONT 5
-
-#define QLOGICFC_REQ_QUEUE_LEN 255 /* must be power of two - 1 */
-#define QLOGICFC_MAX_SG(ql) (DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
-#define QLOGICFC_CMD_PER_LUN 8
-
-/* Configuration section **************************************************** */
-
-/* Set the following macro to 1 to reload the ISP2x00's firmware. This is
- version 1.17.30 of the isp2100's firmware and version 2.00.40 of the
- isp2200's firmware.
-*/
-
-#define USE_NVRAM_DEFAULTS 1
-
-#define ISP2x00_PORTDB 1
-
-/* Set the following to 1 to include fabric support, fabric support is
- * currently not as well tested as the other aspects of the driver */
-
-#define ISP2x00_FABRIC 1
-
-/* Macros used for debugging */
-#define DEBUG_ISP2x00 0
-#define DEBUG_ISP2x00_INT 0
-#define DEBUG_ISP2x00_INTR 0
-#define DEBUG_ISP2x00_SETUP 0
-#define DEBUG_ISP2x00_FABRIC 0
-#define TRACE_ISP 0
-
-
-#define DEFAULT_LOOP_COUNT 1000000000
-
-#define ISP_TIMEOUT (2*HZ)
-/* End Configuration section ************************************************ */
-
-#include <linux/module.h>
-
-#if TRACE_ISP
-
-#define TRACE_BUF_LEN (32*1024)
-
-struct {
- u_long next;
- struct {
- u_long time;
- u_int index;
- u_int addr;
- u_char *name;
- } buf[TRACE_BUF_LEN];
-} trace;
-
-#define TRACE(w, i, a) \
-{ \
- unsigned long flags; \
- \
- save_flags(flags); \
- cli(); \
- trace.buf[trace.next].name = (w); \
- trace.buf[trace.next].time = jiffies; \
- trace.buf[trace.next].index = (i); \
- trace.buf[trace.next].addr = (long) (a); \
- trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1); \
- restore_flags(flags); \
-}
-
-#else
-#define TRACE(w, i, a)
-#endif
-
-#if DEBUG_ISP2x00_FABRIC
-#define DEBUG_FABRIC(x) x
-#else
-#define DEBUG_FABRIC(x)
-#endif /* DEBUG_ISP2x00_FABRIC */
-
-
-#if DEBUG_ISP2x00
-#define ENTER(x) printk("isp2x00 : entering %s()\n", x);
-#define LEAVE(x) printk("isp2x00 : leaving %s()\n", x);
-#define DEBUG(x) x
-#else
-#define ENTER(x)
-#define LEAVE(x)
-#define DEBUG(x)
-#endif /* DEBUG_ISP2x00 */
-
-#if DEBUG_ISP2x00_INTR
-#define ENTER_INTR(x) printk("isp2x00 : entering %s()\n", x);
-#define LEAVE_INTR(x) printk("isp2x00 : leaving %s()\n", x);
-#define DEBUG_INTR(x) x
-#else
-#define ENTER_INTR(x)
-#define LEAVE_INTR(x)
-#define DEBUG_INTR(x)
-#endif /* DEBUG ISP2x00_INTR */
-
-
-#define ISP2100_REV_ID1 1
-#define ISP2100_REV_ID3 3
-#define ISP2200_REV_ID5 5
-
-/* host configuration and control registers */
-#define HOST_HCCR 0xc0 /* host command and control */
-
-/* pci bus interface registers */
-#define FLASH_BIOS_ADDR 0x00
-#define FLASH_BIOS_DATA 0x02
-#define ISP_CTRL_STATUS 0x06 /* configuration register #1 */
-#define PCI_INTER_CTL 0x08 /* pci interrupt control */
-#define PCI_INTER_STS 0x0a /* pci interrupt status */
-#define PCI_SEMAPHORE 0x0c /* pci semaphore */
-#define PCI_NVRAM 0x0e /* pci nvram interface */
-
-/* mailbox registers */
-#define MBOX0 0x10 /* mailbox 0 */
-#define MBOX1 0x12 /* mailbox 1 */
-#define MBOX2 0x14 /* mailbox 2 */
-#define MBOX3 0x16 /* mailbox 3 */
-#define MBOX4 0x18 /* mailbox 4 */
-#define MBOX5 0x1a /* mailbox 5 */
-#define MBOX6 0x1c /* mailbox 6 */
-#define MBOX7 0x1e /* mailbox 7 */
-
-/* mailbox command complete status codes */
-#define MBOX_COMMAND_COMPLETE 0x4000
-#define INVALID_COMMAND 0x4001
-#define HOST_INTERFACE_ERROR 0x4002
-#define TEST_FAILED 0x4003
-#define COMMAND_ERROR 0x4005
-#define COMMAND_PARAM_ERROR 0x4006
-#define PORT_ID_USED 0x4007
-#define LOOP_ID_USED 0x4008
-#define ALL_IDS_USED 0x4009
-
-/* async event status codes */
-#define RESET_DETECTED 0x8001
-#define SYSTEM_ERROR 0x8002
-#define REQUEST_TRANSFER_ERROR 0x8003
-#define RESPONSE_TRANSFER_ERROR 0x8004
-#define REQUEST_QUEUE_WAKEUP 0x8005
-#define LIP_OCCURRED 0x8010
-#define LOOP_UP 0x8011
-#define LOOP_DOWN 0x8012
-#define LIP_RECEIVED 0x8013
-#define PORT_DB_CHANGED 0x8014
-#define CHANGE_NOTIFICATION 0x8015
-#define SCSI_COMMAND_COMPLETE 0x8020
-#define POINT_TO_POINT_UP 0x8030
-#define CONNECTION_MODE 0x8036
-
-struct Entry_header {
- u_char entry_type;
- u_char entry_cnt;
- u_char sys_def_1;
- u_char flags;
-};
-
-/* entry header type commands */
-#define ENTRY_COMMAND 0x19
-#define ENTRY_CONTINUATION 0x0a
-
-#define ENTRY_STATUS 0x03
-#define ENTRY_MARKER 0x04
-
-
-/* entry header flag definitions */
-#define EFLAG_BUSY 2
-#define EFLAG_BAD_HEADER 4
-#define EFLAG_BAD_PAYLOAD 8
-
-struct dataseg {
- u_int d_base;
- u_int d_base_hi;
- u_int d_count;
-};
-
-struct Command_Entry {
- struct Entry_header hdr;
- u_int handle;
- u_char target_lun;
- u_char target_id;
- u_short expanded_lun;
- u_short control_flags;
- u_short rsvd2;
- u_short time_out;
- u_short segment_cnt;
- u_char cdb[16];
- u_int total_byte_cnt;
- struct dataseg dataseg[DATASEGS_PER_COMMAND];
-};
-
-/* command entry control flag definitions */
-#define CFLAG_NODISC 0x01
-#define CFLAG_HEAD_TAG 0x02
-#define CFLAG_ORDERED_TAG 0x04
-#define CFLAG_SIMPLE_TAG 0x08
-#define CFLAG_TAR_RTN 0x10
-#define CFLAG_READ 0x20
-#define CFLAG_WRITE 0x40
-
-struct Continuation_Entry {
- struct Entry_header hdr;
- struct dataseg dataseg[DATASEGS_PER_CONT];
-};
-
-struct Marker_Entry {
- struct Entry_header hdr;
- u_int reserved;
- u_char target_lun;
- u_char target_id;
- u_char modifier;
- u_char expanded_lun;
- u_char rsvds[52];
-};
-
-/* marker entry modifier definitions */
-#define SYNC_DEVICE 0
-#define SYNC_TARGET 1
-#define SYNC_ALL 2
-
-struct Status_Entry {
- struct Entry_header hdr;
- u_int handle;
- u_short scsi_status;
- u_short completion_status;
- u_short state_flags;
- u_short status_flags;
- u_short res_info_len;
- u_short req_sense_len;
- u_int residual;
- u_char res_info[8];
- u_char req_sense_data[32];
-};
-
-/* status entry completion status definitions */
-#define CS_COMPLETE 0x0000
-#define CS_DMA_ERROR 0x0002
-#define CS_RESET_OCCURRED 0x0004
-#define CS_ABORTED 0x0005
-#define CS_TIMEOUT 0x0006
-#define CS_DATA_OVERRUN 0x0007
-#define CS_DATA_UNDERRUN 0x0015
-#define CS_QUEUE_FULL 0x001c
-#define CS_PORT_UNAVAILABLE 0x0028
-#define CS_PORT_LOGGED_OUT 0x0029
-#define CS_PORT_CONFIG_CHANGED 0x002a
-
-/* status entry state flag definitions */
-#define SF_SENT_CDB 0x0400
-#define SF_TRANSFERRED_DATA 0x0800
-#define SF_GOT_STATUS 0x1000
-
-/* status entry status flag definitions */
-#define STF_BUS_RESET 0x0008
-#define STF_DEVICE_RESET 0x0010
-#define STF_ABORTED 0x0020
-#define STF_TIMEOUT 0x0040
-
-/* interrupt control commands */
-#define ISP_EN_INT 0x8000
-#define ISP_EN_RISC 0x0008
-
-/* host control commands */
-#define HCCR_NOP 0x0000
-#define HCCR_RESET 0x1000
-#define HCCR_PAUSE 0x2000
-#define HCCR_RELEASE 0x3000
-#define HCCR_SINGLE_STEP 0x4000
-#define HCCR_SET_HOST_INTR 0x5000
-#define HCCR_CLEAR_HOST_INTR 0x6000
-#define HCCR_CLEAR_RISC_INTR 0x7000
-#define HCCR_BP_ENABLE 0x8000
-#define HCCR_BIOS_DISABLE 0x9000
-#define HCCR_TEST_MODE 0xf000
-
-#define RISC_BUSY 0x0004
-
-/* mailbox commands */
-#define MBOX_NO_OP 0x0000
-#define MBOX_LOAD_RAM 0x0001
-#define MBOX_EXEC_FIRMWARE 0x0002
-#define MBOX_DUMP_RAM 0x0003
-#define MBOX_WRITE_RAM_WORD 0x0004
-#define MBOX_READ_RAM_WORD 0x0005
-#define MBOX_MAILBOX_REG_TEST 0x0006
-#define MBOX_VERIFY_CHECKSUM 0x0007
-#define MBOX_ABOUT_FIRMWARE 0x0008
-#define MBOX_LOAD_RISC_RAM 0x0009
-#define MBOX_DUMP_RISC_RAM 0x000a
-#define MBOX_CHECK_FIRMWARE 0x000e
-#define MBOX_INIT_REQ_QUEUE 0x0010
-#define MBOX_INIT_RES_QUEUE 0x0011
-#define MBOX_EXECUTE_IOCB 0x0012
-#define MBOX_WAKE_UP 0x0013
-#define MBOX_STOP_FIRMWARE 0x0014
-#define MBOX_ABORT_IOCB 0x0015
-#define MBOX_ABORT_DEVICE 0x0016
-#define MBOX_ABORT_TARGET 0x0017
-#define MBOX_BUS_RESET 0x0018
-#define MBOX_STOP_QUEUE 0x0019
-#define MBOX_START_QUEUE 0x001a
-#define MBOX_SINGLE_STEP_QUEUE 0x001b
-#define MBOX_ABORT_QUEUE 0x001c
-#define MBOX_GET_DEV_QUEUE_STATUS 0x001d
-#define MBOX_GET_FIRMWARE_STATUS 0x001f
-#define MBOX_GET_INIT_SCSI_ID 0x0020
-#define MBOX_GET_RETRY_COUNT 0x0022
-#define MBOX_GET_TARGET_PARAMS 0x0028
-#define MBOX_GET_DEV_QUEUE_PARAMS 0x0029
-#define MBOX_SET_RETRY_COUNT 0x0032
-#define MBOX_SET_TARGET_PARAMS 0x0038
-#define MBOX_SET_DEV_QUEUE_PARAMS 0x0039
-#define MBOX_EXECUTE_IOCB64 0x0054
-#define MBOX_INIT_FIRMWARE 0x0060
-#define MBOX_GET_INIT_CB 0x0061
-#define MBOX_INIT_LIP 0x0062
-#define MBOX_GET_POS_MAP 0x0063
-#define MBOX_GET_PORT_DB 0x0064
-#define MBOX_CLEAR_ACA 0x0065
-#define MBOX_TARGET_RESET 0x0066
-#define MBOX_CLEAR_TASK_SET 0x0067
-#define MBOX_ABORT_TASK_SET 0x0068
-#define MBOX_GET_FIRMWARE_STATE 0x0069
-#define MBOX_GET_PORT_NAME 0x006a
-#define MBOX_SEND_SNS 0x006e
-#define MBOX_PORT_LOGIN 0x006f
-#define MBOX_SEND_CHANGE_REQUEST 0x0070
-#define MBOX_PORT_LOGOUT 0x0071
-
-/*
- * Firmware if needed (note this is a hack, it belongs in a separate
- * module.
- */
-
-#ifdef CONFIG_SCSI_QLOGIC_FC_FIRMWARE
-#include "qlogicfc_asm.c"
-#else
-static unsigned short risc_code_addr01 = 0x1000 ;
-#endif
-
-/* Each element in mbox_param is an 8 bit bitmap where each bit indicates
- if that mbox should be copied as input. For example 0x2 would mean
- only copy mbox1. */
-
-static const u_char mbox_param[] =
-{
- 0x01, /* MBOX_NO_OP */
- 0x1f, /* MBOX_LOAD_RAM */
- 0x03, /* MBOX_EXEC_FIRMWARE */
- 0x1f, /* MBOX_DUMP_RAM */
- 0x07, /* MBOX_WRITE_RAM_WORD */
- 0x03, /* MBOX_READ_RAM_WORD */
- 0xff, /* MBOX_MAILBOX_REG_TEST */
- 0x03, /* MBOX_VERIFY_CHECKSUM */
- 0x01, /* MBOX_ABOUT_FIRMWARE */
- 0xff, /* MBOX_LOAD_RISC_RAM */
- 0xff, /* MBOX_DUMP_RISC_RAM */
- 0x00, /* 0x000b */
- 0x00, /* 0x000c */
- 0x00, /* 0x000d */
- 0x01, /* MBOX_CHECK_FIRMWARE */
- 0x00, /* 0x000f */
- 0x1f, /* MBOX_INIT_REQ_QUEUE */
- 0x2f, /* MBOX_INIT_RES_QUEUE */
- 0x0f, /* MBOX_EXECUTE_IOCB */
- 0x03, /* MBOX_WAKE_UP */
- 0x01, /* MBOX_STOP_FIRMWARE */
- 0x0f, /* MBOX_ABORT_IOCB */
- 0x03, /* MBOX_ABORT_DEVICE */
- 0x07, /* MBOX_ABORT_TARGET */
- 0x03, /* MBOX_BUS_RESET */
- 0x03, /* MBOX_STOP_QUEUE */
- 0x03, /* MBOX_START_QUEUE */
- 0x03, /* MBOX_SINGLE_STEP_QUEUE */
- 0x03, /* MBOX_ABORT_QUEUE */
- 0x03, /* MBOX_GET_DEV_QUEUE_STATUS */
- 0x00, /* 0x001e */
- 0x01, /* MBOX_GET_FIRMWARE_STATUS */
- 0x01, /* MBOX_GET_INIT_SCSI_ID */
- 0x00, /* 0x0021 */
- 0x01, /* MBOX_GET_RETRY_COUNT */
- 0x00, /* 0x0023 */
- 0x00, /* 0x0024 */
- 0x00, /* 0x0025 */
- 0x00, /* 0x0026 */
- 0x00, /* 0x0027 */
- 0x03, /* MBOX_GET_TARGET_PARAMS */
- 0x03, /* MBOX_GET_DEV_QUEUE_PARAMS */
- 0x00, /* 0x002a */
- 0x00, /* 0x002b */
- 0x00, /* 0x002c */
- 0x00, /* 0x002d */
- 0x00, /* 0x002e */
- 0x00, /* 0x002f */
- 0x00, /* 0x0030 */
- 0x00, /* 0x0031 */
- 0x07, /* MBOX_SET_RETRY_COUNT */
- 0x00, /* 0x0033 */
- 0x00, /* 0x0034 */
- 0x00, /* 0x0035 */
- 0x00, /* 0x0036 */
- 0x00, /* 0x0037 */
- 0x0f, /* MBOX_SET_TARGET_PARAMS */
- 0x0f, /* MBOX_SET_DEV_QUEUE_PARAMS */
- 0x00, /* 0x003a */
- 0x00, /* 0x003b */
- 0x00, /* 0x003c */
- 0x00, /* 0x003d */
- 0x00, /* 0x003e */
- 0x00, /* 0x003f */
- 0x00, /* 0x0040 */
- 0x00, /* 0x0041 */
- 0x00, /* 0x0042 */
- 0x00, /* 0x0043 */
- 0x00, /* 0x0044 */
- 0x00, /* 0x0045 */
- 0x00, /* 0x0046 */
- 0x00, /* 0x0047 */
- 0x00, /* 0x0048 */
- 0x00, /* 0x0049 */
- 0x00, /* 0x004a */
- 0x00, /* 0x004b */
- 0x00, /* 0x004c */
- 0x00, /* 0x004d */
- 0x00, /* 0x004e */
- 0x00, /* 0x004f */
- 0x00, /* 0x0050 */
- 0x00, /* 0x0051 */
- 0x00, /* 0x0052 */
- 0x00, /* 0x0053 */
- 0xcf, /* MBOX_EXECUTE_IOCB64 */
- 0x00, /* 0x0055 */
- 0x00, /* 0x0056 */
- 0x00, /* 0x0057 */
- 0x00, /* 0x0058 */
- 0x00, /* 0x0059 */
- 0x00, /* 0x005a */
- 0x00, /* 0x005b */
- 0x00, /* 0x005c */
- 0x00, /* 0x005d */
- 0x00, /* 0x005e */
- 0x00, /* 0x005f */
- 0xff, /* MBOX_INIT_FIRMWARE */
- 0xcd, /* MBOX_GET_INIT_CB */
- 0x01, /* MBOX_INIT_LIP */
- 0xcd, /* MBOX_GET_POS_MAP */
- 0xcf, /* MBOX_GET_PORT_DB */
- 0x03, /* MBOX_CLEAR_ACA */
- 0x03, /* MBOX_TARGET_RESET */
- 0x03, /* MBOX_CLEAR_TASK_SET */
- 0x03, /* MBOX_ABORT_TASK_SET */
- 0x01, /* MBOX_GET_FIRMWARE_STATE */
- 0x03, /* MBOX_GET_PORT_NAME */
- 0x00, /* 0x006b */
- 0x00, /* 0x006c */
- 0x00, /* 0x006d */
- 0xcf, /* MBOX_SEND_SNS */
- 0x0f, /* MBOX_PORT_LOGIN */
- 0x03, /* MBOX_SEND_CHANGE_REQUEST */
- 0x03, /* MBOX_PORT_LOGOUT */
-};
-
-#define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short))
-
-
-struct id_name_map {
- u64 wwn;
- u_char loop_id;
-};
-
-struct sns_cb {
- u_short len;
- u_short res1;
- u_int response_low;
- u_int response_high;
- u_short sub_len;
- u_short res2;
- u_char data[44];
-};
-
-/* address of instance of this struct is passed to adapter to initialize things
- */
-struct init_cb {
- u_char version;
- u_char reseverd1[1];
- u_short firm_opts;
- u_short max_frame_len;
- u_short max_iocb;
- u_short exec_throttle;
- u_char retry_cnt;
- u_char retry_delay;
- u_short node_name[4];
- u_short hard_addr;
- u_char reserved2[10];
- u_short req_queue_out;
- u_short res_queue_in;
- u_short req_queue_len;
- u_short res_queue_len;
- u_int req_queue_addr_lo;
- u_int req_queue_addr_high;
- u_int res_queue_addr_lo;
- u_int res_queue_addr_high;
- /* the rest of this structure only applies to the isp2200 */
- u_short lun_enables;
- u_char cmd_resource_cnt;
- u_char notify_resource_cnt;
- u_short timeout;
- u_short reserved3;
- u_short add_firm_opts;
- u_char res_accum_timer;
- u_char irq_delay_timer;
- u_short special_options;
- u_short reserved4[13];
-};
-
-/*
- * The result queue can be quite a bit smaller since continuation entries
- * do not show up there:
- */
-#define RES_QUEUE_LEN ((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1)
-#define QUEUE_ENTRY_LEN 64
-
-#if ISP2x00_FABRIC
-#define QLOGICFC_MAX_ID 0xff
-#else
-#define QLOGICFC_MAX_ID 0x7d
-#endif
-
-#define QLOGICFC_MAX_LUN 128
-#define QLOGICFC_MAX_LOOP_ID 0x7d
-
-/* the following connection options only apply to the 2200. i have only
- * had success with LOOP_ONLY and P2P_ONLY.
- */
-
-#define LOOP_ONLY 0
-#define P2P_ONLY 1
-#define LOOP_PREFERED 2
-#define P2P_PREFERED 3
-
-#define CONNECTION_PREFERENCE LOOP_ONLY
-
-/* adapter_state values */
-#define AS_FIRMWARE_DEAD -1
-#define AS_LOOP_DOWN 0
-#define AS_LOOP_GOOD 1
-#define AS_REDO_FABRIC_PORTDB 2
-#define AS_REDO_LOOP_PORTDB 4
-
-#define RES_SIZE ((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
-#define REQ_SIZE ((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
-
-struct isp2x00_hostdata {
- u_char revision;
- struct pci_dev *pci_dev;
- /* result and request queues (shared with isp2x00): */
- u_int req_in_ptr; /* index of next request slot */
- u_int res_out_ptr; /* index of next result slot */
-
- /* this is here so the queues are nicely aligned */
- long send_marker; /* do we need to send a marker? */
-
- char * res;
- char * req;
- struct init_cb control_block;
- int adapter_state;
- unsigned long int tag_ages[QLOGICFC_MAX_ID + 1];
- Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1];
- unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1];
- struct id_name_map port_db[QLOGICFC_MAX_ID + 1];
- u_char mbox_done;
- u64 wwn;
- u_int port_id;
- u_char queued;
- u_char host_id;
- struct timer_list explore_timer;
- struct id_name_map tempmap[QLOGICFC_MAX_ID + 1];
-};
-
-
-/* queue length's _must_ be power of two: */
-#define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql))
-#define REQ_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, \
- QLOGICFC_REQ_QUEUE_LEN)
-#define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
-
-static void isp2x00_enable_irqs(struct Scsi_Host *);
-static void isp2x00_disable_irqs(struct Scsi_Host *);
-static int isp2x00_init(struct Scsi_Host *);
-static int isp2x00_reset_hardware(struct Scsi_Host *);
-static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]);
-static int isp2x00_return_status(Scsi_Cmnd *, struct Status_Entry *);
-static void isp2x00_intr_handler(int, void *, struct pt_regs *);
-static irqreturn_t do_isp2x00_intr_handler(int, void *, struct pt_regs *);
-static int isp2x00_make_portdb(struct Scsi_Host *);
-
-#if ISP2x00_FABRIC
-static int isp2x00_init_fabric(struct Scsi_Host *, struct id_name_map *, int);
-#endif
-
-#if USE_NVRAM_DEFAULTS
-static int isp2x00_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);
-static u_short isp2x00_read_nvram_word(struct Scsi_Host *, u_short);
-#endif
-
-#if DEBUG_ISP2x00
-static void isp2x00_print_scsi_cmd(Scsi_Cmnd *);
-#endif
-
-#if DEBUG_ISP2x00_INTR
-static void isp2x00_print_status_entry(struct Status_Entry *);
-#endif
-
-static inline void isp2x00_enable_irqs(struct Scsi_Host *host)
-{
- outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
-}
-
-
-static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
-{
- outw(0x0, host->io_port + PCI_INTER_CTL);
-}
-
-
-static int isp2x00_detect(struct scsi_host_template * tmpt)
-{
- int hosts = 0;
- unsigned long wait_time;
- struct Scsi_Host *host = NULL;
- struct isp2x00_hostdata *hostdata;
- struct pci_dev *pdev;
- unsigned short device_ids[2];
- dma_addr_t busaddr;
- int i;
-
-
- ENTER("isp2x00_detect");
-
- device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100;
- device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200;
-
- tmpt->proc_name = "isp2x00";
-
- for (i=0; i<2; i++){
- pdev = NULL;
- while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) {
- if (pci_enable_device(pdev))
- continue;
-
- /* Try to configure DMA attributes. */
- if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
- pci_set_dma_mask(pdev, DMA_32BIT_MASK))
- continue;
-
- host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
- if (!host) {
- printk("qlogicfc%d : could not register host.\n", hosts);
- continue;
- }
- host->max_id = QLOGICFC_MAX_ID + 1;
- host->max_lun = QLOGICFC_MAX_LUN;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
- hostdata->pci_dev = pdev;
- hostdata->res = pci_alloc_consistent(pdev, RES_SIZE + REQ_SIZE, &busaddr);
-
- if (!hostdata->res){
- printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hosts);
- scsi_unregister(host);
- continue;
- }
- hostdata->req = hostdata->res + (RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN;
- hostdata->queued = 0;
- /* set up the control block */
- hostdata->control_block.version = 0x1;
- hostdata->control_block.firm_opts = cpu_to_le16(0x800e);
- hostdata->control_block.max_frame_len = cpu_to_le16(2048);
- hostdata->control_block.max_iocb = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN);
- hostdata->control_block.exec_throttle = cpu_to_le16(QLOGICFC_CMD_PER_LUN);
- hostdata->control_block.retry_delay = 5;
- hostdata->control_block.retry_cnt = 1;
- hostdata->control_block.node_name[0] = cpu_to_le16(0x0020);
- hostdata->control_block.node_name[1] = cpu_to_le16(0xE000);
- hostdata->control_block.node_name[2] = cpu_to_le16(0x008B);
- hostdata->control_block.node_name[3] = cpu_to_le16(0x0000);
- hostdata->control_block.hard_addr = cpu_to_le16(0x0003);
- hostdata->control_block.req_queue_len = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN + 1);
- hostdata->control_block.res_queue_len = cpu_to_le16(RES_QUEUE_LEN + 1);
- hostdata->control_block.res_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr));
- hostdata->control_block.res_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr));
- hostdata->control_block.req_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr + RES_SIZE));
- hostdata->control_block.req_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr + RES_SIZE));
-
-
- hostdata->control_block.add_firm_opts |= cpu_to_le16(CONNECTION_PREFERENCE<<4);
- hostdata->adapter_state = AS_LOOP_DOWN;
- hostdata->explore_timer.data = 1;
- hostdata->host_id = hosts;
-
- if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {
- pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
- scsi_unregister(host);
- continue;
- }
- host->this_id = 0;
-
- if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
- printk("qlogicfc%d : interrupt %d already in use\n",
- hostdata->host_id, host->irq);
- pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
- scsi_unregister(host);
- continue;
- }
- if (!request_region(host->io_port, 0xff, "qlogicfc")) {
- printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "
- "in use\n",
- hostdata->host_id, host->io_port, host->io_port + 0xff);
- free_irq(host->irq, host);
- pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
- scsi_unregister(host);
- continue;
- }
-
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- isp2x00_enable_irqs(host);
- /* wait for the loop to come up */
- for (wait_time = jiffies + 10 * HZ; time_before(jiffies, wait_time) && hostdata->adapter_state == AS_LOOP_DOWN;) {
- barrier();
- cpu_relax();
- }
- if (hostdata->adapter_state == AS_LOOP_DOWN) {
- printk("qlogicfc%d : link is not up\n", hostdata->host_id);
- }
- hosts++;
- hostdata->explore_timer.data = 0;
- }
- }
-
-
- /* this busy loop should not be needed but the isp2x00 seems to need
- some time before recognizing it is attached to a fabric */
-
-#if ISP2x00_FABRIC
- if (hosts) {
- for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) {
- barrier();
- cpu_relax();
- }
- }
-#endif
-
- LEAVE("isp2x00_detect");
-
- return hosts;
-}
-
-
-static int isp2x00_make_portdb(struct Scsi_Host *host)
-{
-
- short param[8];
- int i, j;
- struct isp2x00_hostdata *hostdata;
-
- isp2x00_disable_irqs(host);
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- memset(hostdata->tempmap, 0, sizeof(hostdata->tempmap));
-
-#if ISP2x00_FABRIC
- for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
- param[0] = MBOX_PORT_LOGOUT;
- param[1] = i << 8;
- param[2] = 0;
- param[3] = 0;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
-
- DEBUG_FABRIC(printk("qlogicfc%d : logout failed %x %x\n", hostdata->host_id, i, param[0]));
- }
- }
-#endif
-
-
- param[0] = MBOX_GET_INIT_SCSI_ID;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- hostdata->port_id = ((u_int) param[3]) << 16;
- hostdata->port_id |= param[2];
- hostdata->tempmap[0].loop_id = param[1];
- hostdata->tempmap[0].wwn = hostdata->wwn;
- }
- else {
- printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id);
- }
-
- for (i = 0; i <=QLOGICFC_MAX_ID; i++)
- hostdata->tempmap[i].loop_id = hostdata->tempmap[0].loop_id;
-
- for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
- param[0] = MBOX_GET_PORT_NAME;
- param[1] = (i << 8) & 0xff00;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- hostdata->tempmap[j].loop_id = i;
- hostdata->tempmap[j].wwn = ((u64) (param[2] & 0xff)) << 56;
- hostdata->tempmap[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
- hostdata->tempmap[j].wwn |= ((u64) (param[3] & 0xff)) << 40;
- hostdata->tempmap[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
- hostdata->tempmap[j].wwn |= ((u64) (param[6] & 0xff)) << 24;
- hostdata->tempmap[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
- hostdata->tempmap[j].wwn |= ((u64) (param[7] & 0xff)) << 8;
- hostdata->tempmap[j].wwn |= ((u64) ((param[7] >> 8) & 0xff));
-
- j++;
-
- }
- }
-
-
-#if ISP2x00_FABRIC
- isp2x00_init_fabric(host, hostdata->tempmap, j);
-#endif
-
- for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
- if (hostdata->tempmap[i].wwn != hostdata->port_db[i].wwn) {
- for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
- if (hostdata->tempmap[j].wwn == hostdata->port_db[i].wwn) {
- hostdata->port_db[i].loop_id = hostdata->tempmap[j].loop_id;
- break;
- }
- }
- if (j == QLOGICFC_MAX_ID + 1)
- hostdata->port_db[i].loop_id = hostdata->tempmap[0].loop_id;
-
- for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
- if (hostdata->port_db[j].wwn == hostdata->tempmap[i].wwn || !hostdata->port_db[j].wwn) {
- break;
- }
- }
- if (j == QLOGICFC_MAX_ID + 1)
- printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id);
- if (!hostdata->port_db[j].wwn) {
- hostdata->port_db[j].loop_id = hostdata->tempmap[i].loop_id;
- hostdata->port_db[j].wwn = hostdata->tempmap[i].wwn;
- }
- } else
- hostdata->port_db[i].loop_id = hostdata->tempmap[i].loop_id;
-
- }
-
- isp2x00_enable_irqs(host);
-
- return 0;
-}
-
-
-#if ISP2x00_FABRIC
-
-#define FABRIC_PORT 0x7e
-#define FABRIC_CONTROLLER 0x7f
-#define FABRIC_SNS 0x80
-
-int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int cur_scsi_id)
-{
-
- u_short param[8];
- u64 wwn;
- int done = 0;
- u_short loop_id = 0x81;
- u_short scsi_id = cur_scsi_id;
- u_int port_id;
- struct sns_cb *req;
- u_char *sns_response;
- dma_addr_t busaddr;
- struct isp2x00_hostdata *hostdata;
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id));
- param[0] = MBOX_GET_PORT_NAME;
- param[1] = (u16)FABRIC_PORT << 8;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- DEBUG_FABRIC(printk("qlogicfc%d : fabric check result %x\n", hostdata->host_id, param[0]));
- return 0;
- }
- printk("qlogicfc%d : Fabric found.\n", hostdata->host_id);
-
- req = (struct sns_cb *)pci_alloc_consistent(hostdata->pci_dev, sizeof(*req) + 608, &busaddr);
-
- if (!req){
- printk("qlogicfc%d : Could not allocate DMA resources for fabric initialization\n", hostdata->host_id);
- return 0;
- }
- sns_response = (u_char *)(req + 1);
-
- if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){
- memset(req, 0, sizeof(*req));
-
- req->len = cpu_to_le16(8);
- req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
- req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
- req->sub_len = cpu_to_le16(22);
- req->data[0] = 0x17;
- req->data[1] = 0x02;
- req->data[8] = (u_char) (hostdata->port_id & 0xff);
- req->data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
- req->data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
- req->data[13] = 0x01;
- param[0] = MBOX_SEND_SNS;
- param[1] = 30;
- param[2] = pci64_dma_lo32(busaddr) >> 16;
- param[3] = pci64_dma_lo32(busaddr);
- param[6] = pci64_dma_hi32(busaddr) >> 16;
- param[7] = pci64_dma_hi32(busaddr);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE)
- printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);
- }
-
- port_id = hostdata->port_id;
- while (!done) {
- memset(req, 0, sizeof(*req));
-
- req->len = cpu_to_le16(304);
- req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
- req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
- req->sub_len = cpu_to_le16(6);
- req->data[0] = 0x00;
- req->data[1] = 0x01;
- req->data[8] = (u_char) (port_id & 0xff);
- req->data[9] = (u_char) (port_id >> 8 & 0xff);
- req->data[10] = (u_char) (port_id >> 16 & 0xff);
-
- param[0] = MBOX_SEND_SNS;
- param[1] = 14;
- param[2] = pci64_dma_lo32(busaddr) >> 16;
- param[3] = pci64_dma_lo32(busaddr);
- param[6] = pci64_dma_hi32(busaddr) >> 16;
- param[7] = pci64_dma_hi32(busaddr);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- DEBUG_FABRIC(printk("qlogicfc%d : found node %02x%02x%02x%02x%02x%02x%02x%02x ", hostdata->host_id, sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27]));
- DEBUG_FABRIC(printk(" port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19]));
- port_id = ((u_int) sns_response[17]) << 16;
- port_id |= ((u_int) sns_response[18]) << 8;
- port_id |= ((u_int) sns_response[19]);
- wwn = ((u64) sns_response[20]) << 56;
- wwn |= ((u64) sns_response[21]) << 48;
- wwn |= ((u64) sns_response[22]) << 40;
- wwn |= ((u64) sns_response[23]) << 32;
- wwn |= ((u64) sns_response[24]) << 24;
- wwn |= ((u64) sns_response[25]) << 16;
- wwn |= ((u64) sns_response[26]) << 8;
- wwn |= ((u64) sns_response[27]);
- if (hostdata->port_id >> 8 != port_id >> 8) {
- DEBUG_FABRIC(printk("qlogicfc%d : adding a fabric port: %x\n", hostdata->host_id, port_id));
- param[0] = MBOX_PORT_LOGIN;
- param[1] = loop_id << 8;
- param[2] = (u_short) (port_id >> 16);
- param[3] = (u_short) (port_id);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- port_db[scsi_id].wwn = wwn;
- port_db[scsi_id].loop_id = loop_id;
- loop_id++;
- scsi_id++;
- } else {
- printk("qlogicfc%d : Error performing port login %x\n", hostdata->host_id, param[0]);
- DEBUG_FABRIC(printk("qlogicfc%d : loop_id: %x\n", hostdata->host_id, loop_id));
- param[0] = MBOX_PORT_LOGOUT;
- param[1] = loop_id << 8;
- param[2] = 0;
- param[3] = 0;
-
- isp2x00_mbox_command(host, param);
-
- }
-
- }
- if (hostdata->port_id == port_id)
- done = 1;
- } else {
- printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]);
- pci_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
- return 0;
- }
- }
-
- pci_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
- return 1;
-}
-
-#endif /* ISP2x00_FABRIC */
-
-
-static int isp2x00_release(struct Scsi_Host *host)
-{
- struct isp2x00_hostdata *hostdata;
- dma_addr_t busaddr;
-
- ENTER("isp2x00_release");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- outw(0x0, host->io_port + PCI_INTER_CTL);
- free_irq(host->irq, host);
-
- release_region(host->io_port, 0xff);
-
- busaddr = pci64_dma_build(le32_to_cpu(hostdata->control_block.res_queue_addr_high),
- le32_to_cpu(hostdata->control_block.res_queue_addr_lo));
- pci_free_consistent(hostdata->pci_dev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
-
- LEAVE("isp2x00_release");
-
- return 0;
-}
-
-
-static const char *isp2x00_info(struct Scsi_Host *host)
-{
- static char buf[80];
- struct isp2x00_hostdata *hostdata;
- ENTER("isp2x00_info");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- sprintf(buf,
- "QLogic ISP%04x SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
- hostdata->pci_dev->device, hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
- host->io_port);
-
-
- LEAVE("isp2x00_info");
-
- return buf;
-}
-
-
-/*
- * The middle SCSI layer ensures that queuecommand never gets invoked
- * concurrently with itself or the interrupt handler (though the
- * interrupt handler may call this routine as part of
- * request-completion handling).
- */
-static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
-{
- int i, sg_count, n, num_free;
- u_int in_ptr, out_ptr;
- struct dataseg *ds;
- struct scatterlist *sg;
- struct Command_Entry *cmd;
- struct Continuation_Entry *cont;
- struct Scsi_Host *host;
- struct isp2x00_hostdata *hostdata;
-
- ENTER("isp2x00_queuecommand");
-
- host = Cmnd->device->host;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- Cmnd->scsi_done = done;
-
- DEBUG(isp2x00_print_scsi_cmd(Cmnd));
-
- if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
- isp2x00_make_portdb(host);
- hostdata->adapter_state = AS_LOOP_GOOD;
- printk("qlogicfc%d : Port Database\n", hostdata->host_id);
- for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
- printk("wwn: %08x%08x scsi_id: %x loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
- if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
- printk("%x", hostdata->port_db[i].loop_id);
- else
- printk("Not Available");
- printk("\n");
- }
- }
- if (hostdata->adapter_state == AS_FIRMWARE_DEAD) {
- printk("qlogicfc%d : The firmware is dead, just return.\n", hostdata->host_id);
- host->max_id = 0;
- return 0;
- }
-
- out_ptr = inw(host->io_port + MBOX4);
- in_ptr = hostdata->req_in_ptr;
-
- DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id,
- REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
-
- cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
- in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
- if (in_ptr == out_ptr) {
- DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
- return 1;
- }
- if (hostdata->send_marker) {
- struct Marker_Entry *marker;
-
- TRACE("queue marker", in_ptr, 0);
-
- DEBUG(printk("qlogicfc%d : adding marker entry\n", hostdata->host_id));
- marker = (struct Marker_Entry *) cmd;
- memset(marker, 0, sizeof(struct Marker_Entry));
-
- marker->hdr.entry_type = ENTRY_MARKER;
- marker->hdr.entry_cnt = 1;
- marker->modifier = SYNC_ALL;
-
- hostdata->send_marker = 0;
-
- if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) {
- outw(in_ptr, host->io_port + MBOX4);
- hostdata->req_in_ptr = in_ptr;
- DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
- return 1;
- }
- cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
- in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
- }
- TRACE("queue command", in_ptr, Cmnd);
-
- memset(cmd, 0, sizeof(struct Command_Entry));
-
- /* find a free handle mapping slot */
- for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1)));
-
- if (!hostdata->handle_ptrs[i]) {
- cmd->handle = cpu_to_le32(i);
- hostdata->handle_ptrs[i] = Cmnd;
- hostdata->handle_serials[i] = Cmnd->serial_number;
- } else {
- printk("qlogicfc%d : no handle slots, this should not happen.\n", hostdata->host_id);
- printk("hostdata->queued is %x, in_ptr: %x\n", hostdata->queued, in_ptr);
- for (i = 0; i <= QLOGICFC_REQ_QUEUE_LEN; i++){
- if (!hostdata->handle_ptrs[i]){
- printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]);
- }
- }
- return 1;
- }
-
- cmd->hdr.entry_type = ENTRY_COMMAND;
- cmd->hdr.entry_cnt = 1;
- cmd->target_lun = Cmnd->device->lun;
- cmd->expanded_lun = cpu_to_le16(Cmnd->device->lun);
-#if ISP2x00_PORTDB
- cmd->target_id = hostdata->port_db[Cmnd->device->id].loop_id;
-#else
- cmd->target_id = Cmnd->target;
-#endif
- cmd->total_byte_cnt = cpu_to_le32(Cmnd->request_bufflen);
- cmd->time_out = 0;
- memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
-
- if (Cmnd->use_sg) {
- sg = (struct scatterlist *) Cmnd->request_buffer;
- sg_count = pci_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
- cmd->segment_cnt = cpu_to_le16(sg_count);
- ds = cmd->dataseg;
- /* fill in first two sg entries: */
- n = sg_count;
- if (n > DATASEGS_PER_COMMAND)
- n = DATASEGS_PER_COMMAND;
-
- for (i = 0; i < n; i++) {
- ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma_address(sg)));
- ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma_address(sg)));
- ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
- ++sg;
- }
- sg_count -= DATASEGS_PER_COMMAND;
-
- while (sg_count > 0) {
- ++cmd->hdr.entry_cnt;
- cont = (struct Continuation_Entry *)
- &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
- memset(cont, 0, sizeof(struct Continuation_Entry));
- in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
- if (in_ptr == out_ptr) {
- DEBUG(printk("qlogicfc%d : unexpected request queue overflow\n", hostdata->host_id));
- return 1;
- }
- TRACE("queue continuation", in_ptr, 0);
- cont->hdr.entry_type = ENTRY_CONTINUATION;
- ds = cont->dataseg;
- n = sg_count;
- if (n > DATASEGS_PER_CONT)
- n = DATASEGS_PER_CONT;
- for (i = 0; i < n; ++i) {
- ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma_address(sg)));
- ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma_address(sg)));
- ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
- ++sg;
- }
- sg_count -= n;
- }
- } else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE) {
- struct page *page = virt_to_page(Cmnd->request_buffer);
- unsigned long offset = offset_in_page(Cmnd->request_buffer);
- dma_addr_t busaddr = pci_map_page(hostdata->pci_dev,
- page, offset,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
- Cmnd->SCp.dma_handle = busaddr;
-
- cmd->dataseg[0].d_base = cpu_to_le32(pci64_dma_lo32(busaddr));
- cmd->dataseg[0].d_base_hi = cpu_to_le32(pci64_dma_hi32(busaddr));
- cmd->dataseg[0].d_count = cpu_to_le32(Cmnd->request_bufflen);
- cmd->segment_cnt = cpu_to_le16(1);
- } else {
- cmd->dataseg[0].d_base = 0;
- cmd->dataseg[0].d_base_hi = 0;
- cmd->segment_cnt = cpu_to_le16(1); /* Shouldn't this be 0? */
- }
-
- if (Cmnd->sc_data_direction == DMA_TO_DEVICE)
- cmd->control_flags = cpu_to_le16(CFLAG_WRITE);
- else
- cmd->control_flags = cpu_to_le16(CFLAG_READ);
-
- if (Cmnd->device->tagged_supported) {
- if (time_after(jiffies, hostdata->tag_ages[Cmnd->device->id] + (2 * ISP_TIMEOUT))) {
- cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
- hostdata->tag_ages[Cmnd->device->id] = jiffies;
- } else
- switch (Cmnd->tag) {
- case HEAD_OF_QUEUE_TAG:
- cmd->control_flags |= cpu_to_le16(CFLAG_HEAD_TAG);
- break;
- case ORDERED_QUEUE_TAG:
- cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
- break;
- default:
- cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
- break;
- }
- }
- /*
- * TEST_UNIT_READY commands from scsi_scan will fail due to "overlapped
- * commands attempted" unless we setup at least a simple queue (midlayer
- * will embelish this once it can do an INQUIRY command to the device)
- */
- else
- cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
- outw(in_ptr, host->io_port + MBOX4);
- hostdata->req_in_ptr = in_ptr;
-
- hostdata->queued++;
-
- num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
- num_free = (num_free > 2) ? num_free - 2 : 0;
- host->can_queue = host->host_busy + num_free;
- if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
- host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
- host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
- LEAVE("isp2x00_queuecommand");
-
- return 0;
-}
-
-
-/* we have received an event, such as a lip or an RSCN, which may mean that
- * our port database is incorrect so the port database must be recreated.
- */
-static void redo_port_db(unsigned long arg)
-{
-
- struct Scsi_Host * host = (struct Scsi_Host *) arg;
- struct isp2x00_hostdata * hostdata;
- unsigned long flags;
- int i;
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- hostdata->explore_timer.data = 0;
- del_timer(&hostdata->explore_timer);
-
- spin_lock_irqsave(host->host_lock, flags);
-
- if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
- isp2x00_make_portdb(host);
- printk("qlogicfc%d : Port Database\n", hostdata->host_id);
- for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
- printk("wwn: %08x%08x scsi_id: %x loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
- if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
- printk("%x", hostdata->port_db[i].loop_id);
- else
- printk("Not Available");
- printk("\n");
- }
-
- for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++){
- if (hostdata->handle_ptrs[i] && (hostdata->port_db[hostdata->handle_ptrs[i]->device->id].loop_id > QLOGICFC_MAX_LOOP_ID || hostdata->adapter_state & AS_REDO_LOOP_PORTDB)){
- if (hostdata->port_db[hostdata->handle_ptrs[i]->device->id].loop_id != hostdata->port_db[0].loop_id){
- Scsi_Cmnd *Cmnd = hostdata->handle_ptrs[i];
-
- if (Cmnd->use_sg)
- pci_unmap_sg(hostdata->pci_dev,
- (struct scatterlist *)Cmnd->buffer,
- Cmnd->use_sg,
- Cmnd->sc_data_direction);
- else if (Cmnd->request_bufflen &&
- Cmnd->sc_data_direction != PCI_DMA_NONE) {
- pci_unmap_page(hostdata->pci_dev,
- Cmnd->SCp.dma_handle,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
- }
-
- hostdata->handle_ptrs[i]->result = DID_SOFT_ERROR << 16;
-
- if (hostdata->handle_ptrs[i]->scsi_done){
- (*hostdata->handle_ptrs[i]->scsi_done) (hostdata->handle_ptrs[i]);
- }
- else printk("qlogicfc%d : done is null?\n", hostdata->host_id);
- hostdata->handle_ptrs[i] = NULL;
- hostdata->handle_serials[i] = 0;
- }
- }
- }
-
- hostdata->adapter_state = AS_LOOP_GOOD;
- }
-
- spin_unlock_irqrestore(host->host_lock, flags);
-
-}
-
-#define ASYNC_EVENT_INTERRUPT 0x01
-
-irqreturn_t do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct Scsi_Host *host = dev_id;
- unsigned long flags;
-
- spin_lock_irqsave(host->host_lock, flags);
- isp2x00_intr_handler(irq, dev_id, regs);
- spin_unlock_irqrestore(host->host_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- Scsi_Cmnd *Cmnd;
- struct Status_Entry *sts;
- struct Scsi_Host *host = dev_id;
- struct isp2x00_hostdata *hostdata;
- u_int in_ptr, out_ptr, handle, num_free;
- u_short status;
-
- ENTER_INTR("isp2x00_intr_handler");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- DEBUG_INTR(printk("qlogicfc%d : interrupt on line %d\n", hostdata->host_id, irq));
-
- if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
- /* spurious interrupts can happen legally */
- DEBUG_INTR(printk("qlogicfc%d : got spurious interrupt\n", hostdata->host_id));
- return;
- }
- in_ptr = inw(host->io_port + MBOX5);
- out_ptr = hostdata->res_out_ptr;
-
- if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
- status = inw(host->io_port + MBOX0);
-
- DEBUG_INTR(printk("qlogicfc%d : mbox completion status: %x\n",
- hostdata->host_id, status));
-
- switch (status) {
- case LOOP_UP:
- case POINT_TO_POINT_UP:
- printk("qlogicfc%d : Link is Up\n", hostdata->host_id);
- hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB;
- break;
- case LOOP_DOWN:
- printk("qlogicfc%d : Link is Down\n", hostdata->host_id);
- hostdata->adapter_state = AS_LOOP_DOWN;
- break;
- case CONNECTION_MODE:
- printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
- break;
- case CHANGE_NOTIFICATION:
- printk("qlogicfc%d : RSCN Received\n", hostdata->host_id);
- if (hostdata->adapter_state == AS_LOOP_GOOD)
- hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
- break;
- case LIP_OCCURRED:
- case LIP_RECEIVED:
- printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);
- if (hostdata->adapter_state == AS_LOOP_GOOD)
- hostdata->adapter_state = AS_REDO_LOOP_PORTDB;
- break;
- case SYSTEM_ERROR:
- printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id);
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- break;
- case SCSI_COMMAND_COMPLETE:
- handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16);
- Cmnd = hostdata->handle_ptrs[handle];
- hostdata->handle_ptrs[handle] = NULL;
- hostdata->handle_serials[handle] = 0;
- hostdata->queued--;
- if (Cmnd != NULL) {
- if (Cmnd->use_sg)
- pci_unmap_sg(hostdata->pci_dev,
- (struct scatterlist *)Cmnd->buffer,
- Cmnd->use_sg,
- Cmnd->sc_data_direction);
- else if (Cmnd->request_bufflen &&
- Cmnd->sc_data_direction != PCI_DMA_NONE)
- pci_unmap_page(hostdata->pci_dev,
- Cmnd->SCp.dma_handle,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
- Cmnd->result = 0x0;
- (*Cmnd->scsi_done) (Cmnd);
- } else
- printk("qlogicfc%d.c : got a null value out of handle_ptrs, this sucks\n", hostdata->host_id);
- break;
- case MBOX_COMMAND_COMPLETE:
- case INVALID_COMMAND:
- case HOST_INTERFACE_ERROR:
- case TEST_FAILED:
- case COMMAND_ERROR:
- case COMMAND_PARAM_ERROR:
- case PORT_ID_USED:
- case LOOP_ID_USED:
- case ALL_IDS_USED:
- hostdata->mbox_done = 1;
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- return;
- default:
- printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status);
- }
- if ((hostdata->adapter_state & AS_REDO_LOOP_PORTDB || hostdata->adapter_state & AS_REDO_FABRIC_PORTDB) && hostdata->explore_timer.data == 0){
- hostdata->explore_timer.function = redo_port_db;
- hostdata->explore_timer.data = (unsigned long)host;
- hostdata->explore_timer.expires = jiffies + (HZ/4);
- init_timer(&hostdata->explore_timer);
- add_timer(&hostdata->explore_timer);
- }
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- } else {
- DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id));
- DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));
-
- while (out_ptr != in_ptr) {
- unsigned le_hand;
- sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN];
- out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
-
- TRACE("done", out_ptr, Cmnd);
- DEBUG_INTR(isp2x00_print_status_entry(sts));
- le_hand = le32_to_cpu(sts->handle);
- if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[le_hand])) {
- Cmnd->result = isp2x00_return_status(Cmnd, sts);
- hostdata->queued--;
-
- if (Cmnd->use_sg)
- pci_unmap_sg(hostdata->pci_dev,
- (struct scatterlist *)Cmnd->buffer, Cmnd->use_sg,
- Cmnd->sc_data_direction);
- else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE)
- pci_unmap_page(hostdata->pci_dev,
- Cmnd->SCp.dma_handle,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
-
- /*
- * if any of the following are true we do not
- * call scsi_done. if the status is CS_ABORTED
- * we don't have to call done because the upper
- * level should already know its aborted.
- */
- if (hostdata->handle_serials[le_hand] != Cmnd->serial_number
- || le16_to_cpu(sts->completion_status) == CS_ABORTED){
- hostdata->handle_serials[le_hand] = 0;
- hostdata->handle_ptrs[le_hand] = NULL;
- outw(out_ptr, host->io_port + MBOX5);
- continue;
- }
- /*
- * if we get back an error indicating the port
- * is not there or if the link is down and
- * this is a device that used to be there
- * allow the command to timeout.
- * the device may well be back in a couple of
- * seconds.
- */
- if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == cpu_to_le16(CS_PORT_UNAVAILABLE) || sts->completion_status == cpu_to_le16(CS_PORT_LOGGED_OUT) || sts->completion_status == cpu_to_le16(CS_PORT_CONFIG_CHANGED)) && hostdata->port_db[Cmnd->device->id].wwn){
- outw(out_ptr, host->io_port + MBOX5);
- continue;
- }
- } else {
- outw(out_ptr, host->io_port + MBOX5);
- continue;
- }
-
- hostdata->handle_ptrs[le_hand] = NULL;
-
- if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED)
- || (sts->status_flags & cpu_to_le16(STF_BUS_RESET)))
- hostdata->send_marker = 1;
-
- if (le16_to_cpu(sts->scsi_status) & 0x0200)
- memcpy(Cmnd->sense_buffer, sts->req_sense_data,
- sizeof(Cmnd->sense_buffer));
-
- outw(out_ptr, host->io_port + MBOX5);
-
- if (Cmnd->scsi_done != NULL) {
- (*Cmnd->scsi_done) (Cmnd);
- } else
- printk("qlogicfc%d : Ouch, scsi done is NULL\n", hostdata->host_id);
- }
- hostdata->res_out_ptr = out_ptr;
- }
-
-
- out_ptr = inw(host->io_port + MBOX4);
- in_ptr = hostdata->req_in_ptr;
-
- num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
- num_free = (num_free > 2) ? num_free - 2 : 0;
- host->can_queue = host->host_busy + num_free;
- if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
- host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
- host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- LEAVE_INTR("isp2x00_intr_handler");
-}
-
-
-static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
-{
- int host_status = DID_ERROR;
-#if DEBUG_ISP2x00_INTR
- static char *reason[] =
- {
- "DID_OK",
- "DID_NO_CONNECT",
- "DID_BUS_BUSY",
- "DID_TIME_OUT",
- "DID_BAD_TARGET",
- "DID_ABORT",
- "DID_PARITY",
- "DID_ERROR",
- "DID_RESET",
- "DID_BAD_INTR"
- };
-#endif /* DEBUG_ISP2x00_INTR */
-
- ENTER("isp2x00_return_status");
-
- DEBUG(printk("qlogicfc : completion status = 0x%04x\n",
- le16_to_cpu(sts->completion_status)));
-
- switch (le16_to_cpu(sts->completion_status)) {
- case CS_COMPLETE:
- host_status = DID_OK;
- break;
- case CS_DMA_ERROR:
- host_status = DID_ERROR;
- break;
- case CS_RESET_OCCURRED:
- host_status = DID_RESET;
- break;
- case CS_ABORTED:
- host_status = DID_ABORT;
- break;
- case CS_TIMEOUT:
- host_status = DID_TIME_OUT;
- break;
- case CS_DATA_OVERRUN:
- host_status = DID_ERROR;
- break;
- case CS_DATA_UNDERRUN:
- if (Cmnd->underflow <= (Cmnd->request_bufflen - le32_to_cpu(sts->residual)))
- host_status = DID_OK;
- else
- host_status = DID_ERROR;
- break;
- case CS_PORT_UNAVAILABLE:
- case CS_PORT_LOGGED_OUT:
- case CS_PORT_CONFIG_CHANGED:
- host_status = DID_BAD_TARGET;
- break;
- case CS_QUEUE_FULL:
- host_status = DID_ERROR;
- break;
- default:
- printk("qlogicfc : unknown completion status 0x%04x\n",
- le16_to_cpu(sts->completion_status));
- host_status = DID_ERROR;
- break;
- }
-
- DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",
- reason[host_status], le16_to_cpu(sts->scsi_status)));
-
- LEAVE("isp2x00_return_status");
-
- return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16);
-}
-
-
-static int isp2x00_abort(Scsi_Cmnd * Cmnd)
-{
- u_short param[8];
- int i;
- struct Scsi_Host *host;
- struct isp2x00_hostdata *hostdata;
- int return_status = SUCCESS;
-
- ENTER("isp2x00_abort");
-
- host = Cmnd->device->host;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++)
- if (hostdata->handle_ptrs[i] == Cmnd)
- break;
-
- if (i == QLOGICFC_REQ_QUEUE_LEN){
- return SUCCESS;
- }
-
- isp2x00_disable_irqs(host);
-
- param[0] = MBOX_ABORT_IOCB;
-#if ISP2x00_PORTDB
- param[1] = (((u_short) hostdata->port_db[Cmnd->device->id].loop_id) << 8) | Cmnd->device->lun;
-#else
- param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
-#endif
- param[2] = i & 0xffff;
- param[3] = i >> 16;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : scsi abort failure: %x\n", hostdata->host_id, param[0]);
- if (param[0] == 0x4005)
- Cmnd->result = DID_ERROR << 16;
- if (param[0] == 0x4006)
- Cmnd->result = DID_BAD_TARGET << 16;
- return_status = FAILED;
- }
-
- if (return_status != SUCCESS){
- param[0] = MBOX_GET_FIRMWARE_STATE;
- isp2x00_mbox_command(host, param);
- printk("qlogicfc%d : abort failed\n", hostdata->host_id);
- printk("qlogicfc%d : firmware status is %x %x\n", hostdata->host_id, param[0], param[1]);
- }
-
- isp2x00_enable_irqs(host);
-
- LEAVE("isp2x00_abort");
-
- return return_status;
-}
-
-
-static int isp2x00_biosparam(struct scsi_device *sdev, struct block_device *n,
- sector_t capacity, int ip[])
-{
- int size = capacity;
-
- ENTER("isp2x00_biosparam");
-
- ip[0] = 64;
- ip[1] = 32;
- ip[2] = size >> 11;
- if (ip[2] > 1024) {
- ip[0] = 255;
- ip[1] = 63;
- ip[2] = size / (ip[0] * ip[1]);
- }
- LEAVE("isp2x00_biosparam");
-
- return 0;
-}
-
-static int isp2x00_reset_hardware(struct Scsi_Host *host)
-{
- u_short param[8];
- struct isp2x00_hostdata *hostdata;
- int loop_count;
- dma_addr_t busaddr;
-
- ENTER("isp2x00_reset_hardware");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- /*
- * This cannot be right - PCI writes are posted
- * (apparently this is hardware design flaw not software ?)
- */
-
- outw(0x01, host->io_port + ISP_CTRL_STATUS);
- udelay(100);
- outw(HCCR_RESET, host->io_port + HOST_HCCR);
- udelay(100);
- outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
- outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
-
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) {
- barrier();
- cpu_relax();
- }
- if (!loop_count)
- printk("qlogicfc%d : reset_hardware loop timeout\n", hostdata->host_id);
-
-
-
-#if DEBUG_ISP2x00
- printk("qlogicfc%d : mbox 0 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX0));
- printk("qlogicfc%d : mbox 1 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX1));
- printk("qlogicfc%d : mbox 2 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX2));
- printk("qlogicfc%d : mbox 3 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX3));
- printk("qlogicfc%d : mbox 4 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX4));
- printk("qlogicfc%d : mbox 5 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX5));
- printk("qlogicfc%d : mbox 6 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX6));
- printk("qlogicfc%d : mbox 7 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX7));
-#endif /* DEBUG_ISP2x00 */
-
- DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id));
-
-#if defined(CONFIG_SCSI_QLOGIC_FC_FIRMWARE)
- {
- int i;
- unsigned short * risc_code = NULL;
- unsigned short risc_code_len = 0;
- if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2100){
- risc_code = risc_code2100;
- risc_code_len = risc_code_length2100;
- }
- else if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2200){
- risc_code = risc_code2200;
- risc_code_len = risc_code_length2200;
- }
-
- for (i = 0; i < risc_code_len; i++) {
- param[0] = MBOX_WRITE_RAM_WORD;
- param[1] = risc_code_addr01 + i;
- param[2] = risc_code[i];
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : firmware load failure\n", hostdata->host_id);
- return 1;
- }
- }
- }
-#endif /* RELOAD_FIRMWARE */
-
- param[0] = MBOX_VERIFY_CHECKSUM;
- param[1] = risc_code_addr01;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : ram checksum failure\n", hostdata->host_id);
- return 1;
- }
- DEBUG(printk("qlogicfc%d : executing firmware\n", hostdata->host_id));
-
- param[0] = MBOX_EXEC_FIRMWARE;
- param[1] = risc_code_addr01;
-
- isp2x00_mbox_command(host, param);
-
- param[0] = MBOX_ABOUT_FIRMWARE;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : about firmware failure\n", hostdata->host_id);
- return 1;
- }
- DEBUG(printk("qlogicfc%d : firmware major revision %d\n", hostdata->host_id, param[1]));
- DEBUG(printk("qlogicfc%d : firmware minor revision %d\n", hostdata->host_id, param[2]));
-
-#ifdef USE_NVRAM_DEFAULTS
-
- if (isp2x00_get_nvram_defaults(host, &hostdata->control_block) != 0) {
- printk("qlogicfc%d : Could not read from NVRAM\n", hostdata->host_id);
- }
-#endif
-
- hostdata->wwn = (u64) (cpu_to_le16(hostdata->control_block.node_name[0])) << 56;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[0]) & 0xff00) << 48;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0xff00) << 24;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0x00ff) << 48;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0x00ff) << 24;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0xff00) << 8;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0x00ff) << 8;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0xff00) >> 8;
-
- /* FIXME: If the DMA transfer goes one way only, this should use
- * PCI_DMA_TODEVICE and below as well.
- */
- busaddr = pci_map_page(hostdata->pci_dev,
- virt_to_page(&hostdata->control_block),
- offset_in_page(&hostdata->control_block),
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
-
- param[0] = MBOX_INIT_FIRMWARE;
- param[2] = (u_short) (pci64_dma_lo32(busaddr) >> 16);
- param[3] = (u_short) (pci64_dma_lo32(busaddr) & 0xffff);
- param[4] = 0;
- param[5] = 0;
- param[6] = (u_short) (pci64_dma_hi32(busaddr) >> 16);
- param[7] = (u_short) (pci64_dma_hi32(busaddr) & 0xffff);
- isp2x00_mbox_command(host, param);
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id, param[0]);
- pci_unmap_page(hostdata->pci_dev, busaddr,
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
- return 1;
- }
- param[0] = MBOX_GET_FIRMWARE_STATE;
- isp2x00_mbox_command(host, param);
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id, param[0]);
- pci_unmap_page(hostdata->pci_dev, busaddr,
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
- return 1;
- }
-
- pci_unmap_page(hostdata->pci_dev, busaddr,
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
- LEAVE("isp2x00_reset_hardware");
-
- return 0;
-}
-
-#ifdef USE_NVRAM_DEFAULTS
-
-static int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block)
-{
-
- u_short value;
- if (isp2x00_read_nvram_word(host, 0) != 0x5349)
- return 1;
-
- value = isp2x00_read_nvram_word(host, 8);
- control_block->node_name[0] = cpu_to_le16(isp2x00_read_nvram_word(host, 9));
- control_block->node_name[1] = cpu_to_le16(isp2x00_read_nvram_word(host, 10));
- control_block->node_name[2] = cpu_to_le16(isp2x00_read_nvram_word(host, 11));
- control_block->node_name[3] = cpu_to_le16(isp2x00_read_nvram_word(host, 12));
- control_block->hard_addr = cpu_to_le16(isp2x00_read_nvram_word(host, 13));
-
- return 0;
-
-}
-
-#endif
-
-static int isp2x00_init(struct Scsi_Host *sh)
-{
- u_long io_base;
- struct isp2x00_hostdata *hostdata;
- u_char revision;
- u_int irq;
- u_short command;
- struct pci_dev *pdev;
-
-
- ENTER("isp2x00_init");
-
- hostdata = (struct isp2x00_hostdata *) sh->hostdata;
- pdev = hostdata->pci_dev;
-
- if (pci_read_config_word(pdev, PCI_COMMAND, &command)
- || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) {
- printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id);
- return 1;
- }
- io_base = pci_resource_start(pdev, 0);
- irq = pdev->irq;
-
-
- if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
- printk("qlogicfc%d : 0x%04x is not QLogic vendor ID\n", hostdata->host_id,
- pdev->vendor);
- return 1;
- }
- if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100 && pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2200) {
- printk("qlogicfc%d : 0x%04x does not match ISP2100 or ISP2200 device id\n", hostdata->host_id,
- pdev->device);
- return 1;
- }
- if (!(command & PCI_COMMAND_IO) ||
- !(pdev->resource[0].flags & IORESOURCE_IO)) {
- printk("qlogicfc%d : i/o mapping is disabled\n", hostdata->host_id);
- return 1;
- }
-
- pci_set_master(pdev);
- if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5)
- printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id, revision);
-
-
- hostdata->revision = revision;
-
- sh->irq = irq;
- sh->io_port = io_base;
-
- LEAVE("isp2x00_init");
-
- return 0;
-}
-
-#if USE_NVRAM_DEFAULTS
-
-#define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */
-
-
-u_short isp2x00_read_nvram_word(struct Scsi_Host * host, u_short byte)
-{
- int i;
- u_short value, output, input;
-
- outw(0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(0x3, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
-
- byte &= 0xff;
- byte |= 0x0600;
- for (i = 10; i >= 0; i--) {
- output = ((byte >> i) & 0x1) ? 0x4 : 0x0;
- outw(output | 0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(output | 0x3, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(output | 0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- }
-
- for (i = 0xf, value = 0; i >= 0; i--) {
- value <<= 1;
- outw(0x3, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- input = inw(host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- if (input & 0x8)
- value |= 1;
- }
-
- outw(0x0, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
-
- return value;
-}
-
-
-#endif /* USE_NVRAM_DEFAULTS */
-
-
-
-/*
- * currently, this is only called during initialization or abort/reset,
- * at which times interrupts are disabled, so polling is OK, I guess...
- */
-static int isp2x00_mbox_command(struct Scsi_Host *host, u_short param[])
-{
- int loop_count;
- struct isp2x00_hostdata *hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- if (mbox_param[param[0]] == 0 || hostdata->adapter_state == AS_FIRMWARE_DEAD)
- return 1;
-
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) {
- barrier();
- cpu_relax();
- }
- if (!loop_count) {
- printk("qlogicfc%d : mbox_command loop timeout #1\n", hostdata->host_id);
- param[0] = 0x4006;
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- return 1;
- }
- hostdata->mbox_done = 0;
-
- if (mbox_param[param[0]] == 0)
- printk("qlogicfc%d : invalid mbox command\n", hostdata->host_id);
-
- if (mbox_param[param[0]] & 0x80)
- outw(param[7], host->io_port + MBOX7);
- if (mbox_param[param[0]] & 0x40)
- outw(param[6], host->io_port + MBOX6);
- if (mbox_param[param[0]] & 0x20)
- outw(param[5], host->io_port + MBOX5);
- if (mbox_param[param[0]] & 0x10)
- outw(param[4], host->io_port + MBOX4);
- if (mbox_param[param[0]] & 0x08)
- outw(param[3], host->io_port + MBOX3);
- if (mbox_param[param[0]] & 0x04)
- outw(param[2], host->io_port + MBOX2);
- if (mbox_param[param[0]] & 0x02)
- outw(param[1], host->io_port + MBOX1);
- if (mbox_param[param[0]] & 0x01)
- outw(param[0], host->io_port + MBOX0);
-
-
- outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR);
-
- while (1) {
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && !(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
- barrier();
- cpu_relax();
- }
-
- if (!loop_count) {
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- printk("qlogicfc%d : mbox_command loop timeout #2\n", hostdata->host_id);
- break;
- }
- isp2x00_intr_handler(host->irq, host, NULL);
-
- if (hostdata->mbox_done == 1)
- break;
-
- }
-
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + MBOX0) == 0x04) {
- barrier();
- cpu_relax();
- }
- if (!loop_count)
- printk("qlogicfc%d : mbox_command loop timeout #3\n", hostdata->host_id);
-
- param[7] = inw(host->io_port + MBOX7);
- param[6] = inw(host->io_port + MBOX6);
- param[5] = inw(host->io_port + MBOX5);
- param[4] = inw(host->io_port + MBOX4);
- param[3] = inw(host->io_port + MBOX3);
- param[2] = inw(host->io_port + MBOX2);
- param[1] = inw(host->io_port + MBOX1);
- param[0] = inw(host->io_port + MBOX0);
-
-
- outw(0x0, host->io_port + PCI_SEMAPHORE);
-
- if (inw(host->io_port + HOST_HCCR) & 0x0080) {
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- printk("qlogicfc%d : mbox op is still pending\n", hostdata->host_id);
- }
- return 0;
-}
-
-#if DEBUG_ISP2x00_INTR
-
-void isp2x00_print_status_entry(struct Status_Entry *status)
-{
- printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
- status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
- printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n",
- le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status));
- printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n",
- le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags));
- printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n",
- le16_to_cpu(status->res_info_len), le16_to_cpu(status->req_sense_len));
- printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", le32_to_cpu(status->residual), status->res_info[3]);
-
-}
-
-#endif /* DEBUG_ISP2x00_INTR */
-
-
-#if DEBUG_ISP2x00
-
-void isp2x00_print_scsi_cmd(Scsi_Cmnd * cmd)
-{
- int i;
-
- printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
- cmd->target, cmd->lun, cmd->cmd_len);
- printk("qlogicfc : command = ");
- for (i = 0; i < cmd->cmd_len; i++)
- printk("0x%02x ", cmd->cmnd[i]);
- printk("\n");
-}
-
-#endif /* DEBUG_ISP2x00 */
-
-MODULE_LICENSE("GPL");
-
-static struct scsi_host_template driver_template = {
- .detect = isp2x00_detect,
- .release = isp2x00_release,
- .info = isp2x00_info,
- .queuecommand = isp2x00_queuecommand,
- .eh_abort_handler = isp2x00_abort,
- .bios_param = isp2x00_biosparam,
- .can_queue = QLOGICFC_REQ_QUEUE_LEN,
- .this_id = -1,
- .sg_tablesize = QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN),
- .cmd_per_lun = QLOGICFC_CMD_PER_LUN,
- .use_clustering = ENABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/qlogicfc_asm.c b/drivers/scsi/qlogicfc_asm.c
deleted file mode 100644
index b1d45102d388..000000000000
--- a/drivers/scsi/qlogicfc_asm.c
+++ /dev/null
@@ -1,9751 +0,0 @@
-/************************************************************************
- * *
- * --- ISP2100 Fabric Initiator/Target Firmware --- *
- * with expanded LUN addressing *
- * and FcTape (FCP-2) support *
- * *
- * *
- ************************************************************************
- Copyright (C) 2000 and 2001 Qlogic Corporation
- (www.qlogic.com)
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-************************************************************************/
-
-/*
- * Firmware Version 1.19.16 (10:36 Nov 02, 2000)
- */
-
-static unsigned short risc_code_addr01 = 0x1000 ;
-
-static unsigned short risc_code_length2100 = 0x9260;
-static unsigned short risc_code2100[] = {
- 0x0078, 0x102d, 0x0000, 0x9260, 0x0000, 0x0001, 0x0013, 0x0010,
- 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
- 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
- 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972,
- 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
- 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1,
- 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff,
- 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04,
- 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c,
- 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020,
- 0x2039, 0x8fff, 0x20a1, 0xaa00, 0x2708, 0x810d, 0x810d, 0x810d,
- 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8,
- 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102,
- 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1,
- 0xa260, 0x2009, 0x0000, 0x20a9, 0x07a0, 0x41a4, 0x3400, 0x20c9,
- 0xa7ff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x255d,
- 0x2051, 0xa300, 0x2a70, 0x775e, 0xa786, 0x8fff, 0x0040, 0x1092,
- 0x705b, 0xca00, 0x7057, 0xc9f1, 0x7063, 0x0200, 0x7067, 0x0200,
- 0x0078, 0x109a, 0x7057, 0xba01, 0x7063, 0x0100, 0x7067, 0x0100,
- 0x705b, 0xba00, 0x1078, 0x12df, 0x1078, 0x13c0, 0x1078, 0x1569,
- 0x1078, 0x1ca4, 0x1078, 0x4229, 0x1078, 0x74cf, 0x1078, 0x134b,
- 0x1078, 0x2a3f, 0x1078, 0x4da2, 0x1078, 0x48b2, 0x1078, 0x57df,
- 0x1078, 0x21f7, 0x1078, 0x5abf, 0x1078, 0x5369, 0x1078, 0x210d,
- 0x1078, 0x21d4, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf,
- 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068,
- 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70,
- 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000,
- 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x35bc, 0x1078, 0x2a67,
- 0x1078, 0x4df2, 0x1078, 0x4a75, 0x2009, 0x0100, 0x2104, 0xa082,
- 0x0002, 0x0048, 0x10f3, 0x1078, 0x57fb, 0x0078, 0x10d6, 0x1079,
- 0x10f7, 0x0078, 0x10dc, 0x1078, 0x6fa9, 0x0078, 0x10eb, 0x1101,
- 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078,
- 0x1328, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086,
- 0x0001, 0x00c0, 0x1198, 0x1078, 0x3a43, 0x2079, 0x0100, 0x7844,
- 0xa005, 0x00c0, 0x1198, 0x2011, 0x4129, 0x1078, 0x58d4, 0x1078,
- 0x1ab1, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011,
- 0x8010, 0x73c0, 0x1078, 0x3579, 0x2001, 0xffff, 0x1078, 0x5975,
- 0x7238, 0xc284, 0x723a, 0x2001, 0xa30c, 0x2014, 0xc2ac, 0x2202,
- 0x1078, 0x6db5, 0x2011, 0x0004, 0x1078, 0x8a59, 0x1078, 0x47ce,
- 0x1078, 0x4211, 0x0040, 0x1144, 0x7083, 0x0001, 0x70bb, 0x0000,
- 0x1078, 0x3bf5, 0x0078, 0x1198, 0x1078, 0x4897, 0x0040, 0x114d,
- 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x8ddf, 0x70c8,
- 0xd09c, 0x00c0, 0x1159, 0x7094, 0xa005, 0x0040, 0x1159, 0x1078,
- 0x41f5, 0x70d3, 0x0000, 0x70cf, 0x0000, 0x72c8, 0x2079, 0xa351,
- 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ca, 0xa296, 0x0004,
- 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8a59, 0x708f, 0x0000,
- 0x7093, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x260d, 0x2011,
- 0x0005, 0x1078, 0x6ef2, 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100,
- 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x708f, 0x0000,
- 0x7093, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x6ef2,
- 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f,
- 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e,
- 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078,
- 0x71e0, 0x027f, 0x1078, 0xa190, 0x037f, 0x027f, 0x017f, 0x1078,
- 0x2921, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706b, 0x0000, 0x706c,
- 0xa084, 0x00ff, 0x706e, 0x7097, 0x0000, 0x007c, 0x127e, 0x2091,
- 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7090, 0xa086,
- 0xffff, 0x0040, 0x11d1, 0x1078, 0x260d, 0x1078, 0x6109, 0x0078,
- 0x1244, 0x70c8, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd,
- 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
- 0x0040, 0x11fd, 0x70cc, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078,
- 0x278a, 0x1078, 0x6109, 0x70c8, 0xd094, 0x00c0, 0x1244, 0x2011,
- 0x0001, 0x2019, 0x0000, 0x1078, 0x27c2, 0x1078, 0x6109, 0x0078,
- 0x1244, 0x70d0, 0xa005, 0x00c0, 0x1244, 0x708c, 0xa005, 0x00c0,
- 0x1244, 0x1078, 0x4897, 0x00c0, 0x1244, 0x2001, 0xa352, 0x2004,
- 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
- 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x121a, 0x6000, 0xd0ec,
- 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f,
- 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003,
- 0x0003, 0x7093, 0xffff, 0x2001, 0x0000, 0x1078, 0x2480, 0x1078,
- 0x35f7, 0x2001, 0xa5ac, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c,
- 0x2011, 0x0000, 0x1078, 0x6ef2, 0x2011, 0x0000, 0x1078, 0x6efc,
- 0x1078, 0x6109, 0x1078, 0x61d3, 0x127f, 0x007c, 0x017e, 0x0f7e,
- 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078,
- 0x41de, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040,
- 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008,
- 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5975, 0x7900, 0xa18a,
- 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009,
- 0x00f8, 0x1078, 0x41de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
- 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0,
- 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x2480, 0x0078,
- 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0,
- 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f,
- 0x0000, 0x2009, 0x00f8, 0x1078, 0x41de, 0x20a9, 0x000e, 0x0005,
- 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010,
- 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4,
- 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009,
- 0xa331, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4,
- 0x200b, 0x0000, 0x1078, 0x251e, 0x2001, 0x0001, 0x1078, 0x2480,
- 0x0078, 0x12d3, 0x2001, 0xa331, 0x2003, 0x0000, 0x7828, 0xc09d,
- 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f,
- 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70,
- 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, 0x12eb, 0x704f,
- 0xffff, 0x0078, 0x12ed, 0x704f, 0x0000, 0x7053, 0xffff, 0x706b,
- 0x0000, 0x706f, 0x0000, 0x1078, 0x8ddf, 0x2061, 0xa58c, 0x6003,
- 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013,
- 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061,
- 0xa594, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f,
- 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f,
- 0x0000, 0x2061, 0xa5a3, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b,
- 0x4943, 0x600f, 0x2020, 0x2001, 0xa325, 0x2003, 0x0000, 0x007c,
- 0x2091, 0x8000, 0x0068, 0x132a, 0x007e, 0x017e, 0x2079, 0x0000,
- 0x7818, 0xd084, 0x00c0, 0x1330, 0x017f, 0x792e, 0x007f, 0x782a,
- 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001,
- 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa300, 0x7803, 0x0005,
- 0x0078, 0x1348, 0x007c, 0x2071, 0xa300, 0x7158, 0x712e, 0x2021,
- 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, 0x1361, 0x705c,
- 0xa302, 0x00c8, 0x1361, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078,
- 0x1353, 0x200b, 0x0000, 0x74a6, 0x74aa, 0x007c, 0x0e7e, 0x127e,
- 0x2091, 0x8000, 0x2071, 0xa300, 0x70a8, 0xa0ea, 0x0010, 0x00c8,
- 0x1374, 0xa06e, 0x0078, 0x137e, 0x8001, 0x70aa, 0x702c, 0x2068,
- 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f,
- 0x007c, 0x0e7e, 0x2071, 0xa300, 0x127e, 0x2091, 0x8000, 0x70a8,
- 0x8001, 0x00c8, 0x138e, 0xa06e, 0x0078, 0x1397, 0x70aa, 0x702c,
- 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f,
- 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa300,
- 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa, 0x127f,
- 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13b6, 0x6804, 0x6807, 0x0000,
- 0x007e, 0x1078, 0x139a, 0x0d7f, 0x0078, 0x13aa, 0x007c, 0x0e7e,
- 0x2071, 0xa300, 0x70a8, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c,
- 0x0e7e, 0x2071, 0xa5d0, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f,
- 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f,
- 0x007c, 0x0e7e, 0x2270, 0x700b, 0x0000, 0x2071, 0xa5d0, 0x7018,
- 0xa088, 0xa5d9, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004,
- 0xa005, 0x00c0, 0x13e9, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa,
- 0x0f7f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa5d0, 0x7004, 0xa005,
- 0x00c0, 0x13f8, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa, 0x0f7f,
- 0x0e7f, 0x007c, 0x7000, 0x0079, 0x13fd, 0x1401, 0x146b, 0x1488,
- 0x1488, 0x7018, 0x711c, 0xa106, 0x00c0, 0x1409, 0x7007, 0x0000,
- 0x007c, 0x0d7e, 0xa180, 0xa5d9, 0x2004, 0x700a, 0x2068, 0x8108,
- 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828,
- 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c,
- 0x7016, 0x6804, 0x0d7f, 0xd084, 0x0040, 0x142b, 0x7007, 0x0001,
- 0x1078, 0x1430, 0x007c, 0x7007, 0x0002, 0x1078, 0x1446, 0x007c,
- 0x017e, 0x027e, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8,
- 0x143b, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803,
- 0x0020, 0x7803, 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e,
- 0x137e, 0x147e, 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803,
- 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x145a,
- 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
- 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f,
- 0x027f, 0x017f, 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa3f9,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e,
- 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
- 0x7002, 0x700b, 0xa3f4, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c,
- 0x137e, 0x147e, 0x157e, 0x2001, 0xa428, 0x209c, 0x20a1, 0x0014,
- 0x7803, 0x0026, 0x2001, 0xa429, 0x20ac, 0x53a6, 0x2099, 0xa42a,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e,
- 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
- 0x7002, 0x700b, 0xa425, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c,
- 0x017e, 0x0e7e, 0x2071, 0xa5d0, 0x0f7e, 0x2079, 0x0010, 0x7904,
- 0x7803, 0x0002, 0xd1fc, 0x0040, 0x14c2, 0xa18c, 0x0700, 0x7004,
- 0x1079, 0x14c6, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13fa, 0x14ce,
- 0x14fb, 0x1523, 0x1556, 0x14cc, 0x0078, 0x14cc, 0xa18c, 0x0700,
- 0x00c0, 0x14f4, 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099,
- 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016,
- 0x157f, 0x147f, 0x137f, 0x700c, 0xa005, 0x0040, 0x1510, 0x1078,
- 0x1430, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007,
- 0x0000, 0x1078, 0x13fa, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003,
- 0x0200, 0x0078, 0x14ef, 0xa18c, 0x0700, 0x00c0, 0x1506, 0x700c,
- 0xa005, 0x0040, 0x1510, 0x1078, 0x1446, 0x007c, 0x7008, 0xa080,
- 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x1078, 0x13fa, 0x007c,
- 0x0d7e, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
- 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000,
- 0x1078, 0x13fa, 0x007c, 0xa18c, 0x0700, 0x00c0, 0x1550, 0x137e,
- 0x147e, 0x157e, 0x2001, 0xa3f7, 0x2004, 0xa080, 0x000d, 0x20a0,
- 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001,
- 0xa3f9, 0x2004, 0xd0bc, 0x0040, 0x1546, 0x2001, 0xa402, 0x2004,
- 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f,
- 0x137f, 0x7007, 0x0000, 0x1078, 0x4e9b, 0x1078, 0x13fa, 0x007c,
- 0x2011, 0x8003, 0x1078, 0x3579, 0x0078, 0x1554, 0xa18c, 0x0700,
- 0x00c0, 0x1563, 0x2001, 0xa427, 0x2003, 0x0100, 0x7007, 0x0000,
- 0x1078, 0x13fa, 0x007c, 0x2011, 0x8004, 0x1078, 0x3579, 0x0078,
- 0x1567, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa5e1,
- 0x7803, 0x0004, 0x7003, 0x0000, 0x700f, 0xa5e7, 0x7013, 0xa5e7,
- 0x780f, 0x0076, 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184,
- 0x0007, 0x0079, 0x1583, 0x158b, 0x15d1, 0x158b, 0x158b, 0x158b,
- 0x15b6, 0x159a, 0x158f, 0xa085, 0x0001, 0x0078, 0x15eb, 0x684c,
- 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858,
- 0x0078, 0x15d9, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x158b,
- 0x684c, 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0x6858, 0x0078, 0x15e1, 0xa18c, 0x00ff,
- 0xa186, 0x0015, 0x00c0, 0x158b, 0x684c, 0xd0ac, 0x0040, 0x158b,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078,
- 0x15e1, 0x684c, 0xd0ac, 0x0040, 0x158b, 0xa006, 0x682e, 0x682a,
- 0x6858, 0xa18c, 0x000f, 0xa188, 0x2015, 0x210c, 0x6932, 0x2d08,
- 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
- 0x6912, 0x6980, 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000,
- 0x2001, 0x020a, 0x2004, 0x82ff, 0x0040, 0x160e, 0xa280, 0x0004,
- 0x0d7e, 0x206c, 0x684c, 0xd0dc, 0x00c0, 0x160a, 0x1078, 0x157e,
- 0x0040, 0x160a, 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016,
- 0x0078, 0x160e, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e,
- 0x037e, 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000,
- 0xa005, 0x00c0, 0x1622, 0x7206, 0x2001, 0x1643, 0x007e, 0x2260,
- 0x0078, 0x17be, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a,
- 0x8108, 0xa182, 0xa602, 0x0048, 0x162f, 0x2009, 0xa5e7, 0x710e,
- 0x7010, 0xa102, 0xa082, 0x0009, 0x0040, 0x163a, 0xa080, 0x001b,
- 0x00c0, 0x163d, 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0,
- 0x1643, 0x1078, 0x179f, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e,
- 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f,
- 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005,
- 0x0040, 0x16cf, 0x6808, 0xa005, 0x0040, 0x173c, 0x7000, 0xa005,
- 0x00c0, 0x1664, 0x0078, 0x16c4, 0x700c, 0x7110, 0xa106, 0x00c0,
- 0x1745, 0x7004, 0xa406, 0x00c0, 0x16c4, 0x2001, 0x0005, 0x2004,
- 0xd08c, 0x0040, 0x1681, 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460,
- 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0040, 0x173c, 0x0078,
- 0x165e, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x166d, 0x7804,
- 0xa084, 0x6000, 0x0040, 0x1692, 0xa086, 0x6000, 0x0040, 0x1692,
- 0x0078, 0x166d, 0x7100, 0xa186, 0x0002, 0x00c0, 0x16b2, 0x0e7e,
- 0x2b68, 0x6818, 0x2060, 0x1078, 0x1fea, 0x2804, 0xac70, 0x6034,
- 0xd09c, 0x00c0, 0x16a7, 0x7108, 0x720c, 0x0078, 0x16a9, 0x7110,
- 0x7214, 0x6810, 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f,
- 0x0078, 0x16b6, 0xa186, 0x0001, 0x00c0, 0x16be, 0x7820, 0x6910,
- 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004,
- 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0,
- 0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0078, 0x1745, 0x6808,
- 0xa005, 0x0040, 0x173c, 0x7000, 0xa005, 0x00c0, 0x16d9, 0x0078,
- 0x173c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x16e2, 0x7004, 0xa406,
- 0x00c0, 0x173c, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x16f6,
- 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002,
- 0x2004, 0xa005, 0x0040, 0x173c, 0x0078, 0x16d3, 0x2001, 0x0207,
- 0x2004, 0xd09c, 0x00c0, 0x16e2, 0x2001, 0x0005, 0x2004, 0xd08c,
- 0x00c0, 0x16e8, 0x7804, 0xa084, 0x6000, 0x0040, 0x170d, 0xa086,
- 0x6000, 0x0040, 0x170d, 0x0078, 0x16e2, 0x7007, 0x0000, 0xa016,
- 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x172e, 0xa08e, 0x0002,
- 0x00c0, 0x173c, 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x1fea,
- 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x172a, 0x7308, 0x720c,
- 0x0078, 0x172c, 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318,
- 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816,
- 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0,
- 0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0c7f, 0x0d7f, 0x127f,
- 0x007c, 0x0f7e, 0x0e7e, 0x027e, 0x037e, 0x047e, 0x1078, 0x1af7,
- 0x027e, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0000, 0x0040, 0x1790,
- 0x7004, 0xac06, 0x00c0, 0x1781, 0x2079, 0x0030, 0x7000, 0xa086,
- 0x0003, 0x0040, 0x1781, 0x7804, 0xd0fc, 0x00c0, 0x177d, 0x2001,
- 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1763, 0x7803, 0x0004, 0x7804,
- 0xd0ac, 0x00c0, 0x176f, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003,
- 0x0003, 0x7007, 0x0000, 0x0078, 0x1781, 0x1078, 0x18e2, 0x0078,
- 0x1753, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa5e7, 0x2104, 0xac06,
- 0x00c0, 0x178b, 0x200a, 0xa188, 0x0003, 0x00f0, 0x1786, 0x157f,
- 0x027f, 0x2001, 0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138,
- 0x2202, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, 0x007c, 0x700c,
- 0x7110, 0xa106, 0x00c0, 0x17a7, 0x7003, 0x0000, 0x007c, 0x2104,
- 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182,
- 0xa602, 0x0048, 0x17b5, 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106,
- 0x00c0, 0x17be, 0x2001, 0x0138, 0x2003, 0x0008, 0x8cff, 0x00c0,
- 0x17c5, 0x1078, 0x1b22, 0x0078, 0x1823, 0x6010, 0x2068, 0x2d58,
- 0x6828, 0xa406, 0x00c0, 0x17d0, 0x682c, 0xa306, 0x0040, 0x17fe,
- 0x601c, 0xa086, 0x0008, 0x0040, 0x17fe, 0x6024, 0xd0f4, 0x00c0,
- 0x17fa, 0xd0d4, 0x0040, 0x17f6, 0x6038, 0xa402, 0x6034, 0xa303,
- 0x0040, 0x17e4, 0x00c8, 0x17f6, 0x643a, 0x6336, 0x6c2a, 0x6b2e,
- 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80,
- 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x17fa, 0x1078, 0x8d8e,
- 0x0040, 0x17c1, 0x1078, 0x2035, 0x00c0, 0x17c1, 0x0c7e, 0x7004,
- 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, 0x0040,
- 0x180f, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17c1, 0x6824,
- 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
- 0x2009, 0x0011, 0x1078, 0x1824, 0x0040, 0x1822, 0x2009, 0x0001,
- 0x1078, 0x1824, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18bb, 0xa03e,
- 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1846, 0xd0f4, 0x00c0, 0x1856,
- 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1836, 0x189d, 0x185d,
- 0x185d, 0x189d, 0x189d, 0x1895, 0x189d, 0x185d, 0x189d, 0x1863,
- 0x1863, 0x189d, 0x189d, 0x189d, 0x188c, 0x1863, 0xc0fc, 0x6852,
- 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, 0x18a0,
- 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0xc0f4, 0x6852,
- 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18a7, 0x6b08, 0x6a0c, 0x6d00,
- 0x6c04, 0x0078, 0x18a0, 0x7b0c, 0xd3bc, 0x0040, 0x1884, 0x7004,
- 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1884,
- 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff,
- 0x00c0, 0x187f, 0x6810, 0xa302, 0x0048, 0x187f, 0x6b10, 0x2011,
- 0x0000, 0x2468, 0x0078, 0x1886, 0x6b10, 0x6a14, 0x6d00, 0x6c04,
- 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0x0d7f, 0x0d7e, 0x6834, 0xa084,
- 0x00ff, 0xa086, 0x001e, 0x00c0, 0x189d, 0x0d7f, 0x1078, 0x1fd1,
- 0x00c0, 0x1824, 0xa00e, 0x0078, 0x18bb, 0x0d7f, 0x1078, 0x1328,
- 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000,
- 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201,
- 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, 0xa203,
- 0x6816, 0x1078, 0x1fd1, 0x007c, 0x1078, 0x1328, 0x1078, 0x1c52,
- 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, 0x1078,
- 0x1ac6, 0x1078, 0x8a44, 0x0040, 0x18db, 0x6808, 0x8001, 0x680a,
- 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff,
- 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758, 0x0078, 0x1aad,
- 0x1078, 0x1328, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, 0x2b68,
- 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0,
- 0x18be, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x18e0, 0x7000,
- 0x0079, 0x18fa, 0x1902, 0x1904, 0x1a06, 0x1a84, 0x1a9b, 0x1902,
- 0x1902, 0x1902, 0x1078, 0x1328, 0x8001, 0x7002, 0xa184, 0x0880,
- 0x00c0, 0x1919, 0x8aff, 0x0040, 0x199b, 0x2009, 0x0001, 0x1078,
- 0x1824, 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078,
- 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x1979,
- 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1930, 0x7c20, 0x7d24,
- 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1932,
- 0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500,
- 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, 0x6024,
- 0xd0f4, 0x00c0, 0x1945, 0x633a, 0x6236, 0x0c7f, 0x2400, 0x6910,
- 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, 0x027f,
- 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x1fea, 0x2a00, 0x6826,
- 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, 0x6808,
- 0x8001, 0x680a, 0x00c0, 0x196e, 0x684c, 0xd0e4, 0x0040, 0x196e,
- 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x7000, 0xa086,
- 0x0004, 0x0040, 0x1aad, 0x7003, 0x0000, 0x1078, 0x179f, 0x0078,
- 0x1aad, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x1980, 0x1078, 0xa20c,
- 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4893,
- 0x0040, 0x198d, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff,
- 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980,
- 0x6916, 0x0078, 0x1aad, 0x7004, 0x0c7e, 0x2060, 0x6024, 0x0c7f,
- 0xd0f4, 0x0040, 0x19a8, 0x6808, 0x8001, 0x680a, 0x0078, 0x1aad,
- 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19c0, 0x7003,
- 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19bc, 0x7004, 0x2060,
- 0x2009, 0x0048, 0x1078, 0x756c, 0x1078, 0x179f, 0x0078, 0x1aad,
- 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816,
- 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214,
- 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b,
- 0x810b, 0x1078, 0x1b4d, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803,
- 0x0001, 0x7804, 0xd0fc, 0x0040, 0x19e1, 0x7803, 0x0002, 0x7803,
- 0x0004, 0x780f, 0x0076, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009,
- 0x0048, 0x1078, 0x756c, 0x1078, 0x1b81, 0x0040, 0x19bc, 0x7908,
- 0xd1ec, 0x00c0, 0x19ff, 0x2009, 0x0009, 0x0078, 0x1a01, 0x2009,
- 0x0019, 0x7902, 0x7003, 0x0003, 0x0078, 0x1aad, 0x8001, 0x7002,
- 0xd194, 0x0040, 0x1a18, 0x7804, 0xd0fc, 0x00c0, 0x18ea, 0x8aff,
- 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad,
- 0xa184, 0x0880, 0x00c0, 0x1a25, 0x8aff, 0x0040, 0x1aad, 0x2009,
- 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003,
- 0x0000, 0xd1bc, 0x00c0, 0x1a65, 0x027e, 0x037e, 0x7808, 0xd0ec,
- 0x00c0, 0x1a38, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a3a,
- 0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x1078, 0x1fea, 0x0d7e, 0x0f7e,
- 0x2d78, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a55, 0x6808,
- 0x2008, 0xa31a, 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c,
- 0x7814, 0xa101, 0x7816, 0x0078, 0x1a61, 0x6810, 0x2008, 0xa31a,
- 0x6814, 0xa213, 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101,
- 0x7816, 0x0f7f, 0x0d7f, 0x0078, 0x1934, 0x057e, 0x7d0c, 0x1078,
- 0xa20c, 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078,
- 0x4893, 0x0040, 0x1a76, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b,
- 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912,
- 0x6980, 0x6916, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000,
- 0x7004, 0xa00d, 0x0040, 0x1a97, 0x6808, 0x8001, 0x680a, 0x00c0,
- 0x1a97, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x1078,
- 0x179f, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004,
- 0x2060, 0x6010, 0xa005, 0x0040, 0x1a97, 0x2068, 0x6808, 0x8000,
- 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x17be, 0x017f, 0x007f, 0x127f,
- 0x007c, 0x127e, 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0,
- 0x1ac4, 0x700c, 0x7110, 0xa106, 0x0040, 0x1ac4, 0x20e1, 0x9028,
- 0x700f, 0xa5e7, 0x7013, 0xa5e7, 0x127f, 0x007c, 0x0c7e, 0x1078,
- 0x1af7, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1aed,
- 0x2104, 0xa005, 0x0040, 0x1ada, 0x2060, 0x6010, 0x2060, 0x6008,
- 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xa602, 0x0048, 0x1ae2,
- 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106, 0x00c0, 0x1acb, 0x2001,
- 0x0138, 0x2003, 0x0008, 0x0078, 0x1acb, 0x2001, 0x015d, 0x200c,
- 0x810a, 0x2102, 0x2001, 0x0138, 0x2202, 0x0c7f, 0x007c, 0x2001,
- 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141,
- 0x201c, 0xd3dc, 0x00c0, 0x1b14, 0x2001, 0x0109, 0x201c, 0xa39c,
- 0x0048, 0x00c0, 0x1b14, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0,
- 0x1b14, 0x8421, 0x00c0, 0x1afe, 0x007c, 0x2011, 0x0201, 0x2009,
- 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b21, 0x8109, 0x00c0, 0x1b19,
- 0x007c, 0x007c, 0x1078, 0x1b15, 0x0040, 0x1b4a, 0x7908, 0xd1ec,
- 0x00c0, 0x1b3a, 0x1078, 0x1b81, 0x0040, 0x1b3a, 0x7803, 0x0009,
- 0x7904, 0xd1fc, 0x0040, 0x1b30, 0x7803, 0x0006, 0x1078, 0x1b15,
- 0x0040, 0x1b4a, 0x780c, 0xd0a4, 0x00c0, 0x1b4a, 0x7007, 0x0000,
- 0x1078, 0x1b81, 0x0040, 0x1b4c, 0x7803, 0x0019, 0x7003, 0x0003,
- 0x0078, 0x1b4c, 0x1078, 0x1ac6, 0x007c, 0x0e7e, 0x2071, 0x0200,
- 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1af7, 0x2019, 0x5000,
- 0x8319, 0x0040, 0x1b6b, 0x2001, 0xa602, 0x2004, 0xa086, 0x0000,
- 0x0040, 0x1b6b, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b58, 0x1078,
- 0x1e5d, 0x0078, 0x1b56, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028,
- 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100,
- 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x0e7f,
- 0x007c, 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x1b8c,
- 0xa085, 0x0001, 0x0078, 0x1b9e, 0x2001, 0x020a, 0x81ff, 0x0040,
- 0x1b97, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1,
- 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007c, 0x7c20,
- 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c24,
- 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c24, 0x0d7e,
- 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c22, 0x6824, 0xd0d4,
- 0x00c0, 0x1c22, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1bec,
- 0x8108, 0x2104, 0x6b2c, 0xa306, 0x00c0, 0x1c22, 0x8108, 0x2104,
- 0x6a28, 0xa206, 0x00c0, 0x1c22, 0x6850, 0xc0fc, 0xc0f5, 0x6852,
- 0x686c, 0x7822, 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836,
- 0x6818, 0x2060, 0x6034, 0xd09c, 0x0040, 0x1be7, 0x6830, 0x2004,
- 0xac68, 0x6808, 0x783a, 0x680c, 0x783e, 0x0078, 0x1c20, 0xa006,
- 0x783a, 0x783e, 0x0078, 0x1c20, 0x8108, 0x2104, 0xa005, 0x00c0,
- 0x1c22, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c22, 0x6850, 0xc0f5,
- 0x6852, 0x6830, 0x2004, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004,
- 0xd09c, 0x00c0, 0x1c12, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826,
- 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e,
- 0x0078, 0x1c20, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872,
- 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e,
- 0x7803, 0x0011, 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e,
- 0x027e, 0x2071, 0xa5e1, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000,
- 0xa086, 0x0000, 0x0040, 0x1c4d, 0x8211, 0x0040, 0x1c4b, 0x2001,
- 0x0005, 0x2004, 0xd08c, 0x0040, 0x1c34, 0x7904, 0xa18c, 0x0780,
- 0x017e, 0x1078, 0x18e2, 0x017f, 0x81ff, 0x00c0, 0x1c4b, 0x2011,
- 0x0050, 0x0078, 0x1c2f, 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f,
- 0x0f7f, 0x007c, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac,
- 0x0040, 0x1ca3, 0x8109, 0x00c0, 0x1c56, 0x2009, 0x0100, 0x210c,
- 0xa18a, 0x0003, 0x1048, 0x1328, 0x1078, 0x1f75, 0x0e7e, 0x0f7e,
- 0x2071, 0xa5d0, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0040,
- 0x1c9b, 0x7800, 0x007e, 0x7820, 0x007e, 0x7830, 0x007e, 0x7834,
- 0x007e, 0x7838, 0x007e, 0x783c, 0x007e, 0x7803, 0x0004, 0x7823,
- 0x0000, 0x0005, 0x0005, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0,
- 0x1328, 0x2079, 0x0010, 0x007f, 0x783e, 0x007f, 0x783a, 0x007f,
- 0x7836, 0x007f, 0x7832, 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f,
- 0x0e7f, 0x0078, 0x1ca1, 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0,
- 0x1328, 0x1078, 0x61d3, 0x007c, 0x0e7e, 0x2071, 0xa602, 0x7003,
- 0x0000, 0x0e7f, 0x007c, 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c,
- 0xd1dc, 0x00c0, 0x1d26, 0x6934, 0xa184, 0x0007, 0x0079, 0x1cb8,
- 0x1cc0, 0x1d11, 0x1cc0, 0x1cc0, 0x1cc0, 0x1cf6, 0x1cd3, 0x1cc2,
- 0x1078, 0x1328, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e,
- 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
- 0x6958, 0x0078, 0x1d19, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
- 0x00c0, 0x1cc0, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e,
- 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0x6958, 0x0078, 0x1d22, 0xa18c, 0x00ff,
- 0xa186, 0x0015, 0x00c0, 0x1d26, 0x684c, 0xd0b4, 0x0040, 0x1e34,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0078,
- 0x1d22, 0x684c, 0xd0b4, 0x0040, 0x18bc, 0x6958, 0xa006, 0x682e,
- 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2015,
- 0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c,
- 0x0f7e, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x10c0, 0x1e5d, 0x0e7e,
- 0x0d7e, 0x2071, 0xa602, 0x7000, 0xa005, 0x00c0, 0x1dab, 0x0c7e,
- 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004,
- 0x6818, 0x0d7e, 0x2068, 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1,
- 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6,
- 0x0f7f, 0x0d7f, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
- 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004,
- 0xa086, 0x0007, 0x0040, 0x1d6d, 0xa184, 0x0007, 0x0040, 0x1d6d,
- 0x017e, 0x2009, 0x0008, 0xa102, 0x017f, 0xa108, 0x791a, 0x7116,
- 0x701e, 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e,
- 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x00c0, 0x1d84, 0x6928,
- 0x6810, 0xa106, 0x0040, 0x1d91, 0x037e, 0x047e, 0x6b14, 0x6c10,
- 0x1078, 0x2035, 0x047f, 0x037f, 0x0040, 0x1d91, 0x0c7f, 0x0078,
- 0x1dab, 0x8aff, 0x00c0, 0x1d99, 0x0c7f, 0xa085, 0x0001, 0x0078,
- 0x1dab, 0x127e, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001,
- 0x1078, 0x1daf, 0x0040, 0x1da8, 0x2009, 0x0001, 0x1078, 0x1daf,
- 0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e,
- 0x067e, 0x057e, 0x047e, 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e2d,
- 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0048, 0x1e2c,
- 0xa705, 0x0040, 0x1e2c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0,
- 0x1ddf, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1dcf, 0x1e0e,
- 0x1def, 0x1def, 0x1e0e, 0x1e0e, 0x1e06, 0x1e0e, 0x1def, 0x1e0e,
- 0x1df5, 0x1df5, 0x1e0e, 0x1e0e, 0x1e0e, 0x1dfd, 0x1df5, 0xc0fc,
- 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e12,
- 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x6b08,
- 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1e11, 0x6b10, 0x6a14, 0x6d00,
- 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x0d7f, 0x0d7e, 0x6834,
- 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1e0e, 0x0d7f, 0x1078,
- 0x1fd1, 0x00c0, 0x1db5, 0xa00e, 0x0078, 0x1e2d, 0x0d7f, 0x1078,
- 0x1328, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e,
- 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c,
- 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012,
- 0x1078, 0x1fd1, 0x0078, 0x1e2d, 0xa006, 0x027f, 0x037f, 0x047f,
- 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x1328, 0x027e, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44,
- 0x0040, 0x1e4d, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758,
- 0x20e1, 0x9040, 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc,
- 0x1078, 0x61d3, 0x027f, 0x0078, 0x1f29, 0x127e, 0x2091, 0x2200,
- 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020,
- 0x2071, 0xa602, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
- 0xa184, 0x0700, 0x00c0, 0x1e36, 0x7000, 0x0079, 0x1e77, 0x1f29,
- 0x1e7b, 0x1ef6, 0x1f27, 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1e8f,
- 0x8aff, 0x0040, 0x1eae, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0040,
- 0x1f29, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0078, 0x1f29, 0x7803,
- 0x0004, 0xd194, 0x0040, 0x1e9f, 0x6850, 0xc0fc, 0x6852, 0x8aff,
- 0x00c0, 0x1ea4, 0x684c, 0xc0f5, 0x684e, 0x0078, 0x1ea4, 0x1078,
- 0x1fea, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a,
- 0x2800, 0x6832, 0x7003, 0x0000, 0x0078, 0x1f29, 0x711c, 0x81ff,
- 0x0040, 0x1ec4, 0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001,
- 0x7000, 0x8000, 0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081,
- 0x0000, 0x7012, 0x0078, 0x1f29, 0x0f7e, 0x027e, 0x781c, 0x007e,
- 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085,
- 0x0012, 0x7816, 0x037e, 0x2019, 0x1000, 0x8319, 0x1040, 0x1328,
- 0x7820, 0xd0bc, 0x00c0, 0x1ed5, 0x037f, 0x79c8, 0x007f, 0xa102,
- 0x017f, 0x007e, 0x017e, 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f,
- 0x78ca, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f,
- 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1f29, 0x8001, 0x7002,
- 0xd194, 0x0040, 0x1f0b, 0x7804, 0xd0fc, 0x00c0, 0x1e6d, 0xd19c,
- 0x00c0, 0x1f25, 0x8aff, 0x0040, 0x1f29, 0x2009, 0x0001, 0x1078,
- 0x1daf, 0x0078, 0x1f29, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078,
- 0x1fea, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f1e,
- 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1f22, 0x6810, 0xa31a,
- 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1e9f, 0x0078, 0x1e9f, 0x1078,
- 0x1328, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f,
- 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0xa602, 0x7000, 0xa086, 0x0000,
- 0x0040, 0x1f72, 0x2079, 0x0020, 0x017e, 0x2009, 0x0207, 0x210c,
- 0xd194, 0x0040, 0x1f4f, 0x2009, 0x020c, 0x210c, 0xa184, 0x0003,
- 0x0040, 0x1f4f, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, 0x2009,
- 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x00c0, 0x1f5a,
- 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0040, 0x1f3d, 0x1078, 0x1e5d,
- 0x7000, 0xa086, 0x0000, 0x00c0, 0x1f3d, 0x017f, 0x7803, 0x0004,
- 0x7804, 0xd0ac, 0x00c0, 0x1f68, 0x20e1, 0x9040, 0x7803, 0x0002,
- 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e,
- 0x0e7e, 0x0f7e, 0x2071, 0xa602, 0x2079, 0x0020, 0x7000, 0xa086,
- 0x0000, 0x0040, 0x1fae, 0x7004, 0x2060, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x1f98, 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c,
- 0xa206, 0x00c0, 0x1f98, 0x6808, 0x7a18, 0xa206, 0x0040, 0x1fb4,
- 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004,
- 0x7003, 0x0000, 0x7004, 0x2060, 0x1078, 0x8758, 0x20e1, 0x9040,
- 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc, 0x0f7f, 0x0e7f,
- 0x0d7f, 0x0c7f, 0x027f, 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0,
- 0x1f98, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x1078, 0x1cab, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x2069, 0xa5ab, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078,
- 0x1fae, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1fe5, 0x6004, 0xa005,
- 0x0040, 0x1fe7, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2044, 0x88ff, 0x1040, 0x1328, 0x8a51, 0x007c, 0x2051,
- 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x2004,
- 0x2c00, 0xad06, 0x0040, 0x1ff9, 0x6000, 0xa005, 0x00c0, 0x1ff9,
- 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x2025,
- 0x2044, 0x88ff, 0x1040, 0x1328, 0x007c, 0x0000, 0x0011, 0x0015,
- 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015,
- 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x200a, 0x2006,
- 0x0000, 0x0000, 0x2014, 0x0000, 0x200a, 0x0000, 0x2011, 0x200e,
- 0x0000, 0x0000, 0x0000, 0x2014, 0x2011, 0x0000, 0x200c, 0x200c,
- 0x0000, 0x0000, 0x2014, 0x0000, 0x200c, 0x0000, 0x2012, 0x2012,
- 0x0000, 0x0000, 0x0000, 0x2014, 0x2012, 0x0a7e, 0x097e, 0x087e,
- 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0040, 0x20d8, 0x2d60, 0x6034,
- 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0xa986, 0x0007, 0x0040, 0x2050,
- 0xa986, 0x000e, 0x0040, 0x2050, 0xa986, 0x000f, 0x00c0, 0x2054,
- 0x605c, 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x2062,
- 0x0050, 0x205c, 0x0078, 0x20d8, 0x6004, 0xa065, 0x0040, 0x20d8,
- 0x0078, 0x203f, 0x2804, 0xa005, 0x0040, 0x2080, 0xac68, 0xd99c,
- 0x00c0, 0x2070, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x2074,
- 0x6810, 0xa422, 0x6814, 0xa31b, 0x0048, 0x209f, 0x2300, 0xa405,
- 0x0040, 0x2086, 0x8a51, 0x0040, 0x20d8, 0x8840, 0x0078, 0x2062,
- 0x6004, 0xa065, 0x0040, 0x20d8, 0x0078, 0x203f, 0x8a51, 0x0040,
- 0x20d8, 0x8840, 0x2804, 0xa005, 0x00c0, 0x2099, 0x6004, 0xa065,
- 0x0040, 0x20d8, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0x2804,
- 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x20cc, 0x8422,
- 0x8420, 0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72,
- 0x0d7f, 0xd99c, 0x00c0, 0x20ba, 0x6908, 0x2400, 0xa122, 0x690c,
- 0x2300, 0xa11b, 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319,
- 0x0078, 0x20c6, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
- 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
- 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
- 0x2a00, 0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x20dd,
- 0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005,
- 0x2004, 0xa084, 0x0007, 0x0079, 0x20e5, 0x20ed, 0x20ee, 0x20f1,
- 0x20f4, 0x20f9, 0x20fc, 0x2101, 0x2106, 0x007c, 0x1078, 0x1e5d,
- 0x007c, 0x1078, 0x18e2, 0x007c, 0x1078, 0x18e2, 0x1078, 0x1e5d,
- 0x007c, 0x1078, 0x14b0, 0x007c, 0x1078, 0x1e5d, 0x1078, 0x14b0,
- 0x007c, 0x1078, 0x18e2, 0x1078, 0x14b0, 0x007c, 0x1078, 0x18e2,
- 0x1078, 0x1e5d, 0x1078, 0x14b0, 0x007c, 0x127e, 0x2091, 0x2300,
- 0x2079, 0x0200, 0x2071, 0xa880, 0x2069, 0xa300, 0x2009, 0x0004,
- 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5, 0x781b, 0x0002, 0x20e1,
- 0x8700, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084,
- 0x0007, 0x0079, 0x212b, 0x214f, 0x2133, 0x2137, 0x213b, 0x2141,
- 0x2145, 0x2149, 0x214d, 0x1078, 0x5372, 0x0078, 0x214f, 0x1078,
- 0x53b3, 0x0078, 0x214f, 0x1078, 0x5372, 0x1078, 0x53b3, 0x0078,
- 0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x0078,
- 0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x127f,
- 0x007c, 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040,
- 0x215d, 0x20e1, 0x9040, 0x0078, 0x2186, 0xa184, 0x0030, 0x0040,
- 0x216e, 0x6a00, 0xa286, 0x0003, 0x00c0, 0x2168, 0x0078, 0x216a,
- 0x1078, 0x4171, 0x20e1, 0x9010, 0x0078, 0x2186, 0xa184, 0x00c0,
- 0x0040, 0x2180, 0x0e7e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa5e1,
- 0x1078, 0x1ac6, 0x057f, 0x047f, 0x037f, 0x0e7f, 0x0078, 0x2186,
- 0xa184, 0x0300, 0x0040, 0x2186, 0x20e1, 0x9020, 0x7932, 0x027f,
- 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0xa300,
- 0x7128, 0x2001, 0xa58f, 0x2102, 0x2001, 0xa597, 0x2102, 0xa182,
- 0x0211, 0x00c8, 0x219f, 0x2009, 0x0008, 0x0078, 0x21c9, 0xa182,
- 0x0259, 0x00c8, 0x21a7, 0x2009, 0x0007, 0x0078, 0x21c9, 0xa182,
- 0x02c1, 0x00c8, 0x21af, 0x2009, 0x0006, 0x0078, 0x21c9, 0xa182,
- 0x0349, 0x00c8, 0x21b7, 0x2009, 0x0005, 0x0078, 0x21c9, 0xa182,
- 0x0421, 0x00c8, 0x21bf, 0x2009, 0x0004, 0x0078, 0x21c9, 0xa182,
- 0x0581, 0x00c8, 0x21c7, 0x2009, 0x0003, 0x0078, 0x21c9, 0x2009,
- 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5,
- 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061,
- 0x0100, 0x2071, 0xa300, 0x6024, 0x6026, 0x6053, 0x0030, 0x6033,
- 0x00ef, 0x60e7, 0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b,
- 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007,
- 0x0eaf, 0x600f, 0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001,
- 0xa32f, 0x2003, 0x0000, 0x2001, 0xa32e, 0x2003, 0x0001, 0x007c,
- 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184,
- 0x002c, 0x00c0, 0x220f, 0xa184, 0x0007, 0x0079, 0x2215, 0xa195,
- 0x0004, 0xa284, 0x0007, 0x0079, 0x2215, 0x2241, 0x221d, 0x2221,
- 0x2225, 0x222b, 0x222f, 0x2235, 0x223b, 0x1078, 0x5ad2, 0x0078,
- 0x2241, 0x1078, 0x5bc1, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078,
- 0x5ad2, 0x0078, 0x2241, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078,
- 0x5ad2, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078,
- 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078, 0x5ad2, 0x1078,
- 0x2246, 0x027f, 0x017f, 0x007f, 0x127f, 0x007c, 0x6124, 0xd1ac,
- 0x0040, 0x2342, 0x017e, 0x047e, 0x0c7e, 0x644c, 0xa486, 0xf0f0,
- 0x00c0, 0x2259, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043,
- 0x0010, 0x74c2, 0xa48c, 0xff00, 0x7034, 0xd084, 0x0040, 0x2271,
- 0xa186, 0xf800, 0x00c0, 0x2271, 0x7038, 0xd084, 0x00c0, 0x2271,
- 0xc085, 0x703a, 0x037e, 0x2418, 0x2011, 0x8016, 0x1078, 0x3579,
- 0x037f, 0xa196, 0xff00, 0x0040, 0x22b3, 0x6030, 0xa084, 0x00ff,
- 0x810f, 0xa116, 0x0040, 0x22b3, 0x7130, 0xd184, 0x00c0, 0x22b3,
- 0x2011, 0xa352, 0x2214, 0xd2ec, 0x0040, 0x228e, 0xc18d, 0x7132,
- 0x2011, 0xa352, 0x2214, 0xd2ac, 0x00c0, 0x22b3, 0x6240, 0xa294,
- 0x0010, 0x0040, 0x229a, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00,
- 0x0040, 0x22b3, 0x7030, 0xd08c, 0x0040, 0x2305, 0x7034, 0xd08c,
- 0x00c0, 0x22aa, 0x2001, 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305,
- 0xc1ad, 0x2102, 0x037e, 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579,
- 0x037f, 0x0078, 0x2305, 0x7034, 0xd08c, 0x00c0, 0x22bf, 0x2001,
- 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305, 0xc1ad, 0x2102, 0x037e,
- 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579, 0x037f, 0x7130, 0xc185,
- 0x7132, 0x2011, 0xa352, 0x220c, 0xd1a4, 0x0040, 0x22e9, 0x017e,
- 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x5a6d, 0x2019, 0x000e,
- 0x1078, 0x9e3b, 0xa484, 0x00ff, 0xa080, 0x293f, 0x200c, 0xa18c,
- 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x1078, 0x9ec0,
- 0x017f, 0xd1ac, 0x00c0, 0x22f6, 0x017e, 0x2009, 0x0000, 0x2019,
- 0x0004, 0x1078, 0x27e2, 0x017f, 0x0078, 0x2305, 0x157e, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x1078, 0x4501, 0x00c0, 0x2301, 0x1078,
- 0x4235, 0x8108, 0x00f0, 0x22fb, 0x157f, 0x0c7f, 0x047f, 0x0f7e,
- 0x2079, 0xa5be, 0x783c, 0xa086, 0x0000, 0x0040, 0x2317, 0x6027,
- 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f,
- 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011, 0x0002, 0x1078, 0x6efc,
- 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e, 0x2019, 0x0000, 0x1078,
- 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, 0xa300, 0x2014,
- 0xa296, 0x0004, 0x00c0, 0x233a, 0xd19c, 0x00c0, 0x233a, 0x6228,
- 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa321, 0x2003, 0x0000,
- 0x6027, 0x0020, 0xd194, 0x0040, 0x2426, 0x0f7e, 0x2079, 0xa5be,
- 0x783c, 0xa086, 0x0001, 0x00c0, 0x2366, 0x017e, 0x6027, 0x0004,
- 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000,
- 0x2079, 0xa5ab, 0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x6109,
- 0x1078, 0x61d3, 0x017f, 0x0f7f, 0x0078, 0x2426, 0x0f7f, 0x017e,
- 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x2371, 0x017e, 0x1078, 0x728a,
- 0x017f, 0x6220, 0xd2b4, 0x0040, 0x23dc, 0x1078, 0x595a, 0x1078,
- 0x6c41, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa5b4, 0x2304, 0xa07d,
- 0x0040, 0x23b2, 0x7804, 0xa086, 0x0032, 0x00c0, 0x23b2, 0x0d7e,
- 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
- 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x00c0,
- 0x2396, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e,
- 0x628a, 0x1078, 0x6010, 0x1078, 0x6109, 0x7810, 0x2070, 0x7037,
- 0x0103, 0x2f60, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0d7f, 0x0f7f,
- 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084,
- 0x4000, 0x0040, 0x23bf, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f,
- 0x0c7e, 0x2061, 0xa5ab, 0x6028, 0xa09a, 0x00c8, 0x00c8, 0x23cf,
- 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6c33, 0x0078, 0x2425, 0x2019,
- 0xa5b4, 0x2304, 0xa065, 0x0040, 0x23d9, 0x2009, 0x0027, 0x1078,
- 0x756c, 0x0c7f, 0x0078, 0x2425, 0xd2bc, 0x0040, 0x2425, 0x1078,
- 0x5967, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140,
- 0x6804, 0xa084, 0x4000, 0x0040, 0x23f1, 0x6803, 0x1000, 0x6803,
- 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa5ab, 0x6044, 0xa09a, 0x00c8,
- 0x00c8, 0x2414, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040,
- 0x2425, 0x2009, 0x07d0, 0x1078, 0x595f, 0xa080, 0x0007, 0x2004,
- 0xa086, 0x0006, 0x00c0, 0x2410, 0x6017, 0x0012, 0x0078, 0x2425,
- 0x6017, 0x0016, 0x0078, 0x2425, 0x037e, 0x2019, 0x0001, 0x1078,
- 0x6e6c, 0x037f, 0x2019, 0xa5ba, 0x2304, 0xa065, 0x0040, 0x2424,
- 0x2009, 0x004f, 0x1078, 0x756c, 0x0c7f, 0x017f, 0xd19c, 0x0040,
- 0x247c, 0x7034, 0xd0ac, 0x00c0, 0x2457, 0x017e, 0x157e, 0x6027,
- 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, 0x2435, 0x602f,
- 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0320, 0x00e0,
- 0x243f, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, 0x244e, 0x157f,
- 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x247c, 0x1078, 0x250d,
- 0x00f0, 0x243f, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x017e,
- 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011,
- 0x0002, 0x1078, 0x6efc, 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e,
- 0x2019, 0x0000, 0x1078, 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x1078,
- 0xa22a, 0x1078, 0xa248, 0x2001, 0xa300, 0x2003, 0x0004, 0x6027,
- 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c,
- 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000,
- 0x2071, 0xa300, 0x71b8, 0x70ba, 0xa116, 0x0040, 0x24ae, 0x81ff,
- 0x0040, 0x2498, 0x2011, 0x8011, 0x1078, 0x3579, 0x0078, 0x24ae,
- 0x2011, 0x8012, 0x1078, 0x3579, 0x2001, 0xa371, 0x2004, 0xd0fc,
- 0x00c0, 0x24ae, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028,
- 0x2009, 0x0000, 0x1078, 0x27e2, 0x0c7f, 0x037f, 0x127f, 0x0f7f,
- 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e,
- 0x027e, 0x2061, 0x0100, 0xa190, 0x24d1, 0x2204, 0x60f2, 0x2011,
- 0x24de, 0x6000, 0xa082, 0x0003, 0x00c8, 0x24ca, 0x2001, 0x00ff,
- 0x0078, 0x24cb, 0x2204, 0x60ee, 0x027f, 0x007f, 0x0f7f, 0x0c7f,
- 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0,
- 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8,
- 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094,
- 0xff00, 0x00c0, 0x24ee, 0x81ff, 0x0040, 0x24f2, 0x1078, 0x5623,
- 0x0078, 0x24f9, 0xa080, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f,
- 0xa006, 0x007c, 0xa080, 0x293f, 0x200c, 0xa18c, 0x00ff, 0x007c,
- 0x0c7e, 0x2061, 0xa300, 0x6030, 0x0040, 0x2509, 0xc09d, 0x0078,
- 0x250a, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, 0x157e, 0x0f7e,
- 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x00c0, 0x251a,
- 0x00f0, 0x2514, 0x0f7f, 0x157f, 0x007f, 0x007c, 0x0c7e, 0x007e,
- 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, 0x60e4, 0x007e,
- 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, 0x60ec, 0x007e,
- 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, 0x60e0, 0x007e,
- 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, 0x0005, 0x0005,
- 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, 0x007f, 0x602a,
- 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, 0x007f, 0x60f2,
- 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, 0x007f, 0x604a,
- 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x257d, 0x2581, 0x2585,
- 0x258b, 0x2591, 0x2597, 0x259d, 0x25a5, 0x25ad, 0x25b3, 0x25b9,
- 0x25c1, 0x25c9, 0x25d1, 0x25d9, 0x25e3, 0x25ed, 0x25ed, 0x25ed,
- 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed,
- 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x107e, 0x007e, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2200, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e,
- 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x20de, 0x1078,
- 0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078,
- 0x20de, 0x1078, 0x2123, 0x0078, 0x2606, 0x0005, 0x0078, 0x25ed,
- 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x25f6, 0x2606, 0x2583,
- 0x2587, 0x258d, 0x2593, 0x2599, 0x259f, 0x25a7, 0x25af, 0x25b5,
- 0x25bb, 0x25c3, 0x25cb, 0x25d3, 0x25db, 0x25e5, 0x0008, 0x25f0,
- 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, 0x027e, 0x047e,
- 0x2021, 0x0000, 0x1078, 0x4897, 0x00c0, 0x2705, 0x70c8, 0xd09c,
- 0x0040, 0x2624, 0xd084, 0x00c0, 0x2624, 0xd0bc, 0x00c0, 0x2705,
- 0x1078, 0x2709, 0x0078, 0x2705, 0xd094, 0x0040, 0x262b, 0x7093,
- 0xffff, 0x0078, 0x2705, 0x2001, 0x010c, 0x203c, 0x7280, 0xd284,
- 0x0040, 0x2694, 0xd28c, 0x00c0, 0x2694, 0x037e, 0x7390, 0xa38e,
- 0xffff, 0x0040, 0x263e, 0x83ff, 0x00c0, 0x2640, 0x2019, 0x0001,
- 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x264d,
- 0xa084, 0xff00, 0x8007, 0x0078, 0x264f, 0xa084, 0x00ff, 0xa70e,
- 0x0040, 0x2689, 0xa08e, 0x0000, 0x0040, 0x2689, 0xa08e, 0x00ff,
- 0x00c0, 0x2666, 0x7230, 0xd284, 0x00c0, 0x268f, 0x7280, 0xc28d,
- 0x7282, 0x7093, 0xffff, 0x037f, 0x0078, 0x2694, 0x2009, 0x0000,
- 0x1078, 0x24e3, 0x1078, 0x4499, 0x00c0, 0x268c, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2683, 0x7030, 0xd08c, 0x0040,
- 0x267d, 0x6000, 0xd0bc, 0x0040, 0x2683, 0x1078, 0x271f, 0x0040,
- 0x268c, 0x0078, 0x2689, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040,
- 0x268c, 0x8318, 0x0078, 0x2640, 0x7392, 0x0078, 0x2691, 0x7093,
- 0xffff, 0x037f, 0x0078, 0x2705, 0xa780, 0x293f, 0x203c, 0xa7bc,
- 0xff00, 0x873f, 0x2041, 0x007e, 0x7090, 0xa096, 0xffff, 0x00c0,
- 0x26a6, 0x2009, 0x0000, 0x28a8, 0x0078, 0x26b2, 0xa812, 0x0048,
- 0x26ae, 0x2008, 0xa802, 0x20a8, 0x0078, 0x26b2, 0x7093, 0xffff,
- 0x0078, 0x2705, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, 0x26f9,
- 0xc484, 0x1078, 0x4501, 0x0040, 0x26c3, 0x1078, 0x4499, 0x00c0,
- 0x2702, 0x0078, 0x26c4, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x00c0, 0x26d3, 0x7030, 0xd08c, 0x0040, 0x26f1, 0x6000,
- 0xd0bc, 0x00c0, 0x26f1, 0x7280, 0xd28c, 0x0040, 0x26e9, 0x6004,
- 0xa084, 0x00ff, 0xa082, 0x0006, 0x0048, 0x26f9, 0xd484, 0x00c0,
- 0x26e5, 0x1078, 0x44bc, 0x0078, 0x26e7, 0x1078, 0x2921, 0x0078,
- 0x26f9, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040, 0x2702, 0x0078,
- 0x26f9, 0x1078, 0x28ec, 0x0040, 0x26f9, 0x1078, 0x271f, 0x0040,
- 0x2702, 0x017f, 0x8108, 0x157f, 0x00f0, 0x26b2, 0x7093, 0xffff,
- 0x0078, 0x2705, 0x017f, 0x157f, 0x7192, 0x047f, 0x027f, 0x0c7f,
- 0x007c, 0x0c7e, 0x017e, 0x7093, 0x0000, 0x2009, 0x007e, 0x1078,
- 0x4499, 0x00c0, 0x271c, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040,
- 0x271c, 0x70c8, 0xc0bd, 0x70ca, 0x017f, 0x0c7f, 0x007c, 0x017e,
- 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084,
- 0x00ff, 0x6842, 0x1078, 0x74d7, 0x0040, 0x2747, 0x2d00, 0x601a,
- 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0000,
- 0x1078, 0x443f, 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e,
- 0x127f, 0x2009, 0x0004, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f,
- 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
- 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078,
- 0x74d7, 0x0040, 0x2785, 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802,
- 0x68a0, 0xa086, 0x007e, 0x0040, 0x276e, 0x6804, 0xa084, 0x00ff,
- 0xa086, 0x0006, 0x00c0, 0x276e, 0x1078, 0x2813, 0x601f, 0x0001,
- 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f,
- 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e, 0x127f, 0x2009,
- 0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f,
- 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078, 0x4499,
- 0x00c0, 0x2798, 0x1078, 0x279b, 0x0040, 0x2798, 0x70cf, 0xffff,
- 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68,
- 0x1078, 0x74d7, 0x0040, 0x27bd, 0x2d00, 0x601a, 0x601f, 0x0001,
- 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f,
- 0x127e, 0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x127f, 0x2009,
- 0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f,
- 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009,
- 0x007f, 0x1078, 0x4499, 0x00c0, 0x27de, 0x2c68, 0x1078, 0x74d7,
- 0x0040, 0x27de, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
- 0x2009, 0x0022, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0d7f,
- 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078,
- 0x5d60, 0x1078, 0x5d02, 0x1078, 0x7ddf, 0x2130, 0x81ff, 0x0040,
- 0x27f7, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0078, 0x27fb, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x2804,
- 0x1078, 0x471b, 0x1078, 0x4235, 0x017f, 0x8108, 0x00f0, 0x27fb,
- 0x86ff, 0x00c0, 0x280d, 0x1078, 0x119b, 0x027f, 0x037f, 0x067f,
- 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e,
- 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53,
- 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38,
- 0x077f, 0x017f, 0x2e60, 0x1078, 0x471b, 0x6210, 0x6314, 0x1078,
- 0x4235, 0x6212, 0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
- 0x007c, 0x0e7e, 0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc,
- 0x00c0, 0x284d, 0x2071, 0xa300, 0x708c, 0xa005, 0x0040, 0x284a,
- 0x8001, 0x708e, 0x007f, 0x0e7f, 0x007c, 0x2071, 0xa300, 0x70d0,
- 0xa005, 0x0040, 0x284a, 0x8001, 0x70d2, 0x0078, 0x284a, 0x6000,
- 0xc08c, 0x6002, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e,
- 0x017e, 0x157e, 0x2178, 0x81ff, 0x00c0, 0x286a, 0x20a9, 0x0001,
- 0x0078, 0x2885, 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x2881,
- 0xd0a4, 0x0040, 0x2881, 0x047e, 0x6018, 0xa080, 0x0028, 0x2024,
- 0xa4a4, 0x00ff, 0x8427, 0xa006, 0x2009, 0x002d, 0x1078, 0x9ec0,
- 0x047f, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e,
- 0x0040, 0x28c9, 0xa28e, 0x007f, 0x0040, 0x28c9, 0xa28e, 0x0080,
- 0x0040, 0x28c9, 0xa288, 0xa434, 0x210c, 0x81ff, 0x0040, 0x28c9,
- 0x8fff, 0x1040, 0x28d5, 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078,
- 0x48a2, 0x0c7f, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294,
- 0x00ff, 0xa286, 0x0006, 0x00c0, 0x28b9, 0x6007, 0x0404, 0x0078,
- 0x28be, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f,
- 0x017e, 0x2c08, 0x1078, 0x9c38, 0x017f, 0x077f, 0x2160, 0x1078,
- 0x471b, 0x027f, 0x8210, 0x00f0, 0x2885, 0x157f, 0x017f, 0x027f,
- 0x037f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e,
- 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x28e8, 0xd0a4, 0x0040,
- 0x28e8, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x1078, 0x9ec0,
- 0x017f, 0x027f, 0x047f, 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e,
- 0x7280, 0x82ff, 0x0040, 0x291a, 0xa290, 0xa352, 0x2214, 0xd2ac,
- 0x00c0, 0x291a, 0x2100, 0x1078, 0x24fa, 0x81ff, 0x0040, 0x291c,
- 0x2019, 0x0001, 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xd384, 0x0040,
- 0x290e, 0xa084, 0xff00, 0x8007, 0x0078, 0x2910, 0xa084, 0x00ff,
- 0xa116, 0x0040, 0x291c, 0xa096, 0x00ff, 0x0040, 0x291a, 0x8318,
- 0x0078, 0x2902, 0xa085, 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f,
- 0x007c, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0xa180, 0xa434,
- 0x2004, 0xa065, 0x0040, 0x293b, 0x017e, 0x0c7e, 0x1078, 0x8ec0,
- 0x017f, 0x1040, 0x1328, 0x611a, 0x1078, 0x2813, 0x1078, 0x753d,
- 0x017f, 0x1078, 0x44bc, 0x127f, 0x0c7f, 0x017f, 0x007c, 0x7eef,
- 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9,
- 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd,
- 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3,
- 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2,
- 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7,
- 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098,
- 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080,
- 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072,
- 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067,
- 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055,
- 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b,
- 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a,
- 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e,
- 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025,
- 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010,
- 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800,
- 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000,
- 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000,
- 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000,
- 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000,
- 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000,
- 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000,
- 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000,
- 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000,
- 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500,
- 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071,
- 0xa381, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e,
- 0x7033, 0xa391, 0x7037, 0xa391, 0x7007, 0x0001, 0x2061, 0xa3d1,
- 0x6003, 0x0002, 0x007c, 0x0090, 0x2a66, 0x0068, 0x2a66, 0x2071,
- 0xa381, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2a66, 0x2a60, 0x7820,
- 0xa08e, 0x0069, 0x00c0, 0x2b56, 0x0079, 0x2aea, 0x007c, 0x2071,
- 0xa381, 0x7004, 0x0079, 0x2a6c, 0x2a70, 0x2a71, 0x2a7b, 0x2a8d,
- 0x007c, 0x0090, 0x2a7a, 0x0068, 0x2a7a, 0x2b78, 0x7818, 0xd084,
- 0x0040, 0x2a99, 0x007c, 0x2b78, 0x2061, 0xa3d1, 0x6008, 0xa08e,
- 0x0100, 0x0040, 0x2a88, 0xa086, 0x0200, 0x0040, 0x2b4e, 0x007c,
- 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834,
- 0xa086, 0x0103, 0x0040, 0x2a95, 0x007c, 0x2a60, 0x2b78, 0x7018,
- 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2aa2, 0x61b8,
- 0x0079, 0x2aaa, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2b4a, 0x61b8,
- 0x0079, 0x2aea, 0x2b2c, 0x2b5e, 0x2b66, 0x2b6a, 0x2b72, 0x2b78,
- 0x2b7c, 0x2b88, 0x2b8c, 0x2b96, 0x2b9a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b9e, 0x2b4a, 0x2bae, 0x2bc5, 0x2bdc, 0x2c58, 0x2c5d, 0x2c8a,
- 0x2ce4, 0x2cf5, 0x2d13, 0x2d54, 0x2d5e, 0x2d6b, 0x2d7e, 0x2d9d,
- 0x2da6, 0x2de3, 0x2de9, 0x2b4a, 0x2e05, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2e0c, 0x2e16, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2e1e, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2e30, 0x2e47, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2e59, 0x2eb0, 0x2f0e, 0x2f1f, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x38f1, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2b96, 0x2b9a, 0x2f36, 0x2b4a, 0x2f43, 0x397d,
- 0x39da, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2f90, 0x30c5, 0x30e1, 0x30ed, 0x3150, 0x31a9,
- 0x31b4, 0x31f3, 0x3202, 0x3211, 0x3214, 0x2f47, 0x3238, 0x3284,
- 0x3291, 0x33a2, 0x34cd, 0x34f7, 0x3604, 0x3614, 0x3621, 0x365b,
- 0x372a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x3792, 0x37ae, 0x3828,
- 0x38e2, 0x713c, 0x0078, 0x2b2c, 0x2021, 0x4000, 0x1078, 0x3553,
- 0x127e, 0x2091, 0x8000, 0x0068, 0x2b39, 0x7818, 0xd084, 0x0040,
- 0x2b3c, 0x127f, 0x0078, 0x2b30, 0x7c22, 0x7926, 0x7a2a, 0x7b2e,
- 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000,
- 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2b2e, 0x2021, 0x4002,
- 0x0078, 0x2b2e, 0x2021, 0x4003, 0x0078, 0x2b2e, 0x2021, 0x4005,
- 0x0078, 0x2b2e, 0x2021, 0x4006, 0x0078, 0x2b2e, 0xa02e, 0x2520,
- 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3562, 0x7823, 0x0004,
- 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
- 0x0078, 0x3566, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2b2c,
- 0x7924, 0x2114, 0x0078, 0x2b2c, 0x2099, 0x0009, 0x20a1, 0x0009,
- 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, 0x2b2c,
- 0x7824, 0x2060, 0x0078, 0x2ba0, 0x2009, 0x0001, 0x2011, 0x0013,
- 0x2019, 0x0010, 0x783b, 0x0017, 0x0078, 0x2b2c, 0x7d38, 0x7c3c,
- 0x0078, 0x2b60, 0x7d38, 0x7c3c, 0x0078, 0x2b6c, 0x2061, 0x1000,
- 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, 0x2ba2,
- 0x2010, 0xa005, 0x0040, 0x2b2c, 0x0078, 0x2b52, 0x2069, 0xa351,
- 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a,
- 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a,
- 0x685e, 0x1078, 0x4dbd, 0x0078, 0x2b2c, 0x2069, 0xa351, 0x7824,
- 0x7934, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a, 0x684e,
- 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e,
- 0x1078, 0x494d, 0x0078, 0x2b2c, 0xa02e, 0x2520, 0x81ff, 0x00c0,
- 0x2b56, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xa388,
- 0x41a1, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0020, 0x1078,
- 0x3562, 0x701b, 0x2bf4, 0x007c, 0x6834, 0x2008, 0xa084, 0x00ff,
- 0xa096, 0x0011, 0x0040, 0x2c00, 0xa096, 0x0019, 0x00c0, 0x2b56,
- 0x810f, 0xa18c, 0x00ff, 0x0040, 0x2b56, 0x710e, 0x700c, 0x8001,
- 0x0040, 0x2c31, 0x700e, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009,
- 0x0020, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290,
- 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078,
- 0x3562, 0x701b, 0x2c24, 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096,
- 0x0002, 0x0040, 0x2c2f, 0xa096, 0x000a, 0x00c0, 0x2b56, 0x0078,
- 0x2c06, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x436e,
- 0x00c0, 0x2c3f, 0x7007, 0x0003, 0x701b, 0x2c41, 0x007c, 0x1078,
- 0x4a60, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xa388,
- 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, 0x0078, 0x3566,
- 0x61a0, 0x7824, 0x60a2, 0x0078, 0x2b2c, 0x2091, 0x8000, 0x7823,
- 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
- 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
- 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
- 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
- 0x2071, 0x0010, 0x20c1, 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427,
- 0x0078, 0x0423, 0x81ff, 0x00c0, 0x2b56, 0x7924, 0x810f, 0xa18c,
- 0x00ff, 0x1078, 0x4501, 0x00c0, 0x2b5a, 0x7e38, 0xa684, 0x3fff,
- 0xa082, 0x4000, 0x0048, 0x2c9e, 0x0078, 0x2b5a, 0x7c28, 0x7d2c,
- 0x1078, 0x46d6, 0xd28c, 0x00c0, 0x2ca9, 0x1078, 0x466a, 0x0078,
- 0x2cab, 0x1078, 0x46a4, 0x00c0, 0x2cd5, 0x2061, 0xaa00, 0x127e,
- 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0040, 0x2cc3, 0x6010,
- 0xa06d, 0x0040, 0x2cc3, 0x683c, 0xa406, 0x00c0, 0x2cc3, 0x6840,
- 0xa506, 0x0040, 0x2cce, 0x127f, 0xace0, 0x0010, 0x2001, 0xa315,
- 0x2004, 0xac02, 0x00c8, 0x2b56, 0x0078, 0x2caf, 0x1078, 0x8758,
- 0x127f, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0xa00e, 0x2001, 0x0005,
- 0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cc0, 0x1078,
- 0x4982, 0x127f, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078,
- 0x3530, 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078,
- 0x46e4, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56,
- 0x1078, 0x3542, 0x0040, 0x2b5a, 0x1078, 0x475f, 0x0040, 0x2b56,
- 0x2019, 0x0005, 0x1078, 0x4705, 0x0040, 0x2b56, 0x7828, 0xa08a,
- 0x1000, 0x00c8, 0x2b5a, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078,
- 0x58e1, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040,
- 0x2d1d, 0x2009, 0x0001, 0x0078, 0x2d4e, 0x2029, 0x00ff, 0x644c,
- 0x2400, 0xa506, 0x0040, 0x2d48, 0x2508, 0x1078, 0x4501, 0x00c0,
- 0x2d48, 0x1078, 0x475f, 0x00c0, 0x2d33, 0x2009, 0x0002, 0x62a8,
- 0x2518, 0x0078, 0x2d4e, 0x2019, 0x0004, 0x1078, 0x4705, 0x00c0,
- 0x2d3d, 0x2009, 0x0006, 0x0078, 0x2d4e, 0x7824, 0xa08a, 0x1000,
- 0x00c8, 0x2d51, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x58e1,
- 0x8529, 0x00c8, 0x2d20, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078,
- 0x2b56, 0x127f, 0x0078, 0x2b5a, 0x1078, 0x3530, 0x0040, 0x2b5a,
- 0x1078, 0x461b, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0,
- 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a, 0x1078, 0x460a, 0x1078,
- 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530,
- 0x0040, 0x2b5a, 0x1078, 0x46a7, 0x0040, 0x2b56, 0x1078, 0x43c1,
- 0x1078, 0x4663, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530,
- 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x62a0, 0x2019,
- 0x0005, 0x0c7e, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e,
- 0x2039, 0x0000, 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38,
- 0x077f, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530, 0x0040,
- 0x2b5a, 0x1078, 0x46d6, 0x2208, 0x0078, 0x2b2c, 0x157e, 0x0d7e,
- 0x0e7e, 0x2069, 0xa413, 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2db2,
- 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9,
- 0x00ff, 0x2069, 0xa434, 0x2d04, 0xa075, 0x0040, 0x2dc7, 0x704c,
- 0x1078, 0x2dd1, 0xa210, 0x7080, 0x1078, 0x2dd1, 0xa318, 0x8d68,
- 0x00f0, 0x2dbb, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078,
- 0x2b2c, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x2de0, 0x2001, 0x0000,
- 0x8000, 0x2f0c, 0x81ff, 0x0040, 0x2de0, 0x2178, 0x0078, 0x2dd8,
- 0x017f, 0x0f7f, 0x007c, 0x2069, 0xa413, 0x6910, 0x62a4, 0x0078,
- 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x614c, 0xa190, 0x293f, 0x2214,
- 0xa294, 0x00ff, 0x606c, 0xa084, 0xff00, 0xa215, 0x6368, 0x67c8,
- 0xd79c, 0x0040, 0x2dff, 0x2031, 0x0001, 0x0078, 0x2e01, 0x2031,
- 0x0000, 0x7e3a, 0x7f3e, 0x0078, 0x2b2c, 0x613c, 0x6240, 0x2019,
- 0xa5a0, 0x231c, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x6134,
- 0xa006, 0x2010, 0x2018, 0x127f, 0x0078, 0x2b2c, 0x1078, 0x3542,
- 0x0040, 0x2b5a, 0x6244, 0x6338, 0x0078, 0x2b2c, 0x613c, 0x6240,
- 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xa351, 0x831f, 0xa305,
- 0x6816, 0x782c, 0x2069, 0xa5a0, 0x2d1c, 0x206a, 0x0078, 0x2b2c,
- 0x017e, 0x127e, 0x2091, 0x8000, 0x7824, 0x6036, 0xd094, 0x0040,
- 0x2e43, 0x7828, 0xa085, 0x0001, 0x2009, 0xa5a9, 0x200a, 0x2001,
- 0xffff, 0x1078, 0x5975, 0x127f, 0x017f, 0x0078, 0x2b2c, 0x1078,
- 0x3542, 0x0040, 0x2b5a, 0x7828, 0xa00d, 0x0040, 0x2b5a, 0x782c,
- 0xa005, 0x0040, 0x2b5a, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078,
- 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56,
- 0x0c7e, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196,
- 0x00ff, 0x00c0, 0x2e70, 0x6030, 0xa085, 0xff00, 0x0078, 0x2e7f,
- 0xa182, 0x007f, 0x00c8, 0x2ea9, 0xa188, 0x293f, 0x210c, 0xa18c,
- 0x00ff, 0x6030, 0xa116, 0x0040, 0x2ea9, 0x810f, 0xa105, 0x127e,
- 0x2091, 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2ea5,
- 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040,
- 0x2eac, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
- 0xc0fd, 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032,
- 0x1078, 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078,
- 0x2b56, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2ea5,
- 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0c7e,
- 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff,
- 0x00c0, 0x2ec7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2ed6, 0xa182,
- 0x007f, 0x00c8, 0x2f00, 0xa188, 0x293f, 0x210c, 0xa18c, 0x00ff,
- 0x6030, 0xa116, 0x0040, 0x2f00, 0x810f, 0xa105, 0x127e, 0x2091,
- 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2efc, 0x601a,
- 0x600b, 0xbc05, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040, 0x2f03,
- 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078,
- 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2b56,
- 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2efc, 0x6830,
- 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x2061, 0xa62d,
- 0x127e, 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2f1c, 0x6104,
- 0x6208, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x81ff,
- 0x00c0, 0x2b56, 0x127e, 0x2091, 0x8000, 0x6244, 0x6060, 0xa202,
- 0x0048, 0x2f33, 0xa085, 0x0001, 0x1078, 0x2500, 0x1078, 0x3bf5,
- 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x127e, 0x2091,
- 0x8000, 0x20a9, 0x0011, 0x2001, 0xa340, 0x20a0, 0xa006, 0x40a4,
- 0x127f, 0x0078, 0x2b2c, 0x7d38, 0x7c3c, 0x0078, 0x2bde, 0x7824,
- 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2b56, 0x624c, 0xa084,
- 0xff00, 0x8007, 0xa206, 0x00c0, 0x2f5f, 0x2001, 0xa340, 0x2009,
- 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566, 0x81ff,
- 0x00c0, 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518,
- 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
- 0x1078, 0x8b85, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x2f81,
- 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0xad80, 0x000e,
- 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566,
- 0x1078, 0x3518, 0x0040, 0x2b56, 0x1078, 0x421a, 0x2009, 0x001c,
- 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x2fa1,
- 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2b5a, 0x6804,
- 0xd0ac, 0x0040, 0x2fae, 0xd0a4, 0x0040, 0x2b5a, 0xd094, 0x0040,
- 0x2fb9, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106,
- 0x0c7f, 0xd08c, 0x0040, 0x2fc4, 0x0c7e, 0x2061, 0x0100, 0x6104,
- 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a,
- 0x0002, 0x0048, 0x2fd9, 0xd084, 0x0040, 0x2fd9, 0x6a28, 0xa28a,
- 0x007f, 0x00c8, 0x2b5a, 0xa288, 0x293f, 0x210c, 0xa18c, 0x00ff,
- 0x6152, 0xd0dc, 0x0040, 0x2fe2, 0x6828, 0xa08a, 0x007f, 0x00c8,
- 0x2b5a, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2b5a, 0xa08a,
- 0x0841, 0x00c8, 0x2b5a, 0xa084, 0x0007, 0x00c0, 0x2b5a, 0x680c,
- 0xa005, 0x0040, 0x2b5a, 0x6810, 0xa005, 0x0040, 0x2b5a, 0x6848,
- 0x6940, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x684c,
- 0x6944, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x6804,
- 0xd0fc, 0x0040, 0x3038, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009,
- 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399,
- 0x0000, 0x1078, 0x3562, 0x701b, 0x301e, 0x007c, 0xade8, 0x000d,
- 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa36d, 0x2da0, 0x53a3, 0x7010,
- 0xa0e8, 0x000d, 0x2001, 0xa371, 0x200c, 0xd1e4, 0x0040, 0x3038,
- 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, 0x6006, 0x0c7f,
- 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa351, 0x2da0, 0x53a3, 0x6814,
- 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078,
- 0x4dbd, 0x1078, 0x48dd, 0x1078, 0x494d, 0x6000, 0xa086, 0x0000,
- 0x00c0, 0x30c3, 0x6808, 0x602a, 0x1078, 0x218b, 0x6818, 0x691c,
- 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a,
- 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x3070, 0x6830, 0x6934,
- 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0078, 0x3072,
- 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x1078, 0x59a8,
- 0x6904, 0xd1fc, 0x0040, 0x30a5, 0x0c7e, 0x2009, 0x0000, 0x20a9,
- 0x0001, 0x6b70, 0xd384, 0x0040, 0x30a2, 0x0078, 0x308c, 0x839d,
- 0x00c8, 0x30a2, 0x3508, 0x8109, 0x1078, 0x5364, 0x6878, 0x6016,
- 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff,
- 0x6006, 0x8108, 0x00c0, 0x30a0, 0x6003, 0x0003, 0x0078, 0x30a2,
- 0x6003, 0x0001, 0x00f0, 0x3087, 0x0c7f, 0x0c7e, 0x2061, 0x0100,
- 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, 0x3784, 0x0040,
- 0x30b3, 0x1078, 0x2500, 0x60bc, 0xa005, 0x0040, 0x30bf, 0x6003,
- 0x0001, 0x2091, 0x301d, 0x1078, 0x4171, 0x0078, 0x30c3, 0x6003,
- 0x0004, 0x2091, 0x301d, 0x0078, 0x2b2c, 0x6000, 0xa086, 0x0000,
- 0x0040, 0x2b56, 0x2069, 0xa351, 0x7830, 0x6842, 0x7834, 0x6846,
- 0x6804, 0xd0fc, 0x0040, 0x30d8, 0x2009, 0x0030, 0x0078, 0x30da,
- 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
- 0x3566, 0xa006, 0x1078, 0x2500, 0x81ff, 0x00c0, 0x2b56, 0x1078,
- 0x421a, 0x1078, 0x4171, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56,
- 0x6180, 0x81ff, 0x0040, 0x3107, 0x703f, 0x0000, 0x2001, 0xa9c0,
- 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e, 0x2091,
- 0x8000, 0x1078, 0x3566, 0x701b, 0x2b29, 0x127f, 0x007c, 0x703f,
- 0x0001, 0x0d7e, 0x2069, 0xa9c0, 0x20a9, 0x0040, 0x20a1, 0xa9c0,
- 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x293f, 0x210c, 0xa18c,
- 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x0040,
- 0x3139, 0x1078, 0x4501, 0x00c0, 0x3139, 0x6014, 0x821c, 0x0048,
- 0x3131, 0xa398, 0xa9c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0078,
- 0x3138, 0xa398, 0xa9c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a,
- 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x3140, 0x0078, 0x311d,
- 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9, 0x0040,
- 0x20a1, 0xa9c0, 0x2099, 0xa9c0, 0x1078, 0x41be, 0x0078, 0x30f6,
- 0x1078, 0x3542, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f,
- 0x00c0, 0x315e, 0x2009, 0x0002, 0x0078, 0x2b56, 0x2001, 0xa352,
- 0x2004, 0xd0b4, 0x0040, 0x3185, 0x6000, 0xd08c, 0x00c0, 0x3185,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3185, 0x6837,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x317c,
- 0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3181,
- 0x007c, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x20a9, 0x002b, 0x2c98,
- 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006,
- 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x41be, 0x20a9, 0x0004,
- 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x41be,
- 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
- 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a,
- 0x1078, 0x46ef, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x7828,
- 0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x1078, 0x3542, 0x0040, 0x2b5a,
- 0x1078, 0x475f, 0x0040, 0x2b56, 0x2019, 0x0004, 0x1078, 0x4705,
- 0x7924, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x0078, 0x2b2c, 0xa186,
- 0x00ff, 0x0040, 0x31d7, 0x1078, 0x31e7, 0x0078, 0x31e6, 0x2029,
- 0x007e, 0x2061, 0xa300, 0x644c, 0x2400, 0xa506, 0x0040, 0x31e3,
- 0x2508, 0x1078, 0x31e7, 0x8529, 0x00c8, 0x31dc, 0x007c, 0x1078,
- 0x4501, 0x00c0, 0x31f2, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108,
- 0x1078, 0x58e1, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530,
- 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46fa,
- 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040,
- 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46e4, 0x0078,
- 0x2b2c, 0x6100, 0x0078, 0x2b2c, 0x1078, 0x3542, 0x0040, 0x2b5a,
- 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0d7e,
- 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x3228, 0xace8, 0x0006,
- 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f,
- 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078, 0x2b2c,
- 0xa006, 0x1078, 0x2500, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
- 0x0040, 0x3245, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x421a, 0x7828,
- 0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x7924, 0xa18c, 0xff00, 0x810f,
- 0xa186, 0x00ff, 0x0040, 0x325b, 0xa182, 0x007f, 0x00c8, 0x2b5a,
- 0x2100, 0x1078, 0x24fa, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000,
- 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x0100,
- 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090,
- 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078, 0x596c,
- 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x127f,
- 0x0c7f, 0x027f, 0x0078, 0x2b2c, 0x7924, 0xa18c, 0xff00, 0x810f,
- 0x0c7e, 0x1078, 0x4499, 0x2c08, 0x0c7f, 0x00c0, 0x2b5a, 0x0078,
- 0x2b2c, 0x81ff, 0x0040, 0x3298, 0x2009, 0x0001, 0x0078, 0x2b56,
- 0x60c8, 0xd09c, 0x00c0, 0x32a0, 0x2009, 0x0005, 0x0078, 0x2b56,
- 0x1078, 0x3518, 0x00c0, 0x32a8, 0x2009, 0x0002, 0x0078, 0x2b56,
- 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b,
- 0x32b2, 0x007c, 0x2009, 0x0080, 0x1078, 0x4501, 0x00c0, 0x32bf,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x32c3, 0x2021,
- 0x400a, 0x0078, 0x2b2e, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08,
- 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040,
- 0x3336, 0xa0be, 0x0112, 0x0040, 0x3336, 0xa0be, 0x0113, 0x0040,
- 0x3336, 0xa0be, 0x0114, 0x0040, 0x3336, 0xa0be, 0x0117, 0x0040,
- 0x3336, 0xa0be, 0x011a, 0x0040, 0x3336, 0xa0be, 0x0121, 0x0040,
- 0x332c, 0xa0be, 0x0131, 0x0040, 0x332c, 0xa0be, 0x0171, 0x0040,
- 0x3336, 0xa0be, 0x0173, 0x0040, 0x3336, 0xa0be, 0x01a1, 0x00c0,
- 0x32fe, 0x6830, 0x8007, 0x6832, 0x0078, 0x333c, 0xa0be, 0x0212,
- 0x0040, 0x3332, 0xa0be, 0x0213, 0x0040, 0x3332, 0xa0be, 0x0214,
- 0x0040, 0x3324, 0xa0be, 0x0217, 0x0040, 0x331e, 0xa0be, 0x021a,
- 0x00c0, 0x3317, 0x6838, 0x8007, 0x683a, 0x0078, 0x3336, 0xa0be,
- 0x0300, 0x0040, 0x3336, 0x0d7f, 0x0078, 0x2b5a, 0xad80, 0x0010,
- 0x20a9, 0x0007, 0x1078, 0x337e, 0xad80, 0x000e, 0x20a9, 0x0001,
- 0x1078, 0x337e, 0x0078, 0x3336, 0xad80, 0x000c, 0x1078, 0x338c,
- 0x0078, 0x333c, 0xad80, 0x000e, 0x1078, 0x338c, 0xad80, 0x000c,
- 0x20a9, 0x0001, 0x1078, 0x337e, 0x0c7e, 0x1078, 0x3518, 0x0040,
- 0x336f, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, 0x0000,
- 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000,
- 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f,
- 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
- 0x6804, 0x2068, 0x1078, 0x8ba1, 0x00c0, 0x336a, 0x2009, 0x0003,
- 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3375, 0x007c, 0x0c7f,
- 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2b56, 0x6820, 0xa086, 0x8001,
- 0x00c0, 0x2b2c, 0x2009, 0x0004, 0x0078, 0x2b56, 0x017e, 0x2008,
- 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108,
- 0x00f0, 0x3380, 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008,
- 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a,
- 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f,
- 0x017f, 0x007c, 0x81ff, 0x0040, 0x33a9, 0x2009, 0x0001, 0x0078,
- 0x2b56, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080,
- 0x0048, 0x2b5a, 0xa182, 0x00ff, 0x00c8, 0x2b5a, 0x7a2c, 0x7b28,
- 0x6068, 0xa306, 0x00c0, 0x33c4, 0x606c, 0xa24e, 0x0040, 0x2b5a,
- 0xa9cc, 0xff00, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x346d, 0x2c68,
- 0x0c7f, 0x0040, 0x33fc, 0xa0c6, 0x4000, 0x00c0, 0x33e2, 0x0c7e,
- 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x47cb, 0x00c0, 0x33d9,
- 0xc185, 0x6000, 0xd0bc, 0x0040, 0x33de, 0xc18d, 0x007f, 0x0c7f,
- 0x0078, 0x33f9, 0xa0c6, 0x4007, 0x00c0, 0x33e9, 0x2408, 0x0078,
- 0x33f9, 0xa0c6, 0x4008, 0x00c0, 0x33f1, 0x2708, 0x2610, 0x0078,
- 0x33f9, 0xa0c6, 0x4009, 0x00c0, 0x33f7, 0x0078, 0x33f9, 0x2001,
- 0x4006, 0x2020, 0x0078, 0x2b2e, 0x2d00, 0x7022, 0x017e, 0x0b7e,
- 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x74d7, 0x0040, 0x3442, 0x2d00,
- 0x601a, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x2e58,
- 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2b70, 0x00c0,
- 0x3423, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x2009,
- 0x0002, 0x0078, 0x2b56, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078,
- 0x2813, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b,
- 0x2001, 0x0002, 0x1078, 0x443f, 0x2009, 0x0002, 0x1078, 0x756c,
- 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x00c0, 0x344c,
- 0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3451,
- 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, 0x00c0, 0x345f,
- 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, 0x2b56, 0x2009,
- 0x0000, 0x1078, 0x47cb, 0x00c0, 0x3466, 0xc185, 0x6000, 0xd0bc,
- 0x0040, 0x346b, 0xc18d, 0x0078, 0x2b2c, 0x0e7e, 0x0d7e, 0x2029,
- 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xa4b4, 0x2e04,
- 0xa005, 0x00c0, 0x3482, 0x2100, 0xa406, 0x00c0, 0x34b3, 0x2428,
- 0x0078, 0x34b3, 0x2068, 0x6f10, 0x2700, 0xa306, 0x00c0, 0x34a4,
- 0x6e14, 0x2600, 0xa206, 0x00c0, 0x34a4, 0x2400, 0xa106, 0x00c0,
- 0x34a0, 0x2d60, 0xd884, 0x0040, 0x34c8, 0x6004, 0xa084, 0x00ff,
- 0xa086, 0x0006, 0x00c0, 0x34c8, 0x2001, 0x4000, 0x0078, 0x34c9,
- 0x2001, 0x4007, 0x0078, 0x34c9, 0x2400, 0xa106, 0x00c0, 0x34b3,
- 0x6e14, 0x87ff, 0x00c0, 0x34af, 0x86ff, 0x0040, 0x347f, 0x2001,
- 0x4008, 0x0078, 0x34c9, 0x8420, 0x8e70, 0x00f0, 0x3477, 0x85ff,
- 0x00c0, 0x34c2, 0x2001, 0x4009, 0x0078, 0x34c9, 0x2001, 0x0001,
- 0x0078, 0x34c9, 0x1078, 0x4499, 0x00c0, 0x34be, 0x6312, 0x6216,
- 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x2b56,
- 0x1078, 0x3518, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x7824, 0xa005, 0x0040, 0x2b5a, 0xa096, 0x00ff, 0x0040,
- 0x34e5, 0xa092, 0x0004, 0x00c8, 0x2b5a, 0x2010, 0x2d18, 0x1078,
- 0x27c2, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x34f0, 0x007c,
- 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x7924,
- 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2b5a, 0xa182,
- 0x00ff, 0x00c8, 0x2b5a, 0x127e, 0x2091, 0x8000, 0x1078, 0x8a89,
- 0x00c0, 0x3515, 0xa190, 0xa434, 0x2204, 0xa065, 0x0040, 0x3515,
- 0x1078, 0x4235, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b56,
- 0x1078, 0x1381, 0x0040, 0x352f, 0xa006, 0x6802, 0x7010, 0xa005,
- 0x00c0, 0x3527, 0x2d00, 0x7012, 0x7016, 0x0078, 0x352d, 0x7014,
- 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x007c,
- 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501, 0x00c0, 0x353f,
- 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x3540, 0xa066,
- 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078, 0x4501,
- 0x00c0, 0x3550, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0048, 0x3551,
- 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040, 0x355e,
- 0x2168, 0x6904, 0x1078, 0x139a, 0x0078, 0x3555, 0x7112, 0x7116,
- 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x3568, 0x2031, 0x0000,
- 0x2061, 0xa3d1, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e,
- 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x2b2c,
- 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001,
- 0xa38f, 0x2004, 0xa005, 0x00c0, 0x3594, 0x0068, 0x3594, 0x7818,
- 0xd084, 0x00c0, 0x3594, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001,
- 0x2091, 0x4080, 0x0078, 0x35b9, 0x017e, 0x0c7e, 0x0e7e, 0x2071,
- 0xa381, 0x7138, 0xa182, 0x0008, 0x0048, 0x35a2, 0x7030, 0x2060,
- 0x0078, 0x35b3, 0x7030, 0xa0e0, 0x0008, 0xac82, 0xa3d1, 0x0048,
- 0x35ab, 0x2061, 0xa391, 0x2c00, 0x7032, 0x81ff, 0x00c0, 0x35b1,
- 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f, 0x0c7f,
- 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0xa381, 0x7038,
- 0xa005, 0x0040, 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x35f4,
- 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x35f3, 0x0c7e,
- 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a,
- 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005,
- 0x00c0, 0x35e9, 0x7033, 0xa391, 0x7037, 0xa391, 0x0c7f, 0x0078,
- 0x35f3, 0xac80, 0x0008, 0xa0fa, 0xa3d1, 0x0048, 0x35f1, 0x2001,
- 0xa391, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c, 0x027e,
- 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x3602, 0x2011, 0x8014,
- 0x1078, 0x3579, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x127e,
- 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x1078,
- 0x4171, 0x127f, 0x0078, 0x2b2c, 0x7824, 0x2008, 0xa18c, 0xfffd,
- 0x00c0, 0x361f, 0x61d4, 0xa10d, 0x61d6, 0x0078, 0x2b2c, 0x0078,
- 0x2b5a, 0x81ff, 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x00c0,
- 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x2b56, 0x1078,
- 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
- 0x00c0, 0x363e, 0x7828, 0xa005, 0x0040, 0x2b2c, 0x0c7e, 0x1078,
- 0x3518, 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6833, 0x0000,
- 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8c4d, 0x0040, 0x2b56, 0x7007,
- 0x0003, 0x701b, 0x3654, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040,
- 0x2b56, 0x0078, 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003,
- 0x00c0, 0x2b56, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078,
- 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023,
- 0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078,
- 0x4501, 0x00c0, 0x36d8, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006,
- 0x0040, 0x3688, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x36d8,
- 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x3695, 0x1078, 0x47cb,
- 0x00c0, 0x3695, 0xd79c, 0x0040, 0x36d8, 0xd794, 0x00c0, 0x369b,
- 0xd784, 0x0040, 0x36a7, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9,
- 0x0004, 0x53a3, 0x1078, 0x338c, 0xd794, 0x0040, 0x36b0, 0xac80,
- 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, 0x338c,
- 0x21a2, 0xd794, 0x0040, 0x36d0, 0xac80, 0x0000, 0x2098, 0x94a0,
- 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80,
- 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x1078, 0x337e,
- 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0078, 0x36d1,
- 0x94a0, 0xd794, 0x0040, 0x36d6, 0xa6b0, 0x000b, 0xa6b0, 0x0005,
- 0x8108, 0xd78c, 0x0040, 0x36e2, 0xa186, 0x0100, 0x0040, 0x36f3,
- 0x0078, 0x36e6, 0xa186, 0x007e, 0x0040, 0x36f3, 0xd794, 0x0040,
- 0x36ed, 0xa686, 0x0020, 0x0078, 0x36ef, 0xa686, 0x0028, 0x0040,
- 0x36fc, 0x0078, 0x3677, 0x86ff, 0x00c0, 0x36fa, 0x7120, 0x810b,
- 0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022,
- 0x772a, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e,
- 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007,
- 0x0002, 0x701b, 0x3714, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3726,
- 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0xa3d1,
- 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3677, 0x7120, 0x810b,
- 0x0078, 0x2b2c, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38,
- 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502,
- 0x0048, 0x2b5a, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a,
- 0xa502, 0x0048, 0x2b5a, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020,
- 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa284, 0x00ff, 0xa0e2,
- 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa384, 0xff00,
- 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a,
- 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048,
- 0x2b5a, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a,
- 0xa502, 0x0048, 0x2b5a, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048,
- 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0x2061, 0xa5a3, 0x6102, 0x6206,
- 0x630a, 0x640e, 0x0078, 0x2b2c, 0x007e, 0x2001, 0xa352, 0x2004,
- 0xd0cc, 0x007f, 0x007c, 0x007e, 0x2001, 0xa371, 0x2004, 0xd0bc,
- 0x007f, 0x007c, 0x6160, 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x379b,
- 0x7926, 0x0078, 0x2b2c, 0x83ff, 0x00c0, 0x2b5a, 0x2001, 0xfff0,
- 0xa200, 0x00c8, 0x2b5a, 0x2019, 0xffff, 0x6064, 0xa302, 0xa200,
- 0x0048, 0x2b5a, 0x7926, 0x6262, 0x0078, 0x2b2c, 0x2001, 0xa300,
- 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x7c28, 0x7d24, 0x7e38,
- 0x7f2c, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2019,
- 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026,
- 0x20a0, 0xa1e0, 0xa434, 0x2c64, 0x8cff, 0x0040, 0x37e8, 0x6004,
- 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x37dd, 0x6004, 0xa084,
- 0xff00, 0xa086, 0x0600, 0x00c0, 0x37e8, 0x6014, 0x20a2, 0x94a0,
- 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002,
- 0x8108, 0xa182, 0x00ff, 0x0040, 0x37f3, 0xa386, 0x002a, 0x0040,
- 0x37fc, 0x0078, 0x37c9, 0x83ff, 0x00c0, 0x37fa, 0x7120, 0x810c,
- 0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022,
- 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426,
- 0x652a, 0x662e, 0x6732, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002,
- 0x701b, 0x3813, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3824, 0x711c,
- 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xa3d1, 0x6424, 0x6528,
- 0x662c, 0x6730, 0x0078, 0x37c9, 0x7120, 0x810c, 0x0078, 0x2b2c,
- 0x81ff, 0x00c0, 0x2b56, 0x60c8, 0xd09c, 0x0040, 0x2b56, 0x1078,
- 0x3518, 0x0040, 0x2b56, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x1078, 0x3562, 0x701b, 0x383d, 0x007c, 0x0d7e, 0xade8, 0x000d,
- 0x6828, 0xa0be, 0x7000, 0x0040, 0x3850, 0xa0be, 0x7100, 0x0040,
- 0x3850, 0xa0be, 0x7200, 0x0040, 0x3850, 0x0d7f, 0x0078, 0x2b5a,
- 0x6820, 0x6924, 0x1078, 0x24e3, 0x00c0, 0x387b, 0x1078, 0x4499,
- 0x00c0, 0x387b, 0x7122, 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078,
- 0x3518, 0x0040, 0x387b, 0x1078, 0x3518, 0x0040, 0x387b, 0x0c7f,
- 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
- 0x6804, 0x2068, 0x1078, 0x8bbd, 0x0040, 0x2b56, 0x7007, 0x0003,
- 0x701b, 0x387e, 0x007c, 0x0d7f, 0x0078, 0x2b56, 0x7120, 0x1078,
- 0x2921, 0x6820, 0xa086, 0x8001, 0x0040, 0x2b56, 0x2d00, 0x701e,
- 0x6804, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0,
- 0x1078, 0x41be, 0x007f, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10,
- 0x6d14, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6,
- 0x7000, 0x00c0, 0x38a5, 0x0078, 0x38a9, 0xa7c6, 0x7100, 0x00c0,
- 0x38b1, 0xa6c2, 0x0004, 0x0048, 0x2b5a, 0x2009, 0x0004, 0x0078,
- 0x3566, 0xa7c6, 0x7200, 0x00c0, 0x2b5a, 0xa6c2, 0x0054, 0x0048,
- 0x2b5a, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532,
- 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x38c8, 0x007c,
- 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002,
- 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x41be, 0x007f,
- 0x2009, 0x002a, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530,
- 0x0078, 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040,
- 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x4710, 0x0078,
- 0x2b2c, 0x7824, 0xd084, 0x0040, 0x3150, 0x1078, 0x3542, 0x0040,
- 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x00c0, 0x3903, 0x2009,
- 0x0002, 0x0078, 0x2b56, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
- 0x0040, 0x3910, 0xa08e, 0x0004, 0x0040, 0x3910, 0xa08e, 0x0005,
- 0x00c0, 0x3934, 0x2001, 0xa352, 0x2004, 0xd0b4, 0x0040, 0x3185,
- 0x6000, 0xd08c, 0x00c0, 0x3185, 0x6837, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x3929, 0x2009, 0x0003, 0x0078,
- 0x2b56, 0x7007, 0x0003, 0x701b, 0x392e, 0x007c, 0x1078, 0x3542,
- 0x0040, 0x2b5a, 0x0078, 0x3185, 0x2009, 0xa32e, 0x210c, 0x81ff,
- 0x0040, 0x393e, 0x2009, 0x0001, 0x0078, 0x2b56, 0x2001, 0xa300,
- 0x2004, 0xa086, 0x0003, 0x0040, 0x3949, 0x2009, 0x0007, 0x0078,
- 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x0040, 0x3953, 0x2009,
- 0x0008, 0x0078, 0x2b56, 0x609c, 0xd0a4, 0x00c0, 0x395a, 0xd0ac,
- 0x00c0, 0x3185, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x1078, 0x8c4d, 0x00c0, 0x3969, 0x2009, 0x0003, 0x0078,
- 0x2b56, 0x7007, 0x0003, 0x701b, 0x396e, 0x007c, 0x6830, 0xa086,
- 0x0100, 0x00c0, 0x3977, 0x2009, 0x0004, 0x0078, 0x2b56, 0x1078,
- 0x3542, 0x0040, 0x2b5a, 0x0078, 0x3912, 0x81ff, 0x2009, 0x0001,
- 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0,
- 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x00c0,
- 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff,
- 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078,
- 0x3518, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2b56, 0x6837, 0x0000,
- 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00,
- 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x39bc, 0xc0ed, 0x6952,
- 0x792c, 0x6956, 0x0078, 0x39c5, 0xa28e, 0x0100, 0x00c0, 0x2b5a,
- 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, 0x8df6,
- 0x2009, 0x0003, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x39d1,
- 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, 0x2b56,
- 0x0078, 0x2b2c, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2b56, 0x6000,
- 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2b56, 0x1078, 0x3542,
- 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009,
- 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2009,
- 0x0002, 0x0040, 0x2b56, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c,
- 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x3a08, 0x007c,
- 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, 0x3a1b,
- 0x6804, 0xa005, 0x00c0, 0x3a1b, 0x6808, 0xa084, 0xff00, 0x00c0,
- 0x3a1b, 0x0078, 0x3a1e, 0x0d7f, 0x00c0, 0x2b5a, 0x0d7f, 0x6837,
- 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, 0x1078,
- 0x3542, 0x00c0, 0x3a2e, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x8e52,
- 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b,
- 0x3a3a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040,
- 0x2b56, 0x0078, 0x2b2c, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100,
- 0x2071, 0xa300, 0x6044, 0xd0a4, 0x00c0, 0x3a6c, 0xd084, 0x0040,
- 0x3a55, 0x1078, 0x3bcc, 0x0078, 0x3a68, 0xd08c, 0x0040, 0x3a5c,
- 0x1078, 0x3ae3, 0x0078, 0x3a68, 0xd094, 0x0040, 0x3a63, 0x1078,
- 0x3ab7, 0x0078, 0x3a68, 0xd09c, 0x0040, 0x3a68, 0x1078, 0x3a76,
- 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0,
- 0x3a73, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3a68, 0x624c, 0xa286,
- 0xf0f0, 0x00c0, 0x3a87, 0x6048, 0xa086, 0xf0f0, 0x0040, 0x3a87,
- 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3ab6, 0xa294,
- 0xff00, 0xa296, 0xf700, 0x0040, 0x3a9c, 0x7134, 0xd1a4, 0x00c0,
- 0x3a9c, 0x6240, 0xa294, 0x0010, 0x0040, 0x3a9c, 0x2009, 0x00f7,
- 0x1078, 0x41de, 0x0078, 0x3ab6, 0x6043, 0x0040, 0x6043, 0x0000,
- 0x7073, 0x0000, 0x708b, 0x0001, 0x70af, 0x0000, 0x70cb, 0x0000,
- 0x2009, 0xa9c0, 0x200b, 0x0000, 0x7083, 0x0000, 0x7077, 0x000f,
- 0x2009, 0x000f, 0x2011, 0x4122, 0x1078, 0x596c, 0x007c, 0x157e,
- 0x7074, 0xa005, 0x00c0, 0x3ae1, 0x2011, 0x4122, 0x1078, 0x58d4,
- 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8,
- 0x6044, 0xd08c, 0x00c0, 0x3ada, 0x00f0, 0x3ac8, 0x6242, 0x7087,
- 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242,
- 0x0078, 0x3ae1, 0x6242, 0x7087, 0x0000, 0x707b, 0x0000, 0x0078,
- 0x3ae1, 0x157f, 0x007c, 0x7078, 0xa08a, 0x0003, 0x00c8, 0x3aec,
- 0x1079, 0x3aef, 0x0078, 0x3aee, 0x1078, 0x1328, 0x007c, 0x3af2,
- 0x3b41, 0x3bcb, 0x0f7e, 0x707b, 0x0001, 0x20e1, 0xa000, 0x20e1,
- 0x8700, 0x1078, 0x218b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
- 0xa800, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f,
- 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f,
- 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f,
- 0x0000, 0x2079, 0xa80c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
- 0xa305, 0x20a1, 0xa80e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xa812,
- 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xa800, 0x20a1, 0x020b,
- 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078,
- 0x4158, 0x0f7f, 0x707f, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
- 0x007c, 0x0d7e, 0x707c, 0x707f, 0x0000, 0xa025, 0x0040, 0x3bb5,
- 0x6020, 0xd0b4, 0x00c0, 0x3bb3, 0x7188, 0x81ff, 0x0040, 0x3ba2,
- 0xa486, 0x000c, 0x00c0, 0x3bad, 0xa480, 0x0018, 0x8004, 0x20a8,
- 0x2011, 0xa880, 0x2019, 0xa800, 0x220c, 0x2304, 0xa106, 0x00c0,
- 0x3b79, 0x8210, 0x8318, 0x00f0, 0x3b5c, 0x6043, 0x0004, 0x608b,
- 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707b, 0x0002, 0x7087,
- 0x0002, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c, 0x0078,
- 0x3bb3, 0x2069, 0xa880, 0x6930, 0xa18e, 0x1101, 0x00c0, 0x3bad,
- 0x6834, 0xa005, 0x00c0, 0x3bad, 0x6900, 0xa18c, 0x00ff, 0x00c0,
- 0x3b8d, 0x6804, 0xa005, 0x0040, 0x3ba2, 0x2011, 0xa88e, 0x2019,
- 0xa305, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, 0x3ba0,
- 0x00c0, 0x3bad, 0x8210, 0x8318, 0x00f0, 0x3b93, 0x0078, 0x3bad,
- 0x708b, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880,
- 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043,
- 0x0000, 0x0078, 0x3bb5, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0,
- 0x3bb3, 0x60c3, 0x000c, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f,
- 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
- 0x6c38, 0x0078, 0x3bb3, 0x007c, 0x7084, 0xa08a, 0x001d, 0x00c8,
- 0x3bd5, 0x1079, 0x3bd8, 0x0078, 0x3bd7, 0x1078, 0x1328, 0x007c,
- 0x3c02, 0x3c11, 0x3c40, 0x3c59, 0x3c85, 0x3cb1, 0x3cdd, 0x3d13,
- 0x3d3f, 0x3d67, 0x3daa, 0x3dd4, 0x3df6, 0x3e0c, 0x3e32, 0x3e45,
- 0x3e4e, 0x3e7e, 0x3eaa, 0x3ed6, 0x3f02, 0x3f38, 0x3f7d, 0x3fac,
- 0x3fce, 0x4010, 0x4036, 0x404f, 0x4050, 0x0c7e, 0x2061, 0xa300,
- 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006,
- 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002,
- 0x7087, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c,
- 0x007c, 0x0f7e, 0x707c, 0xa086, 0x0014, 0x00c0, 0x3c3e, 0x6043,
- 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3c3e, 0x2079, 0xa880, 0x7a30,
- 0xa296, 0x1102, 0x00c0, 0x3c3c, 0x7834, 0xa005, 0x00c0, 0x3c3c,
- 0x7a38, 0xd2fc, 0x0040, 0x3c32, 0x70ac, 0xa005, 0x00c0, 0x3c32,
- 0x70af, 0x0001, 0x2011, 0x4129, 0x1078, 0x58d4, 0x7087, 0x0010,
- 0x1078, 0x3e4e, 0x0078, 0x3c3e, 0x1078, 0x4171, 0x0f7f, 0x007c,
- 0x7087, 0x0003, 0x6043, 0x0004, 0x2011, 0x4129, 0x1078, 0x58d4,
- 0x1078, 0x41c6, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a,
- 0x20a3, 0x0000, 0x00f0, 0x3c50, 0x60c3, 0x0014, 0x1078, 0x4158,
- 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3c83, 0x2011, 0x4129,
- 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3c81, 0x2079, 0xa880,
- 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3c81, 0x7834, 0xa005, 0x00c0,
- 0x3c81, 0x7a38, 0xd2fc, 0x0040, 0x3c7b, 0x70ac, 0xa005, 0x00c0,
- 0x3c7b, 0x70af, 0x0001, 0x7087, 0x0004, 0x1078, 0x3c85, 0x0078,
- 0x3c83, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0005, 0x1078,
- 0x41c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e,
- 0x1078, 0x4211, 0x00c0, 0x3ca3, 0x7070, 0xa005, 0x00c0, 0x3ca3,
- 0x714c, 0xa186, 0xffff, 0x0040, 0x3ca3, 0x1078, 0x40ea, 0x0040,
- 0x3ca3, 0x1078, 0x41f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158,
- 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3cdb, 0x2011, 0x4129,
- 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3cd9, 0x2079, 0xa880,
- 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3cd9, 0x7834, 0xa005, 0x00c0,
- 0x3cd9, 0x7a38, 0xd2fc, 0x0040, 0x3cd3, 0x70ac, 0xa005, 0x00c0,
- 0x3cd3, 0x70af, 0x0001, 0x7087, 0x0006, 0x1078, 0x3cdd, 0x0078,
- 0x3cdb, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0007, 0x1078,
- 0x41c6, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e,
- 0x1078, 0x4211, 0x00c0, 0x3d05, 0x7070, 0xa005, 0x00c0, 0x3d05,
- 0x7150, 0xa186, 0xffff, 0x0040, 0x3d05, 0xa180, 0x293f, 0x200c,
- 0xa18c, 0xff00, 0x810f, 0x1078, 0x40ea, 0x0040, 0x3d05, 0x1078,
- 0x378b, 0x0040, 0x3d05, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298,
- 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
- 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3d3d,
- 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3d3b,
- 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3d3b, 0x7834,
- 0xa005, 0x00c0, 0x3d3b, 0x7a38, 0xd2fc, 0x0040, 0x3d35, 0x70ac,
- 0xa005, 0x00c0, 0x3d35, 0x70af, 0x0001, 0x7087, 0x0008, 0x1078,
- 0x3d3f, 0x0078, 0x3d3d, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087,
- 0x0009, 0x1078, 0x41c6, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430,
- 0x1078, 0x4211, 0x00c0, 0x3d58, 0x7070, 0xa005, 0x00c0, 0x3d58,
- 0x1078, 0x4051, 0x00c0, 0x3d62, 0xa085, 0x0001, 0x1078, 0x2500,
- 0x20a9, 0x0008, 0x2099, 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e,
- 0x707c, 0xa005, 0x0040, 0x3da8, 0x2011, 0x4129, 0x1078, 0x58d4,
- 0xa086, 0x0014, 0x00c0, 0x3da6, 0x2079, 0xa880, 0x7a30, 0xa296,
- 0x1105, 0x00c0, 0x3da6, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0,
- 0x3d91, 0x7a38, 0xd2fc, 0x0040, 0x3d8b, 0x70ac, 0xa005, 0x00c0,
- 0x3d8b, 0x70af, 0x0001, 0x7087, 0x000a, 0x1078, 0x3daa, 0x0078,
- 0x3da8, 0xa005, 0x00c0, 0x3da6, 0x7a38, 0xd2fc, 0x0040, 0x3d9e,
- 0x70ac, 0xa005, 0x00c0, 0x3d9e, 0x70af, 0x0001, 0x7083, 0x0000,
- 0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3da8, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x000b, 0x2011, 0xa80e, 0x22a0, 0x20a9,
- 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000,
- 0x41a4, 0x1078, 0x41c6, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x1078,
- 0x4211, 0x0040, 0x3dc7, 0x2013, 0x0000, 0x0078, 0x3dcb, 0x6030,
- 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
- 0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
- 0x3df4, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
- 0x3df2, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3df2,
- 0x7834, 0xa005, 0x00c0, 0x3df2, 0x7087, 0x000c, 0x1078, 0x3df6,
- 0x0078, 0x3df4, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x000d,
- 0x1078, 0x41c6, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xa88e,
- 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
- 0x3e30, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
- 0x3e2e, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3e2e,
- 0x7834, 0xa005, 0x00c0, 0x3e2e, 0x7083, 0x0001, 0x1078, 0x41b8,
- 0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3e30, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x000f, 0x707f, 0x0000, 0x608b, 0xbc85,
- 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0,
- 0x2011, 0x4129, 0x1078, 0x58c7, 0x007c, 0x707c, 0xa005, 0x0040,
- 0x3e4d, 0x2011, 0x4129, 0x1078, 0x58d4, 0x007c, 0x7087, 0x0011,
- 0x1078, 0x4211, 0x00c0, 0x3e67, 0x7168, 0x81ff, 0x0040, 0x3e67,
- 0x2009, 0x0000, 0x706c, 0xa084, 0x00ff, 0x1078, 0x24e3, 0xa186,
- 0x0080, 0x0040, 0x3e67, 0x2011, 0xa88e, 0x1078, 0x40ea, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x747c,
- 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8,
- 0x53a6, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c,
- 0xa005, 0x0040, 0x3ea8, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086,
- 0x0014, 0x00c0, 0x3ea6, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1103,
- 0x00c0, 0x3ea6, 0x7834, 0xa005, 0x00c0, 0x3ea6, 0x7a38, 0xd2fc,
- 0x0040, 0x3ea0, 0x70ac, 0xa005, 0x00c0, 0x3ea0, 0x70af, 0x0001,
- 0x7087, 0x0012, 0x1078, 0x3eaa, 0x0078, 0x3ea8, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x0013, 0x1078, 0x41d2, 0x20a3, 0x1103,
- 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0,
- 0x3ec8, 0x7070, 0xa005, 0x00c0, 0x3ec8, 0x714c, 0xa186, 0xffff,
- 0x0040, 0x3ec8, 0x1078, 0x40ea, 0x0040, 0x3ec8, 0x1078, 0x41f5,
- 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c,
- 0xa005, 0x0040, 0x3f00, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086,
- 0x0014, 0x00c0, 0x3efe, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104,
- 0x00c0, 0x3efe, 0x7834, 0xa005, 0x00c0, 0x3efe, 0x7a38, 0xd2fc,
- 0x0040, 0x3ef8, 0x70ac, 0xa005, 0x00c0, 0x3ef8, 0x70af, 0x0001,
- 0x7087, 0x0014, 0x1078, 0x3f02, 0x0078, 0x3f00, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x0015, 0x1078, 0x41d2, 0x20a3, 0x1104,
- 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0,
- 0x3f2a, 0x7070, 0xa005, 0x00c0, 0x3f2a, 0x7150, 0xa186, 0xffff,
- 0x0040, 0x3f2a, 0xa180, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f,
- 0x1078, 0x40ea, 0x0040, 0x3f2a, 0x1078, 0x378b, 0x0040, 0x3f2a,
- 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c,
- 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3f7b, 0x2011, 0x4129, 0x1078,
- 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3f79, 0x2079, 0xa880, 0x7a30,
- 0xa296, 0x1105, 0x00c0, 0x3f79, 0x7834, 0x2011, 0x0100, 0xa21e,
- 0x00c0, 0x3f5e, 0x7a38, 0xd2fc, 0x0040, 0x3f5c, 0x70ac, 0xa005,
- 0x00c0, 0x3f5c, 0x70af, 0x0001, 0x0078, 0x3f6d, 0xa005, 0x00c0,
- 0x3f79, 0x7a38, 0xd2fc, 0x0040, 0x3f6b, 0x70ac, 0xa005, 0x00c0,
- 0x3f6b, 0x70af, 0x0001, 0x7083, 0x0000, 0x7a38, 0xd2f4, 0x0040,
- 0x3f73, 0x70cb, 0x0008, 0x7087, 0x0016, 0x1078, 0x3f7d, 0x0078,
- 0x3f7b, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6,
- 0x3430, 0x2011, 0xa88e, 0x7087, 0x0017, 0x1078, 0x4211, 0x00c0,
- 0x3f9d, 0x7070, 0xa005, 0x00c0, 0x3f9d, 0x1078, 0x4051, 0x00c0,
- 0x3fa7, 0xa085, 0x0001, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2099,
- 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
- 0x3fcc, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
- 0x3fca, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3fca,
- 0x7834, 0xa005, 0x00c0, 0x3fca, 0x7087, 0x0018, 0x1078, 0x3fce,
- 0x0078, 0x3fcc, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0019,
- 0x1078, 0x41d2, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099,
- 0xa88e, 0x2039, 0xa80e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x1078,
- 0x4211, 0x00c0, 0x4002, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff,
- 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x6030,
- 0x2310, 0x8214, 0xa2a0, 0xa80e, 0x2414, 0xa38c, 0x0001, 0x0040,
- 0x3ffd, 0xa294, 0xff00, 0x0078, 0x4000, 0xa294, 0x00ff, 0x8007,
- 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c,
- 0x0f7e, 0x707c, 0xa005, 0x0040, 0x4034, 0x2011, 0x4129, 0x1078,
- 0x58d4, 0xa086, 0x0084, 0x00c0, 0x4032, 0x2079, 0xa880, 0x7a30,
- 0xa296, 0x1107, 0x00c0, 0x4032, 0x7834, 0xa005, 0x00c0, 0x4032,
- 0x7083, 0x0001, 0x1078, 0x41b8, 0x7087, 0x001a, 0x1078, 0x4036,
- 0x0078, 0x4034, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x001b,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b,
- 0x747c, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004,
- 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c, 0x007c,
- 0x007c, 0x087e, 0x097e, 0x2029, 0xa352, 0x252c, 0x20a9, 0x0008,
- 0x2041, 0xa80e, 0x28a0, 0x2099, 0xa88e, 0x53a3, 0x20a9, 0x0008,
- 0x2011, 0x0007, 0xd5d4, 0x0040, 0x4067, 0x2011, 0x0000, 0x2800,
- 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x4079, 0xd5d4, 0x0040,
- 0x4074, 0x8210, 0x0078, 0x4075, 0x8211, 0x00f0, 0x4067, 0x0078,
- 0x40e1, 0x82ff, 0x00c0, 0x408b, 0xd5d4, 0x0040, 0x4085, 0xa1a6,
- 0x3fff, 0x0040, 0x4071, 0x0078, 0x4089, 0xa1a6, 0x3fff, 0x0040,
- 0x40e1, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4,
- 0x0040, 0x4094, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x409b,
- 0x8423, 0x0078, 0x409c, 0x8424, 0x00c8, 0x40a9, 0xd5d4, 0x0040,
- 0x40a4, 0x8319, 0x0078, 0x40a5, 0x8318, 0x00f0, 0x4095, 0x0078,
- 0x40e1, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x40ad,
- 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, 0x40c1, 0x007e, 0x2039,
- 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0,
- 0x40bd, 0x754e, 0xa5c8, 0x293f, 0x292c, 0xa5ac, 0x00ff, 0x6532,
- 0x60e7, 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x2018, 0x2304,
- 0xa405, 0x201a, 0x7073, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008,
- 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0078,
- 0x40e7, 0xa006, 0x0078, 0x40e7, 0xa006, 0x1078, 0x1328, 0x097f,
- 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a,
- 0x0010, 0x0048, 0x40f7, 0x8420, 0x8001, 0x0078, 0x40ef, 0x2118,
- 0x84ff, 0x0040, 0x4100, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x40fb,
- 0x2021, 0x0001, 0x83ff, 0x0040, 0x4109, 0x8423, 0x8319, 0x00c0,
- 0x4105, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x4121, 0xa405, 0x203a,
- 0x714e, 0xa1a0, 0x293f, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
- 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x7073, 0x0001, 0xa084,
- 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x7077, 0x0000, 0x0e7f,
- 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, 0x1078, 0x5975, 0x2079,
- 0x0100, 0x2071, 0x0140, 0x1078, 0x6c41, 0x7004, 0xa084, 0x4000,
- 0x0040, 0x413e, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, 0x2091,
- 0x8000, 0x2071, 0xa321, 0x2073, 0x0000, 0x7840, 0x027e, 0x017e,
- 0x2009, 0x00f7, 0x1078, 0x41de, 0x017f, 0xa094, 0x0010, 0xa285,
- 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, 0x0f7f, 0x0e7f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f,
- 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
- 0x1078, 0x6c38, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c,
- 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2009,
- 0x00f7, 0x1078, 0x41de, 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f,
- 0x0000, 0x2061, 0xa300, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043,
- 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078,
- 0x58c7, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, 0x0e7e, 0x007e,
- 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, 0x1078, 0x5975, 0x2071,
- 0x0100, 0x1078, 0x6c41, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000,
- 0x0040, 0x41ae, 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001,
- 0x1078, 0x2480, 0x1078, 0x4171, 0x127f, 0x007f, 0x0e7f, 0x007c,
- 0x20a9, 0x0040, 0x20a1, 0xa9c0, 0x2099, 0xa88e, 0x3304, 0x8007,
- 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x41be, 0x007c, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x2099, 0xa800, 0x20a1, 0x020b, 0x20a9, 0x000c,
- 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880,
- 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e,
- 0x2061, 0x0100, 0x810f, 0x2001, 0xa32e, 0x2004, 0xa005, 0x00c0,
- 0x41ef, 0x6030, 0xa084, 0x00ff, 0xa105, 0x0078, 0x41f1, 0xa185,
- 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x4208, 0xa006, 0x2020, 0x2009,
- 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195, 0x2102,
- 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, 0x27e2, 0x047f, 0x017f,
- 0x007c, 0x007e, 0x2001, 0xa30c, 0x2004, 0xd09c, 0x0040, 0x4218,
- 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, 0x2091, 0x8000, 0x2001,
- 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x127f, 0x017f, 0x007f,
- 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0xa434, 0xa006, 0x200a,
- 0x8108, 0x00f0, 0x422f, 0x157f, 0x007c, 0x0d7e, 0x037e, 0x157e,
- 0x137e, 0x147e, 0x2069, 0xa351, 0xa006, 0x6002, 0x6007, 0x0707,
- 0x600a, 0x600e, 0x6012, 0xa198, 0x293f, 0x231c, 0xa39c, 0x00ff,
- 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9,
- 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e,
- 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e,
- 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e,
- 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x0d7e, 0x60a4,
- 0xa06d, 0x0040, 0x4275, 0x1078, 0x139a, 0x60a7, 0x0000, 0x60a8,
- 0xa06d, 0x0040, 0x427d, 0x1078, 0x139a, 0x60ab, 0x0000, 0x0d7f,
- 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084,
- 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082,
- 0x4000, 0x00c8, 0x4361, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
- 0x00c8, 0x4367, 0x2001, 0xa30c, 0x2004, 0xa084, 0x0003, 0x0040,
- 0x42c2, 0x2001, 0xa30c, 0x2004, 0xd084, 0x00c0, 0x4342, 0xa188,
- 0xa434, 0x2104, 0xa065, 0x0040, 0x4342, 0x6004, 0xa084, 0x00ff,
- 0xa08e, 0x0006, 0x00c0, 0x4342, 0x6000, 0xd0c4, 0x0040, 0x4342,
- 0x0078, 0x42cf, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4326,
- 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x432c, 0x60a4,
- 0xa00d, 0x0040, 0x42d7, 0x1078, 0x4749, 0x0040, 0x4320, 0x60a8,
- 0xa00d, 0x0040, 0x42f1, 0x1078, 0x479a, 0x00c0, 0x42f1, 0x694c,
- 0xd1fc, 0x00c0, 0x42e7, 0x1078, 0x441c, 0x0078, 0x431b, 0x1078,
- 0x43d6, 0x694c, 0xd1ec, 0x00c0, 0x431b, 0x1078, 0x460a, 0x0078,
- 0x431b, 0x694c, 0xa184, 0xa000, 0x0040, 0x430b, 0xd1ec, 0x0040,
- 0x4304, 0xd1fc, 0x0040, 0x4300, 0x1078, 0x461b, 0x0078, 0x4307,
- 0x1078, 0x461b, 0x0078, 0x430b, 0xd1fc, 0x0040, 0x430b, 0x1078,
- 0x43d6, 0x0078, 0x431b, 0x6050, 0xa00d, 0x0040, 0x4316, 0x2d00,
- 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x431b, 0x2d00, 0x6052,
- 0x604e, 0x6803, 0x0000, 0x1078, 0x5c17, 0xa006, 0x127f, 0x007c,
- 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001, 0x0028,
- 0x2009, 0x0000, 0x0078, 0x436b, 0xa082, 0x0006, 0x00c8, 0x4342,
- 0x60a0, 0xd0bc, 0x00c0, 0x433e, 0x6100, 0xd1fc, 0x0040, 0x42cf,
- 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x436b, 0x2001, 0x0028,
- 0x0078, 0x435d, 0x2009, 0xa30c, 0x210c, 0xd18c, 0x0040, 0x434c,
- 0x2001, 0x0004, 0x0078, 0x435d, 0xd184, 0x0040, 0x4353, 0x2001,
- 0x0004, 0x0078, 0x435d, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0040,
- 0x435d, 0x2009, 0x1000, 0x0078, 0x436b, 0x2009, 0x0000, 0x0078,
- 0x436b, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001,
- 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0x6e48,
- 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x43bb, 0xa18c, 0xff00,
- 0x810f, 0xa182, 0x00ff, 0x00c8, 0x43a1, 0xa188, 0xa434, 0x2104,
- 0xa065, 0x0040, 0x43a1, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006,
- 0x00c0, 0x43a7, 0x684c, 0xd0ec, 0x0040, 0x4394, 0x1078, 0x461b,
- 0x1078, 0x43d6, 0x0078, 0x439c, 0x1078, 0x43d6, 0x684c, 0xd0fc,
- 0x0040, 0x439c, 0x1078, 0x460a, 0x1078, 0x4663, 0xa006, 0x0078,
- 0x43bf, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x43bf, 0xa082,
- 0x0006, 0x00c8, 0x43b5, 0x6100, 0xd1fc, 0x0040, 0x438a, 0x2001,
- 0x0029, 0x2009, 0x1000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009,
- 0x0000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
- 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040, 0x43cf,
- 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c, 0x2d00,
- 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x43cd, 0x127e, 0x2091,
- 0x8000, 0x604c, 0xa005, 0x0040, 0x43ec, 0x0e7e, 0x2071, 0xa5ab,
- 0x7004, 0xa086, 0x0002, 0x0040, 0x43f3, 0x0e7f, 0x604c, 0x6802,
- 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803,
- 0x0000, 0x0078, 0x43ea, 0x701c, 0xac06, 0x00c0, 0x43e5, 0x604c,
- 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x0e7f, 0x127f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040, 0x440e, 0x6800,
- 0xa005, 0x00c0, 0x440c, 0x6052, 0x604e, 0xad05, 0x127f, 0x007c,
- 0x604c, 0xa06d, 0x0040, 0x441b, 0x6800, 0xa005, 0x00c0, 0x4419,
- 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000, 0x6084, 0xa00d,
- 0x0040, 0x4426, 0x2d00, 0x200a, 0x6086, 0x007c, 0x2d00, 0x6086,
- 0x6082, 0x0078, 0x4425, 0x127e, 0x0c7e, 0x027e, 0x2091, 0x8000,
- 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x4439, 0xc285, 0x0078,
- 0x443a, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e,
- 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086,
- 0x0006, 0x00c0, 0x445e, 0x609c, 0xd0ac, 0x0040, 0x445e, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x445e, 0xa284, 0xff00, 0x8007,
- 0xa086, 0x0007, 0x00c0, 0x445e, 0x2011, 0x0600, 0x007f, 0xa294,
- 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, 0x0006, 0x00c0, 0x446e,
- 0x6290, 0x82ff, 0x00c0, 0x446e, 0x1078, 0x1328, 0x007f, 0x0c7f,
- 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260,
- 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4490, 0x609c, 0xd0a4,
- 0x0040, 0x4490, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x4490,
- 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, 0x4490, 0x2011, 0x0006,
- 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f,
- 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, 0x44a2, 0xa085, 0x0001,
- 0x0078, 0x44ba, 0xa190, 0xa434, 0x2204, 0xa065, 0x00c0, 0x44b9,
- 0x017e, 0x0d7e, 0x1078, 0x1366, 0x2d60, 0x0d7f, 0x017f, 0x0040,
- 0x449e, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x1078,
- 0x4235, 0xa006, 0x027f, 0x007c, 0x127e, 0x2091, 0x8000, 0x027e,
- 0xa182, 0x00ff, 0x0048, 0x44c8, 0xa085, 0x0001, 0x0078, 0x44fe,
- 0x0d7e, 0xa190, 0xa434, 0x2204, 0xa06d, 0x0040, 0x44fc, 0x2013,
- 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, 0xa06d, 0x0040, 0x44da,
- 0x1078, 0x139a, 0x60a8, 0xa06d, 0x0040, 0x44e0, 0x1078, 0x139a,
- 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, 0x2060, 0x8cff, 0x0040,
- 0x44f8, 0x600c, 0x007e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040,
- 0x44f3, 0x1078, 0x13aa, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x44e6,
- 0x0c7f, 0x0d7f, 0x1078, 0x139a, 0x0d7f, 0xa006, 0x027f, 0x127f,
- 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, 0x450a, 0xa085, 0x0001,
- 0x0078, 0x4511, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4506,
- 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b,
- 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0xa88e,
- 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0048, 0x4529,
- 0x603a, 0x6814, 0x6066, 0x2099, 0xa896, 0xac88, 0x000a, 0x21a0,
- 0x20a9, 0x0004, 0x53a3, 0x2099, 0xa89a, 0xac88, 0x0006, 0x21a0,
- 0x20a9, 0x0004, 0x53a3, 0x2069, 0xa8ae, 0x6808, 0x606a, 0x690c,
- 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x00c8,
- 0x454d, 0x2009, 0x0008, 0x0078, 0x4577, 0xa182, 0x0259, 0x00c8,
- 0x4555, 0x2009, 0x0007, 0x0078, 0x4577, 0xa182, 0x02c1, 0x00c8,
- 0x455d, 0x2009, 0x0006, 0x0078, 0x4577, 0xa182, 0x0349, 0x00c8,
- 0x4565, 0x2009, 0x0005, 0x0078, 0x4577, 0xa182, 0x0421, 0x00c8,
- 0x456d, 0x2009, 0x0004, 0x0078, 0x4577, 0xa182, 0x0581, 0x00c8,
- 0x4575, 0x2009, 0x0003, 0x0078, 0x4577, 0x2009, 0x0002, 0x6192,
- 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x017e, 0x027e, 0x0e7e,
- 0x2071, 0xa88d, 0x2e04, 0x6896, 0x2071, 0xa88e, 0x7004, 0x689a,
- 0x701c, 0x689e, 0x6a00, 0x2009, 0xa371, 0x210c, 0xd0bc, 0x0040,
- 0x4597, 0xd1ec, 0x0040, 0x4597, 0xc2ad, 0x0078, 0x4598, 0xc2ac,
- 0xd0c4, 0x0040, 0x45a1, 0xd1e4, 0x0040, 0x45a1, 0xc2bd, 0x0078,
- 0x45a2, 0xc2bc, 0x6a02, 0x0e7f, 0x027f, 0x017f, 0x007c, 0x0d7e,
- 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x0040, 0x45cb, 0x6900,
- 0x81ff, 0x00c0, 0x45df, 0x6a04, 0xa282, 0x0010, 0x00c8, 0x45e4,
- 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040,
- 0x45c6, 0x8108, 0x00f0, 0x45bc, 0x1078, 0x1328, 0x260a, 0x8210,
- 0x6a06, 0x0078, 0x45df, 0x1078, 0x1381, 0x0040, 0x45e4, 0x2d00,
- 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
- 0xffff, 0x8108, 0x00f0, 0x45d7, 0x6807, 0x0001, 0x6e12, 0xa085,
- 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x45e1, 0x127e,
- 0x2091, 0x8000, 0x0d7e, 0x60a4, 0xa00d, 0x0040, 0x4607, 0x2168,
- 0x6800, 0xa005, 0x00c0, 0x4603, 0x1078, 0x4749, 0x00c0, 0x4607,
- 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0048, 0x4603, 0x8001,
- 0x6806, 0x0078, 0x4607, 0x1078, 0x139a, 0x60a7, 0x0000, 0x0d7f,
- 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x47af, 0x0078,
- 0x4613, 0x1078, 0x43c1, 0x1078, 0x46a7, 0x00c0, 0x4611, 0x1078,
- 0x4663, 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a8,
- 0xa06d, 0x0040, 0x463f, 0x6950, 0x81ff, 0x00c0, 0x4653, 0x6a54,
- 0xa282, 0x0010, 0x00c8, 0x4660, 0xad88, 0x0018, 0x20a9, 0x0010,
- 0x2104, 0xa086, 0xffff, 0x0040, 0x463a, 0x8108, 0x00f0, 0x4630,
- 0x1078, 0x1328, 0x260a, 0x8210, 0x6a56, 0x0078, 0x4653, 0x1078,
- 0x1381, 0x0040, 0x4660, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88,
- 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x464b,
- 0x6857, 0x0001, 0x6e62, 0x0078, 0x4657, 0x1078, 0x441c, 0x1078,
- 0x466d, 0x00c0, 0x4655, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c,
- 0xa006, 0x0078, 0x465d, 0x127e, 0x2091, 0x8000, 0x1078, 0x5c17,
- 0x127f, 0x007c, 0xa01e, 0x0078, 0x466f, 0x2019, 0x0001, 0xa00e,
- 0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0,
- 0x468d, 0x8dff, 0x0040, 0x46a2, 0x83ff, 0x0040, 0x4685, 0x6848,
- 0xa606, 0x0040, 0x4692, 0x0078, 0x468d, 0x683c, 0xa406, 0x00c0,
- 0x468d, 0x6840, 0xa506, 0x0040, 0x4692, 0x2d08, 0x6800, 0x2068,
- 0x0078, 0x4679, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x469a, 0x624e,
- 0x0078, 0x469d, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x46a2,
- 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x46a9, 0x2019,
- 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x46d5, 0x83ff,
- 0x0040, 0x46b8, 0x6848, 0xa606, 0x0040, 0x46c5, 0x0078, 0x46c0,
- 0x683c, 0xa406, 0x00c0, 0x46c0, 0x6840, 0xa506, 0x0040, 0x46c5,
- 0x2d08, 0x6800, 0x2068, 0x0078, 0x46ac, 0x6a00, 0x6080, 0xad06,
- 0x00c0, 0x46cd, 0x6282, 0x0078, 0x46d0, 0xa180, 0x0000, 0x2202,
- 0x82ff, 0x00c0, 0x46d5, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078,
- 0x4742, 0x00c0, 0x46dd, 0x2011, 0x0001, 0x1078, 0x4793, 0x00c0,
- 0x46e3, 0xa295, 0x0002, 0x007c, 0x1078, 0x47cb, 0x0040, 0x46ec,
- 0x1078, 0x8b12, 0x0078, 0x46ee, 0xa085, 0x0001, 0x007c, 0x1078,
- 0x47cb, 0x0040, 0x46f7, 0x1078, 0x8aaa, 0x0078, 0x46f9, 0xa085,
- 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040, 0x4702, 0x1078, 0x8af4,
- 0x0078, 0x4704, 0xa085, 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040,
- 0x470d, 0x1078, 0x8ac6, 0x0078, 0x470f, 0xa085, 0x0001, 0x007c,
- 0x1078, 0x47cb, 0x0040, 0x4718, 0x1078, 0x8b30, 0x0078, 0x471a,
- 0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000,
- 0x6080, 0xa06d, 0x0040, 0x473a, 0x6800, 0x007e, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x007e, 0x6000, 0xd0fc,
- 0x0040, 0x4734, 0x1078, 0xa18c, 0x007f, 0x1078, 0x4982, 0x007f,
- 0x0078, 0x4721, 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f,
- 0x127f, 0x007c, 0x60a4, 0xa00d, 0x00c0, 0x4749, 0xa085, 0x0001,
- 0x007c, 0x0e7e, 0x2170, 0x7000, 0xa005, 0x00c0, 0x475c, 0x20a9,
- 0x0010, 0xae88, 0x0004, 0x2104, 0xa606, 0x0040, 0x475c, 0x8108,
- 0x00f0, 0x4753, 0xa085, 0x0001, 0xa006, 0x0e7f, 0x007c, 0x0d7e,
- 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x476d, 0x1078,
- 0x1381, 0x0040, 0x477f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807,
- 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108,
- 0x00f0, 0x4775, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006,
- 0x0078, 0x477c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d,
- 0x0040, 0x4790, 0x60a7, 0x0000, 0x1078, 0x139a, 0xa085, 0x0001,
- 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x479a, 0xa085,
- 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x47ad,
- 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x47ad,
- 0x8108, 0x00f0, 0x47a4, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x4793, 0x00c0, 0x47c9, 0x200b, 0xffff,
- 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x47c4,
- 0x8001, 0x6856, 0x0078, 0x47c8, 0x1078, 0x139a, 0x60ab, 0x0000,
- 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71ac,
- 0x81ff, 0x00c0, 0x47e9, 0x71c8, 0xd19c, 0x0040, 0x47e9, 0x2001,
- 0x007e, 0xa080, 0xa434, 0x2004, 0xa07d, 0x0040, 0x47e9, 0x7804,
- 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x47e9, 0x7800, 0xc0ed,
- 0x7802, 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x480f, 0x157e,
- 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501,
- 0x00c0, 0x4809, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
- 0x0040, 0x4806, 0xa086, 0x0006, 0x00c0, 0x4809, 0x6000, 0xc0ed,
- 0x6002, 0x017f, 0x8108, 0x00f0, 0x47f5, 0x0c7f, 0x157f, 0x1078,
- 0x4897, 0x0040, 0x4818, 0x2001, 0xa59f, 0x200c, 0x0078, 0x4820,
- 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x4824, 0x2009, 0x07d0,
- 0x2011, 0x4826, 0x1078, 0x596c, 0x0f7f, 0x007c, 0x2011, 0x4826,
- 0x1078, 0x58d4, 0x1078, 0x4897, 0x0040, 0x484e, 0x2001, 0xa4b2,
- 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa352,
- 0x2004, 0xd0a4, 0x0040, 0x4842, 0x2009, 0x07d0, 0x2011, 0x4826,
- 0x1078, 0x596c, 0x0e7e, 0x2071, 0xa300, 0x706b, 0x0000, 0x706f,
- 0x0000, 0x1078, 0x260d, 0x0e7f, 0x0078, 0x4886, 0x157e, 0x0c7e,
- 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0,
- 0x4880, 0x6000, 0xd0ec, 0x0040, 0x4880, 0x047e, 0x62a0, 0xa294,
- 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6000,
- 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700,
- 0x6006, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000,
- 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38, 0x077f, 0x047f,
- 0x017f, 0x8108, 0x00f0, 0x4854, 0x0c7f, 0x157f, 0x007c, 0x0c7e,
- 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818,
- 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e,
- 0x2001, 0xa4b2, 0x2004, 0xa07d, 0x0040, 0x48a0, 0x7800, 0xd0ec,
- 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x6200, 0xa005,
- 0x0040, 0x48ad, 0xc2fd, 0x0078, 0x48ae, 0xc2fc, 0x6202, 0x027f,
- 0x127f, 0x007c, 0x2071, 0xa413, 0x7003, 0x0001, 0x7007, 0x0000,
- 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000,
- 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020,
- 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa57c, 0x7003, 0xa413,
- 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa55c, 0x7013, 0x0020,
- 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, 0x2071,
- 0xa534, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xa352,
- 0x2004, 0xd0fc, 0x00c0, 0x48f7, 0x2001, 0xa352, 0x2004, 0xa00e,
- 0xd09c, 0x0040, 0x48f4, 0x8108, 0x7102, 0x0078, 0x494a, 0x2001,
- 0xa371, 0x200c, 0xa184, 0x000f, 0x2009, 0xa372, 0x210c, 0x0079,
- 0x4901, 0x48ec, 0x4922, 0x492a, 0x4935, 0x493b, 0x48ec, 0x48ec,
- 0x48ec, 0x4911, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec,
- 0x48ec, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, 0xa375,
- 0x20a1, 0xa585, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f,
- 0x0078, 0x494a, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002,
- 0x0078, 0x4930, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003,
- 0x7002, 0x7097, 0x0001, 0x0078, 0x4947, 0x7007, 0x0122, 0x2001,
- 0x0002, 0x0078, 0x493f, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002,
- 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, 0xa184,
- 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, 0xa413,
- 0x684c, 0xa005, 0x00c0, 0x495b, 0x7028, 0xc085, 0x702a, 0xa085,
- 0x0001, 0x0078, 0x4980, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868,
- 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844,
- 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006,
- 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
- 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
- 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, 0x49d8,
- 0x6804, 0xa00d, 0x0040, 0x499e, 0x0d7e, 0x2071, 0xa300, 0xa016,
- 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x00c0,
- 0x4991, 0x702e, 0x70a8, 0xa200, 0x70aa, 0x0d7f, 0x2071, 0xa413,
- 0x701c, 0xa005, 0x00c0, 0x49ea, 0x0068, 0x49e8, 0x2071, 0xa534,
- 0x7200, 0x82ff, 0x0040, 0x49e8, 0x6934, 0xa186, 0x0103, 0x00c0,
- 0x49fb, 0x6948, 0x6844, 0xa105, 0x00c0, 0x49db, 0x2009, 0x8020,
- 0x2200, 0x0079, 0x49bb, 0x49e8, 0x49c0, 0x4a18, 0x4a26, 0x49e8,
- 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x49e8, 0x7122, 0x683c,
- 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x2071,
- 0xa300, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa,
- 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, 0x49e8,
- 0x6868, 0xa005, 0x00c0, 0x49e8, 0x2009, 0x8020, 0x0078, 0x49b8,
- 0x2071, 0xa413, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012,
- 0x7018, 0xa06d, 0x711a, 0x0040, 0x49f8, 0x6902, 0x0078, 0x49f9,
- 0x711e, 0x0078, 0x49d8, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040,
- 0x4a09, 0xa186, 0x001e, 0x0040, 0x4a09, 0xa18e, 0x001f, 0x00c0,
- 0x49e8, 0x684c, 0xd0cc, 0x0040, 0x49e8, 0x6850, 0xa084, 0x00ff,
- 0xa086, 0x0001, 0x00c0, 0x49e8, 0x2009, 0x8021, 0x0078, 0x49b8,
- 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x49e8, 0x7186, 0xae90,
- 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4a36, 0x7084, 0x8008,
- 0xa092, 0x000f, 0x00c8, 0x49e8, 0x7186, 0xae90, 0x0003, 0x8003,
- 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a,
- 0x0048, 0x49cf, 0x718c, 0x7084, 0xa10a, 0x0048, 0x49cf, 0x2071,
- 0x0000, 0x7018, 0xd084, 0x00c0, 0x49cf, 0x2071, 0xa534, 0x7000,
- 0xa086, 0x0002, 0x00c0, 0x4a56, 0x1078, 0x4cd2, 0x2071, 0x0000,
- 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf, 0x1078, 0x4cfd,
- 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf,
- 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
- 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, 0x00ff,
- 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa413, 0x7004,
- 0x0079, 0x4a7a, 0x4a84, 0x4a95, 0x4ca3, 0x4ca4, 0x4ccb, 0x4cd1,
- 0x4a85, 0x4c91, 0x4c32, 0x4cb4, 0x007c, 0x127e, 0x2091, 0x8000,
- 0x0068, 0x4a94, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080,
- 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa5be, 0x6844,
- 0xa005, 0x0050, 0x4abd, 0x00c0, 0x4abd, 0x127e, 0x2091, 0x8000,
- 0x2069, 0x0000, 0x6934, 0x2001, 0xa41f, 0x2004, 0xa10a, 0x0040,
- 0x4ab8, 0x0068, 0x4abc, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
- 0x4abc, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080,
- 0x2069, 0xa5be, 0x6847, 0xffff, 0x127f, 0x2069, 0xa300, 0x6844,
- 0x6960, 0xa102, 0x2069, 0xa534, 0x688a, 0x6984, 0x701c, 0xa06d,
- 0x0040, 0x4acf, 0x81ff, 0x0040, 0x4b17, 0x0078, 0x4ae5, 0x81ff,
- 0x0040, 0x4be9, 0x2071, 0xa534, 0x7184, 0x7088, 0xa10a, 0x00c8,
- 0x4ae5, 0x7190, 0x2071, 0xa5be, 0x7040, 0xa005, 0x0040, 0x4ae5,
- 0x00d0, 0x4be9, 0x7142, 0x0078, 0x4be9, 0x2071, 0xa534, 0x718c,
- 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4c06, 0x0068,
- 0x4b9b, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4b9b, 0x2001,
- 0xffff, 0x2071, 0xa5be, 0x7042, 0x2071, 0xa534, 0x7000, 0xa086,
- 0x0002, 0x00c0, 0x4b0d, 0x1078, 0x4cd2, 0x2071, 0x0000, 0x701b,
- 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x1078, 0x4cfd, 0x2071,
- 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x2071,
- 0xa534, 0x7000, 0xa005, 0x0040, 0x4bc8, 0x6934, 0xa186, 0x0103,
- 0x00c0, 0x4b9e, 0x684c, 0xd0bc, 0x00c0, 0x4bc8, 0x6948, 0x6844,
- 0xa105, 0x00c0, 0x4bbb, 0x2009, 0x8020, 0x2071, 0xa534, 0x7000,
- 0x0079, 0x4b32, 0x4bc8, 0x4b80, 0x4b58, 0x4b6a, 0x4b37, 0x137e,
- 0x147e, 0x157e, 0x2099, 0xa375, 0x20a1, 0xa585, 0x20a9, 0x0004,
- 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa57c, 0xad80, 0x000f,
- 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, 0x2e10,
- 0x1078, 0x13d1, 0x2071, 0xa413, 0x7007, 0x0009, 0x0078, 0x4be9,
- 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4be9, 0xae90, 0x0003,
- 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b,
- 0x0078, 0x4be9, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, 0x4be9,
- 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840,
- 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b, 0x0078, 0x4be9,
- 0x127e, 0x2091, 0x8000, 0x0068, 0x4b9b, 0x2071, 0x0000, 0x7018,
- 0xd084, 0x00c0, 0x4b9b, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a,
- 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa413, 0x1078,
- 0x4d5b, 0x0078, 0x4be9, 0x127f, 0x0078, 0x4be9, 0xa18c, 0x00ff,
- 0xa186, 0x0017, 0x0040, 0x4bac, 0xa186, 0x001e, 0x0040, 0x4bac,
- 0xa18e, 0x001f, 0x00c0, 0x4bc8, 0x684c, 0xd0cc, 0x0040, 0x4bc8,
- 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4bc8, 0x2009,
- 0x8021, 0x0078, 0x4b2d, 0x6844, 0xa086, 0x0100, 0x00c0, 0x4bc8,
- 0x6868, 0xa005, 0x00c0, 0x4bc8, 0x2009, 0x8020, 0x0078, 0x4b2d,
- 0x2071, 0xa413, 0x1078, 0x4d6f, 0x0040, 0x4be9, 0x2071, 0xa413,
- 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x00c0,
- 0x4be0, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4be0, 0x710e,
- 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100, 0x0040,
- 0x4ca4, 0x127e, 0x2091, 0x8000, 0x2071, 0xa413, 0x7008, 0xa086,
- 0x0001, 0x00c0, 0x4c04, 0x0068, 0x4c04, 0x2009, 0x000d, 0x7030,
- 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006,
- 0x00c0, 0x4c04, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, 0xa413,
- 0x1078, 0x4d6f, 0x0040, 0x4c2f, 0x2071, 0xa534, 0x7084, 0x700a,
- 0x20a9, 0x0020, 0x2099, 0xa535, 0x20a1, 0xa55c, 0x53a3, 0x7087,
- 0x0000, 0x2071, 0xa413, 0x2069, 0xa57c, 0x706c, 0x6826, 0x7070,
- 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, 0x13d1,
- 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa5be, 0x7042, 0x127f,
- 0x0078, 0x4be9, 0x2069, 0xa57c, 0x6808, 0xa08e, 0x0000, 0x0040,
- 0x4c90, 0xa08e, 0x0200, 0x0040, 0x4c8e, 0xa08e, 0x0100, 0x00c0,
- 0x4c90, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8b, 0x2069, 0x0000,
- 0x6818, 0xd084, 0x00c0, 0x4c8b, 0x702c, 0x7130, 0x8108, 0xa102,
- 0x0048, 0x4c59, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078,
- 0x4c63, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4c63, 0x7070,
- 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001,
- 0xa559, 0x2004, 0xa005, 0x00c0, 0x4c82, 0x6934, 0x2069, 0xa534,
- 0x689c, 0x699e, 0x2069, 0xa5be, 0xa102, 0x00c0, 0x4c7b, 0x6844,
- 0xa005, 0x00d0, 0x4c89, 0x2001, 0xa55a, 0x200c, 0x810d, 0x6946,
- 0x0078, 0x4c89, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091,
- 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4c90, 0x7007, 0x0005,
- 0x007c, 0x701c, 0xa06d, 0x0040, 0x4ca2, 0x1078, 0x4d6f, 0x0040,
- 0x4ca2, 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100,
- 0x0040, 0x4ca4, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, 0x00c0,
- 0x4cad, 0x7007, 0x0004, 0x0078, 0x4ccb, 0xa086, 0x0200, 0x00c0,
- 0x4cb3, 0x7007, 0x0005, 0x007c, 0x2001, 0xa57e, 0x2004, 0xa08e,
- 0x0100, 0x00c0, 0x4cc0, 0x7007, 0x0001, 0x1078, 0x4d5b, 0x007c,
- 0xa08e, 0x0000, 0x0040, 0x4cbf, 0xa08e, 0x0200, 0x00c0, 0x4cbf,
- 0x7007, 0x0005, 0x007c, 0x1078, 0x4d25, 0x7006, 0x1078, 0x4d5b,
- 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa534, 0x7184, 0x81ff,
- 0x0040, 0x4cfa, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000,
- 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722a,
- 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722e, 0x8000, 0x0070, 0x4cf7,
- 0x2014, 0x723a, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x723e, 0xa180,
- 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, 0x2071,
- 0xa534, 0x7184, 0x81ff, 0x0040, 0x4d22, 0xa006, 0x7086, 0xae80,
- 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014,
- 0x722a, 0x8000, 0x0070, 0x4d1b, 0x2014, 0x723a, 0x8000, 0x2014,
- 0x723e, 0x0078, 0x4d1f, 0x2001, 0x8020, 0x0078, 0x4d21, 0x2001,
- 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, 0x8108,
- 0xa102, 0x0048, 0x4d32, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
- 0x0078, 0x4d3c, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d3c,
- 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e,
- 0x00c0, 0x4d52, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d55, 0x2001,
- 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, 0x0000,
- 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x700b,
- 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d6e, 0x127e,
- 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005,
- 0x00c0, 0x4d6b, 0x701a, 0x127f, 0x1078, 0x139a, 0x007c, 0x2019,
- 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4d7e, 0x2304, 0x230c,
- 0xa10e, 0x0040, 0x4d7e, 0xa006, 0x0078, 0x4d8e, 0x732c, 0x8319,
- 0x7130, 0xa102, 0x00c0, 0x4d88, 0x2300, 0xa005, 0x0078, 0x4d8e,
- 0x0048, 0x4d8d, 0xa302, 0x0078, 0x4d8e, 0x8002, 0x007c, 0x2d00,
- 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, 0x2091,
- 0x8000, 0x2009, 0xa5d0, 0x2104, 0xc08d, 0x200a, 0x127f, 0x1078,
- 0x13eb, 0x007c, 0x2071, 0xa3e1, 0x7003, 0x0000, 0x7007, 0x0000,
- 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001,
- 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000,
- 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa3e1,
- 0x6848, 0xa005, 0x00c0, 0x4dcb, 0x7028, 0xc085, 0x702a, 0xa085,
- 0x0001, 0x0078, 0x4df0, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858,
- 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840,
- 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c,
- 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376,
- 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006,
- 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa3e1, 0x7004, 0x1079, 0x4e50,
- 0x700c, 0x0079, 0x4dfb, 0x4e00, 0x4df5, 0x4df5, 0x4df5, 0x4df5,
- 0x007c, 0x700c, 0x0079, 0x4e04, 0x4e09, 0x4e4e, 0x4e4e, 0x4e4f,
- 0x4e4f, 0x7830, 0x7930, 0xa106, 0x0040, 0x4e13, 0x7830, 0x7930,
- 0xa106, 0x00c0, 0x4e39, 0x7030, 0xa10a, 0x0040, 0x4e39, 0x00c8,
- 0x4e1b, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4e3a, 0x1078,
- 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001,
- 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, 0x2009,
- 0xa5d0, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, 0x1078,
- 0x13eb, 0x007c, 0x1078, 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a,
- 0x1078, 0x1366, 0x00c0, 0x4e46, 0x0078, 0x4e25, 0x2d00, 0x7086,
- 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4e29, 0x007c, 0x007c,
- 0x4e61, 0x4e62, 0x4e99, 0x4e9a, 0x4e4e, 0x4ed0, 0x4ed5, 0x4f0c,
- 0x4f0d, 0x4f28, 0x4f29, 0x4f2a, 0x4f2b, 0x4f2c, 0x4f2d, 0x4fad,
- 0x4fd7, 0x007c, 0x700c, 0x0079, 0x4e65, 0x4e6a, 0x4e6d, 0x4e7d,
- 0x4e98, 0x4e98, 0x1078, 0x4e01, 0x007c, 0x127e, 0x8001, 0x700e,
- 0x7058, 0x007e, 0x1078, 0x5348, 0x0040, 0x4e7a, 0x2091, 0x8000,
- 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4e86, 0x127e, 0x8001, 0x700e,
- 0x1078, 0x5348, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000,
- 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x00c8,
- 0x4e95, 0x1079, 0x4eb0, 0x127f, 0x007c, 0x127f, 0x1078, 0x4f2e,
- 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa3e1, 0x700c, 0x0079,
- 0x4ea1, 0x4ea6, 0x4ea6, 0x4ea6, 0x4ea8, 0x4eac, 0x0e7f, 0x007c,
- 0x700f, 0x0001, 0x0078, 0x4eae, 0x700f, 0x0002, 0x0e7f, 0x007c,
- 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x5080, 0x4f2e, 0x4f2e, 0x4f2e,
- 0x4f2e, 0x4f2e, 0x4f4a, 0x50ca, 0x5117, 0x5170, 0x5186, 0x4f2e,
- 0x4f2e, 0x4f66, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f87, 0x5245, 0x5263,
- 0x4f2e, 0x4f66, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f7c, 0x5263,
- 0x7020, 0x2068, 0x1078, 0x139a, 0x007c, 0x700c, 0x0079, 0x4ed8,
- 0x4edd, 0x4ee0, 0x4ef0, 0x4f0b, 0x4f0b, 0x1078, 0x4e01, 0x007c,
- 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5348, 0x0040,
- 0x4eed, 0x2091, 0x8000, 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4ef9,
- 0x127e, 0x8001, 0x700e, 0x1078, 0x5348, 0x7058, 0x2068, 0x7084,
- 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
- 0xa08a, 0x001a, 0x00c8, 0x4f08, 0x1079, 0x4f0e, 0x127f, 0x007c,
- 0x127f, 0x1078, 0x4f2e, 0x007c, 0x007c, 0x007c, 0x4f2e, 0x4f4a,
- 0x506a, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a,
- 0x506a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a,
- 0x506a, 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f4a,
- 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, 0x0001,
- 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, 0x8000,
- 0x1078, 0x4982, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
- 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982,
- 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed,
- 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c,
- 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c, 0x6834, 0x8007,
- 0xa084, 0x00ff, 0x0040, 0x4f3c, 0x8001, 0x00c0, 0x4f73, 0x7007,
- 0x0001, 0x0078, 0x5049, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016,
- 0x701a, 0x704b, 0x5049, 0x007c, 0x684c, 0xa084, 0x00c0, 0xa086,
- 0x00c0, 0x00c0, 0x4f87, 0x7007, 0x0001, 0x0078, 0x5280, 0x2d00,
- 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1,
- 0xa40c, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, 0x4f58,
- 0x6884, 0xa08a, 0x0002, 0x00c8, 0x4f58, 0x82ff, 0x00c0, 0x4fa9,
- 0x6888, 0x698c, 0xa105, 0x0040, 0x4fa9, 0x2001, 0x5019, 0x0078,
- 0x4fac, 0xa280, 0x500f, 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040,
- 0x4ff7, 0x1078, 0x1366, 0x00c0, 0x4fb8, 0x7007, 0x000f, 0x007c,
- 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, 0xad00,
- 0x7096, 0x6008, 0xa20a, 0x00c8, 0x4fc7, 0xa00e, 0x2200, 0x7112,
- 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x4fd0, 0xa108,
- 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13d1, 0x7090,
- 0xa08e, 0x0100, 0x0040, 0x4feb, 0xa086, 0x0200, 0x0040, 0x4fe3,
- 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x139a, 0x7014,
- 0x2068, 0x0078, 0x4f58, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807,
- 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x4fad, 0x7014,
- 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x5006, 0x6888,
- 0x698c, 0xa105, 0x0040, 0x5006, 0x1078, 0x501d, 0x6834, 0xa084,
- 0x00ff, 0xa086, 0x001e, 0x0040, 0x5280, 0x0078, 0x5049, 0x5011,
- 0x5015, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005,
- 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, 0x0c7e,
- 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021,
- 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812,
- 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0040,
- 0x503f, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x502c, 0x6004,
- 0xa065, 0x00c0, 0x5026, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f,
- 0x007c, 0x2009, 0xa32e, 0x210c, 0x81ff, 0x00c0, 0x5064, 0x6838,
- 0xa084, 0x00ff, 0x683a, 0x1078, 0x4290, 0x00c0, 0x5058, 0x007c,
- 0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cb8, 0x1078,
- 0x4982, 0x127f, 0x0078, 0x5057, 0x2001, 0x0028, 0x2009, 0x0000,
- 0x0078, 0x5058, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a,
- 0x7010, 0x8001, 0x7012, 0x0040, 0x5079, 0x7007, 0x0006, 0x0078,
- 0x507f, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c,
- 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084,
- 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x50a9, 0x2009,
- 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x50a9, 0xa005,
- 0x00c0, 0x50bc, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501,
- 0x00c0, 0x50bc, 0x067e, 0x6e50, 0x1078, 0x45e7, 0x067f, 0x0078,
- 0x50bc, 0x047e, 0x2011, 0xa30c, 0x2224, 0xc484, 0xc48c, 0x2412,
- 0x047f, 0x0c7e, 0x1078, 0x4501, 0x00c0, 0x50b8, 0x1078, 0x4782,
- 0x8108, 0x00f0, 0x50b2, 0x0c7f, 0x684c, 0xd084, 0x00c0, 0x50c3,
- 0x1078, 0x139a, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982,
- 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x510e, 0x2061, 0xa62d, 0x6100,
- 0xd184, 0x0040, 0x50ee, 0x6858, 0xa084, 0x00ff, 0x00c0, 0x5111,
- 0x6000, 0xd084, 0x0040, 0x510e, 0x6004, 0xa005, 0x00c0, 0x5114,
- 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x510b, 0x2011, 0x0001,
- 0x6860, 0xa005, 0x00c0, 0x50f6, 0x2001, 0x001e, 0x8000, 0x6016,
- 0x6858, 0xa084, 0x00ff, 0x0040, 0x510e, 0x6006, 0x6858, 0x8007,
- 0xa084, 0x00ff, 0x0040, 0x510e, 0x600a, 0x6858, 0x8000, 0x00c0,
- 0x510a, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5337, 0x127f, 0x0078,
- 0x532f, 0x127f, 0x0078, 0x5327, 0x127f, 0x0078, 0x532b, 0x127e,
- 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa352, 0x2004, 0xd0a4,
- 0x0040, 0x516d, 0x2061, 0xa62d, 0x6000, 0xd084, 0x0040, 0x516d,
- 0x6204, 0x6308, 0xd08c, 0x00c0, 0x515f, 0x6c48, 0xa484, 0x0003,
- 0x0040, 0x5145, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x513e,
- 0x2100, 0xa210, 0x0048, 0x516a, 0x0078, 0x5145, 0x8001, 0x00c0,
- 0x516a, 0x2100, 0xa212, 0x0048, 0x516a, 0xa484, 0x000c, 0x0040,
- 0x515f, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0,
- 0x5157, 0x2100, 0xa318, 0x0048, 0x516a, 0x0078, 0x515f, 0xa082,
- 0x0004, 0x00c0, 0x516a, 0x2100, 0xa31a, 0x0048, 0x516a, 0x6860,
- 0xa005, 0x0040, 0x5165, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f,
- 0x0078, 0x5337, 0x127f, 0x0078, 0x5333, 0x127f, 0x0078, 0x532f,
- 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xa62d, 0x6300,
- 0xd38c, 0x00c0, 0x5180, 0x6308, 0x8318, 0x0048, 0x5183, 0x630a,
- 0x127f, 0x0078, 0x5345, 0x127f, 0x0078, 0x5333, 0x127e, 0x0c7e,
- 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, 0x519a,
- 0x0c7e, 0x2061, 0xa62d, 0x6000, 0xa084, 0xfcff, 0x6002, 0x0c7f,
- 0x0078, 0x51c9, 0x6858, 0xa005, 0x0040, 0x51e0, 0x685c, 0xa065,
- 0x0040, 0x51dc, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x51ac,
- 0x1078, 0x8c01, 0x0078, 0x51ba, 0x6013, 0x0400, 0x6037, 0x0000,
- 0x694c, 0xd1a4, 0x0040, 0x51b6, 0x6950, 0x6136, 0x2009, 0x0041,
- 0x1078, 0x756c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x00c0,
- 0x51c9, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, 0x5a6d,
- 0x027f, 0x684c, 0xd0c4, 0x0040, 0x51d8, 0x2061, 0xa62d, 0x6000,
- 0xd08c, 0x00c0, 0x51d8, 0x6008, 0x8000, 0x0048, 0x51dc, 0x600a,
- 0x0c7f, 0x127f, 0x0078, 0x5337, 0x0c7f, 0x127f, 0x0078, 0x532f,
- 0x6954, 0xa186, 0x0045, 0x0040, 0x5213, 0xa186, 0x002a, 0x00c0,
- 0x51f0, 0x2001, 0xa30c, 0x200c, 0xc194, 0x2102, 0x0078, 0x51c9,
- 0xa186, 0x0020, 0x0040, 0x5209, 0xa186, 0x0029, 0x0040, 0x51fc,
- 0xa186, 0x002d, 0x00c0, 0x51dc, 0x6944, 0xa18c, 0xff00, 0x810f,
- 0x1078, 0x4501, 0x00c0, 0x51c9, 0x6000, 0xc0e4, 0x6002, 0x0078,
- 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x2001, 0xa5a1, 0x2004,
- 0x6016, 0x0078, 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x0e7e,
- 0x6860, 0xa075, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x522b,
- 0x1078, 0x8c01, 0x8eff, 0x0040, 0x5228, 0x2e60, 0x1078, 0x8c01,
- 0x0e7f, 0x0078, 0x51c9, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60,
- 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, 0x523c, 0x6007, 0x003b,
- 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x1078, 0x5bf8,
- 0x1078, 0x6109, 0x0e7f, 0x0078, 0x51c9, 0x2061, 0xa62d, 0x6000,
- 0xd084, 0x0040, 0x525f, 0xd08c, 0x00c0, 0x5345, 0x2091, 0x8000,
- 0x6204, 0x8210, 0x0048, 0x5259, 0x6206, 0x2091, 0x8001, 0x0078,
- 0x5345, 0x2091, 0x8001, 0x6853, 0x0016, 0x0078, 0x533e, 0x6853,
- 0x0007, 0x0078, 0x533e, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0,
- 0x526d, 0x1078, 0x4f3c, 0x0078, 0x527f, 0x2030, 0x8001, 0x00c0,
- 0x5277, 0x7007, 0x0001, 0x1078, 0x5280, 0x0078, 0x527f, 0x7007,
- 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5280, 0x007c,
- 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2009, 0xa32e, 0x210c, 0x81ff,
- 0x00c0, 0x530b, 0x2009, 0xa30c, 0x210c, 0xd194, 0x00c0, 0x5315,
- 0x6848, 0x2070, 0xae82, 0xaa00, 0x0048, 0x52fb, 0x2001, 0xa315,
- 0x2004, 0xae02, 0x00c8, 0x52fb, 0x2061, 0xa62d, 0x6100, 0xa184,
- 0x0301, 0xa086, 0x0001, 0x00c0, 0x52de, 0x711c, 0xa186, 0x0006,
- 0x00c0, 0x52e6, 0x7018, 0xa005, 0x0040, 0x530b, 0x2004, 0xd0e4,
- 0x00c0, 0x530f, 0x7024, 0xd0dc, 0x00c0, 0x5319, 0x6853, 0x0000,
- 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x00c0, 0x52ca, 0x7112,
- 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x2e60, 0x1078, 0x59b6, 0x127f,
- 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, 0x00c0, 0x52ca, 0x6902,
- 0x2168, 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x127f, 0x0e7f, 0x007c,
- 0x127f, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x533e, 0xd184, 0x0040,
- 0x52d8, 0xd1c4, 0x00c0, 0x52ff, 0x0078, 0x5303, 0x6944, 0xa18c,
- 0xff00, 0x810f, 0x1078, 0x4501, 0x00c0, 0x530f, 0x6000, 0xd0e4,
- 0x00c0, 0x530f, 0x711c, 0xa186, 0x0007, 0x00c0, 0x52fb, 0x6853,
- 0x0002, 0x0078, 0x5311, 0x6853, 0x0008, 0x0078, 0x5311, 0x6853,
- 0x000e, 0x0078, 0x5311, 0x6853, 0x0017, 0x0078, 0x5311, 0x6853,
- 0x0035, 0x0078, 0x5311, 0x6853, 0x0028, 0x0078, 0x5311, 0x6853,
- 0x0029, 0x127f, 0x0e7f, 0x0078, 0x533e, 0x6853, 0x002a, 0x0078,
- 0x5311, 0x6853, 0x0045, 0x0078, 0x5311, 0x2e60, 0x2019, 0x0002,
- 0x6017, 0x0014, 0x1078, 0x9a6a, 0x127f, 0x0e7f, 0x007c, 0x2009,
- 0x003e, 0x0078, 0x5339, 0x2009, 0x0004, 0x0078, 0x5339, 0x2009,
- 0x0006, 0x0078, 0x5339, 0x2009, 0x0016, 0x0078, 0x5339, 0x2009,
- 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x2091, 0x8000,
- 0x1078, 0x4982, 0x2091, 0x8001, 0x007c, 0x1078, 0x139a, 0x007c,
- 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x5355, 0xa00e, 0x7034,
- 0x7072, 0x7038, 0x7076, 0x0078, 0x5361, 0x7070, 0xa080, 0x0040,
- 0x7072, 0x00c8, 0x5361, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085,
- 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, 0x1078, 0x59ad, 0x0d7f,
- 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012,
- 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00,
- 0xa084, 0x7000, 0x0040, 0x5380, 0xa086, 0x1000, 0x00c0, 0x53ac,
- 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, 0xf000,
- 0xa086, 0x3000, 0x00c0, 0x5390, 0x1078, 0x5570, 0x0078, 0x53a7,
- 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x5397, 0x3e60, 0xac84,
- 0x000f, 0x00c0, 0x53ac, 0xac82, 0xaa00, 0x0048, 0x53ac, 0x6854,
- 0xac02, 0x00c8, 0x53ac, 0x2009, 0x0047, 0x1078, 0x756c, 0x7a1c,
- 0xd284, 0x00c0, 0x5372, 0x007c, 0xa016, 0x1078, 0x15ec, 0x0078,
- 0x53a7, 0x0078, 0x53ac, 0x781c, 0xd08c, 0x0040, 0x53db, 0x157e,
- 0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076,
- 0x00c0, 0x53f1, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x53e0,
- 0x1078, 0x540c, 0x0040, 0x53f1, 0x20e1, 0x3000, 0x7828, 0x7828,
- 0x1078, 0x542a, 0x147f, 0x137f, 0x157f, 0x2009, 0xa5b3, 0x2104,
- 0xa005, 0x00c0, 0x53dc, 0x007c, 0x1078, 0x6109, 0x0078, 0x53db,
- 0xa484, 0x7000, 0x00c0, 0x53f1, 0x1078, 0x540c, 0x0040, 0x5403,
- 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x53cc, 0x0078,
- 0x5403, 0x1078, 0xa1ee, 0xd5a4, 0x0040, 0x53ff, 0x1078, 0x1af7,
- 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5407, 0x1078,
- 0x540c, 0x687f, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f,
- 0x137f, 0x157f, 0x0078, 0x53db, 0xa484, 0x01ff, 0x687e, 0xa005,
- 0x0040, 0x541e, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1,
- 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c,
- 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001,
- 0x0078, 0x541d, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007,
- 0xa196, 0x0000, 0x00c0, 0x5437, 0x0078, 0x567c, 0x007c, 0xa196,
- 0x2000, 0x00c0, 0x5448, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x5444,
- 0x1078, 0x3a43, 0x0078, 0x5436, 0x1078, 0x5450, 0x0078, 0x5436,
- 0xa196, 0x8000, 0x00c0, 0x5436, 0x1078, 0x570c, 0x0078, 0x5436,
- 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040,
- 0x545d, 0xa196, 0x0023, 0x00c0, 0x5568, 0xa08e, 0x0023, 0x00c0,
- 0x5492, 0x1078, 0x57b2, 0x0040, 0x5568, 0x7124, 0x610a, 0x7030,
- 0xa08e, 0x0200, 0x00c0, 0x5476, 0x7034, 0xa005, 0x00c0, 0x5568,
- 0x2009, 0x0015, 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0214,
- 0x0040, 0x547e, 0xa08e, 0x0210, 0x00c0, 0x5484, 0x2009, 0x0015,
- 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0100, 0x00c0, 0x5568,
- 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, 0x0016, 0x1078, 0x756c,
- 0x0078, 0x5568, 0xa08e, 0x0022, 0x00c0, 0x5568, 0x7030, 0xa08e,
- 0x0300, 0x00c0, 0x54a3, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
- 0x0017, 0x0078, 0x5534, 0xa08e, 0x0500, 0x00c0, 0x54af, 0x7034,
- 0xa005, 0x00c0, 0x5568, 0x2009, 0x0018, 0x0078, 0x5534, 0xa08e,
- 0x2010, 0x00c0, 0x54b7, 0x2009, 0x0019, 0x0078, 0x5534, 0xa08e,
- 0x2110, 0x00c0, 0x54bf, 0x2009, 0x001a, 0x0078, 0x5534, 0xa08e,
- 0x5200, 0x00c0, 0x54cb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
- 0x001b, 0x0078, 0x5534, 0xa08e, 0x5000, 0x00c0, 0x54d7, 0x7034,
- 0xa005, 0x00c0, 0x5568, 0x2009, 0x001c, 0x0078, 0x5534, 0xa08e,
- 0x1300, 0x00c0, 0x54df, 0x2009, 0x0034, 0x0078, 0x5534, 0xa08e,
- 0x1200, 0x00c0, 0x54eb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
- 0x0024, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x00c0,
- 0x54f5, 0x2009, 0x002d, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e,
- 0x5300, 0x00c0, 0x54ff, 0x2009, 0x002a, 0x0078, 0x5534, 0xa08e,
- 0x0f00, 0x00c0, 0x5507, 0x2009, 0x0020, 0x0078, 0x5534, 0xa08e,
- 0x5300, 0x00c0, 0x550d, 0x0078, 0x552a, 0xa08e, 0x6104, 0x00c0,
- 0x552a, 0x2011, 0xa88d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8,
- 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x047e, 0x2124,
- 0x1078, 0x3579, 0x047f, 0x8108, 0x00f0, 0x551a, 0x2009, 0x0023,
- 0x0078, 0x5534, 0xa08e, 0x6000, 0x00c0, 0x5532, 0x2009, 0x003f,
- 0x0078, 0x5534, 0x2009, 0x001d, 0x017e, 0x2011, 0xa883, 0x2204,
- 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x556a, 0x1078, 0x4499,
- 0x00c0, 0x556a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x555a, 0x017f,
- 0x017e, 0xa186, 0x0017, 0x00c0, 0x555a, 0x6868, 0xa606, 0x00c0,
- 0x555a, 0x686c, 0xa506, 0xa084, 0xff00, 0x00c0, 0x555a, 0x6000,
- 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x74d7, 0x0040, 0x556d, 0x017f,
- 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x756c,
- 0x0c7f, 0x007c, 0x017f, 0x0078, 0x5568, 0x0c7f, 0x0078, 0x556a,
- 0x0c7e, 0x1078, 0x55d4, 0x00c0, 0x55d2, 0xa184, 0xff00, 0x8007,
- 0xa086, 0x0008, 0x00c0, 0x55d2, 0xa28e, 0x0033, 0x00c0, 0x55a3,
- 0x1078, 0x57b2, 0x0040, 0x55d2, 0x7124, 0x610a, 0x7030, 0xa08e,
- 0x0200, 0x00c0, 0x5595, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009,
- 0x0015, 0x1078, 0x756c, 0x0078, 0x55d2, 0xa08e, 0x0100, 0x00c0,
- 0x55d2, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009, 0x0016, 0x1078,
- 0x756c, 0x0078, 0x55d2, 0xa28e, 0x0032, 0x00c0, 0x55d2, 0x7030,
- 0xa08e, 0x1400, 0x00c0, 0x55d2, 0x2009, 0x0038, 0x017e, 0x2011,
- 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x55d1,
- 0x1078, 0x4499, 0x00c0, 0x55d1, 0x6612, 0x6516, 0x0c7e, 0x1078,
- 0x74d7, 0x0040, 0x55d0, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120,
- 0x610a, 0x017f, 0x1078, 0x756c, 0x1078, 0x6109, 0x0078, 0x55d2,
- 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0d7e, 0x027e, 0x017e,
- 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, 0x2079, 0x0030, 0x2069,
- 0x0200, 0x1078, 0x1c25, 0x00c0, 0x5615, 0x1078, 0x1b15, 0x0040,
- 0x561f, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, 0x00c8, 0x561f,
- 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
- 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, 0xa080,
- 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, 0x10c8, 0x1328, 0x80ac,
- 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828,
- 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, 0x007f, 0x20e0, 0x157f,
- 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, 0x0f7f, 0x007c, 0xa085,
- 0x0001, 0x0078, 0x5615, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130,
- 0xa696, 0x00ff, 0x00c0, 0x5644, 0xa596, 0xfffd, 0x00c0, 0x5634,
- 0x2009, 0x007f, 0x0078, 0x5677, 0xa596, 0xfffe, 0x00c0, 0x563c,
- 0x2009, 0x007e, 0x0078, 0x5677, 0xa596, 0xfffc, 0x00c0, 0x5644,
- 0x2009, 0x0080, 0x0078, 0x5677, 0x2011, 0x0000, 0x2021, 0x0081,
- 0x20a9, 0x007e, 0x2071, 0xa4b5, 0x2e1c, 0x83ff, 0x00c0, 0x5656,
- 0x82ff, 0x00c0, 0x566b, 0x2410, 0x0078, 0x566b, 0x2368, 0x6f10,
- 0x007e, 0x2100, 0xa706, 0x007f, 0x6b14, 0x00c0, 0x5665, 0xa346,
- 0x00c0, 0x5665, 0x2408, 0x0078, 0x5677, 0x87ff, 0x00c0, 0x566b,
- 0x83ff, 0x0040, 0x5650, 0x8420, 0x8e70, 0x00f0, 0x564c, 0x82ff,
- 0x00c0, 0x5676, 0xa085, 0x0001, 0x0078, 0x5678, 0x2208, 0xa006,
- 0x0d7f, 0x0e7f, 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x5681,
- 0x007c, 0x5689, 0x5689, 0x5689, 0x57c8, 0x5689, 0x568a, 0x56a3,
- 0x56f3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x56a2, 0x7120, 0x2160,
- 0xac8c, 0x000f, 0x00c0, 0x56a2, 0xac8a, 0xaa00, 0x0048, 0x56a2,
- 0x6854, 0xac02, 0x00c8, 0x56a2, 0x7124, 0x610a, 0x2009, 0x0046,
- 0x1078, 0x756c, 0x007c, 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x56f1,
- 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0,
- 0x56f1, 0x1078, 0x4499, 0x00c0, 0x56f1, 0x6612, 0x6516, 0x6000,
- 0xd0ec, 0x00c0, 0x56f1, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286,
- 0x0006, 0x00c0, 0x56d6, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040,
- 0x56f1, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122,
- 0x2009, 0x0044, 0x1078, 0x756c, 0x0078, 0x56f1, 0x0c7e, 0x1078,
- 0x74d7, 0x017f, 0x0040, 0x56f1, 0x611a, 0x601f, 0x0004, 0x7120,
- 0x610a, 0xa286, 0x0004, 0x00c0, 0x56e9, 0x6007, 0x0005, 0x0078,
- 0x56eb, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078,
- 0x6109, 0x0c7f, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x570b, 0x7020,
- 0x2060, 0xac84, 0x000f, 0x00c0, 0x570b, 0xac82, 0xaa00, 0x0048,
- 0x570b, 0x6854, 0xac02, 0x00c8, 0x570b, 0x7124, 0x610a, 0x2009,
- 0x0045, 0x1078, 0x756c, 0x007c, 0x7110, 0xa18c, 0xff00, 0x810f,
- 0xa18e, 0x0000, 0x00c0, 0x571c, 0xa084, 0x000f, 0xa08a, 0x0006,
- 0x00c8, 0x571c, 0x1079, 0x571d, 0x007c, 0x5723, 0x5724, 0x5723,
- 0x5723, 0x5794, 0x57a3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x572c,
- 0x702c, 0xd084, 0x0040, 0x5793, 0x700c, 0x7108, 0x1078, 0x24e3,
- 0x00c0, 0x5793, 0x1078, 0x4499, 0x00c0, 0x5793, 0x6612, 0x6516,
- 0x6204, 0x7110, 0xd1bc, 0x0040, 0x575e, 0xa28c, 0x00ff, 0xa186,
- 0x0004, 0x0040, 0x5747, 0xa186, 0x0006, 0x00c0, 0x5784, 0x0c7e,
- 0x1078, 0x57b2, 0x0c7f, 0x0040, 0x5793, 0x0c7e, 0x1078, 0x74d7,
- 0x017f, 0x0040, 0x5793, 0x611a, 0x601f, 0x0002, 0x7120, 0x610a,
- 0x2009, 0x0088, 0x1078, 0x756c, 0x0078, 0x5793, 0xa28c, 0x00ff,
- 0xa186, 0x0006, 0x0040, 0x5773, 0xa186, 0x0004, 0x0040, 0x5773,
- 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, 0x0040, 0x5773, 0xa286,
- 0x0006, 0x00c0, 0x5784, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040,
- 0x5793, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088,
- 0x1078, 0x756c, 0x0078, 0x5793, 0x0c7e, 0x1078, 0x74d7, 0x017f,
- 0x0040, 0x5793, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009,
- 0x0001, 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57a2,
- 0x1078, 0x57b2, 0x0040, 0x57a2, 0x7124, 0x610a, 0x2009, 0x0089,
- 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57b1, 0x1078,
- 0x57b2, 0x0040, 0x57b1, 0x7124, 0x610a, 0x2009, 0x008a, 0x1078,
- 0x756c, 0x007c, 0x7020, 0x2060, 0xac84, 0x000f, 0x00c0, 0x57c5,
- 0xac82, 0xaa00, 0x0048, 0x57c5, 0x2001, 0xa315, 0x2004, 0xac02,
- 0x00c8, 0x57c5, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x57c4,
- 0x7110, 0xd1bc, 0x00c0, 0x57de, 0x7024, 0x2060, 0xac84, 0x000f,
- 0x00c0, 0x57de, 0xac82, 0xaa00, 0x0048, 0x57de, 0x6854, 0xac02,
- 0x00c8, 0x57de, 0x2009, 0x0051, 0x1078, 0x756c, 0x007c, 0x2071,
- 0xa5be, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
- 0x7017, 0xaa00, 0x7007, 0x0000, 0x7026, 0x702b, 0x6c4e, 0x7032,
- 0x7037, 0x6ca0, 0x703b, 0x0002, 0x703f, 0x0000, 0x7043, 0xffff,
- 0x7047, 0xffff, 0x007c, 0x2071, 0xa5be, 0x00e0, 0x58c1, 0x2091,
- 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x5873, 0x700f, 0x0361,
- 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109, 0x713a,
- 0x00c0, 0x5871, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104, 0xa082,
- 0x0003, 0x00c8, 0x5871, 0x703c, 0xa086, 0x0001, 0x00c0, 0x584e,
- 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x582c,
- 0x6803, 0x1000, 0x0078, 0x5833, 0x6804, 0xa084, 0x1000, 0x0040,
- 0x5833, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000, 0x2069,
- 0xa5ab, 0x6804, 0xa082, 0x0006, 0x00c0, 0x5840, 0x6807, 0x0000,
- 0x6830, 0xa082, 0x0003, 0x00c0, 0x5847, 0x6833, 0x0000, 0x1078,
- 0x6109, 0x1078, 0x61d3, 0x0d7f, 0x0078, 0x5871, 0x0d7e, 0x2069,
- 0xa300, 0x6944, 0x6860, 0xa102, 0x00c8, 0x5870, 0x2069, 0xa5ab,
- 0x6804, 0xa086, 0x0000, 0x00c0, 0x5870, 0x6830, 0xa086, 0x0000,
- 0x00c0, 0x5870, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833, 0x0003,
- 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803, 0x0600,
- 0x0d7f, 0x0078, 0x5876, 0x127e, 0x2091, 0x8000, 0x7024, 0xa00d,
- 0x0040, 0x588e, 0x7020, 0x8001, 0x7022, 0x00c0, 0x588e, 0x7023,
- 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x00c0, 0x5889, 0x7028,
- 0x107a, 0x81ff, 0x00c0, 0x588e, 0x7028, 0x107a, 0x7030, 0xa00d,
- 0x0040, 0x589f, 0x702c, 0x8001, 0x702e, 0x00c0, 0x589f, 0x702f,
- 0x0009, 0x8109, 0x7132, 0x00c0, 0x589f, 0x7034, 0x107a, 0x7040,
- 0xa005, 0x0040, 0x58a7, 0x0050, 0x58a7, 0x8001, 0x7042, 0x7044,
- 0xa005, 0x0040, 0x58af, 0x0050, 0x58af, 0x8001, 0x7046, 0x7018,
- 0xa00d, 0x0040, 0x58c0, 0x7008, 0x8001, 0x700a, 0x00c0, 0x58c0,
- 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x58c0, 0x701c, 0x107a,
- 0x127f, 0x7004, 0x0079, 0x58c4, 0x58eb, 0x58ec, 0x5908, 0x0e7e,
- 0x2071, 0xa5be, 0x7018, 0xa005, 0x00c0, 0x58d2, 0x711a, 0x721e,
- 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, 0xa5be,
- 0x701c, 0xa206, 0x00c0, 0x58de, 0x701a, 0x701e, 0x007f, 0x0e7f,
- 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x6088, 0xa102, 0x0048, 0x58e9,
- 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x4501, 0x00c0,
- 0x58fe, 0x6088, 0x8001, 0x0048, 0x58fe, 0x608a, 0x00c0, 0x58fe,
- 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x8108, 0xa182,
- 0x00ff, 0x0048, 0x5906, 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c,
- 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, 0x0040,
- 0x5917, 0x8001, 0x603e, 0x00c0, 0x5917, 0x1078, 0x8cd7, 0x6014,
- 0xa005, 0x0040, 0x5941, 0x8001, 0x6016, 0x00c0, 0x5941, 0x611c,
- 0xa186, 0x0003, 0x0040, 0x5928, 0xa186, 0x0006, 0x00c0, 0x593f,
- 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x593f, 0xa082,
- 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5938, 0x2001, 0x1999,
- 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5941, 0x1078,
- 0x8810, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xca00, 0xa102,
- 0x0048, 0x594e, 0x7017, 0xaa00, 0x7007, 0x0000, 0x007c, 0x0e7e,
- 0x2071, 0xa5be, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, 0x0002,
- 0x0e7f, 0x007c, 0x2001, 0xa5c7, 0x2003, 0x0000, 0x007c, 0x0e7e,
- 0x2071, 0xa5be, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, 0x2011,
- 0xa5ca, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x711a,
- 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, 0x0f7e,
- 0x2079, 0xa300, 0x7a34, 0xd294, 0x0040, 0x59a4, 0x2071, 0xa5aa,
- 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5991, 0xa0fe, 0x0001, 0x0040,
- 0x5995, 0xa0fe, 0x0002, 0x00c0, 0x59a0, 0xa292, 0x0085, 0x0078,
- 0x5997, 0xa292, 0x0005, 0x0078, 0x5997, 0xa292, 0x0002, 0x2272,
- 0x0040, 0x599c, 0x00c8, 0x59a4, 0x2011, 0x8037, 0x1078, 0x3579,
- 0x2011, 0xa5a9, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, 0x007c,
- 0x0c7e, 0x2061, 0xa62d, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa080, 0xa62d, 0x2060, 0x007c, 0x6854, 0xa08a,
- 0x199a, 0x0048, 0x59bd, 0x2001, 0x1999, 0xa005, 0x00c0, 0x59cc,
- 0x0c7e, 0x2061, 0xa62d, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x59d1,
- 0x2001, 0x001e, 0x0078, 0x59d1, 0xa08e, 0xffff, 0x00c0, 0x59d1,
- 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c,
- 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5a24, 0xd0b4, 0x00c0, 0x59e8,
- 0xd0bc, 0x00c0, 0x5a14, 0x2009, 0x0006, 0x1078, 0x5a43, 0x007c,
- 0xd0fc, 0x0040, 0x59f3, 0xa084, 0x0003, 0x0040, 0x59f3, 0xa086,
- 0x0003, 0x00c0, 0x5a3c, 0x6024, 0xd0d4, 0x0040, 0x59fd, 0xc0d4,
- 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa373, 0x2104,
- 0xd084, 0x0040, 0x5a0f, 0x6118, 0xa188, 0x0027, 0x2104, 0xd08c,
- 0x00c0, 0x5a0f, 0x2009, 0x0042, 0x1078, 0x756c, 0x007c, 0x2009,
- 0x0043, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a1f, 0xa084,
- 0x0003, 0x0040, 0x5a1f, 0xa086, 0x0003, 0x00c0, 0x5a3c, 0x2009,
- 0x0042, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a32, 0xa084,
- 0x0003, 0xa08e, 0x0002, 0x0040, 0x5a36, 0x2009, 0x0041, 0x1078,
- 0x756c, 0x007c, 0x1078, 0x5a41, 0x0078, 0x5a31, 0x2009, 0x0043,
- 0x1078, 0x756c, 0x0078, 0x5a31, 0x2009, 0x0004, 0x1078, 0x5a43,
- 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040,
- 0x5a6b, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0,
- 0x5a65, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5a65,
- 0x0c7e, 0x2061, 0xa62d, 0x6200, 0xd28c, 0x00c0, 0x5a64, 0x6204,
- 0x8210, 0x0048, 0x5a64, 0x6206, 0x0c7f, 0x1078, 0x4982, 0x6010,
- 0xa06d, 0x10c0, 0x59b6, 0x0d7f, 0x007c, 0x157e, 0x0c7e, 0x2061,
- 0xa62d, 0x6000, 0x81ff, 0x0040, 0x5a78, 0xa205, 0x0078, 0x5a79,
- 0xa204, 0x6002, 0x0c7f, 0x157f, 0x007c, 0x6800, 0xd08c, 0x00c0,
- 0x5a89, 0x6808, 0xa005, 0x0040, 0x5a89, 0x8001, 0x680a, 0xa085,
- 0x0001, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
- 0x00c8, 0x5a93, 0xa200, 0x00f0, 0x5a8e, 0x8086, 0x818e, 0x007c,
- 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x5ab9, 0xa11a, 0x00c8,
- 0x5ab9, 0x8213, 0x818d, 0x0048, 0x5aac, 0xa11a, 0x00c8, 0x5aad,
- 0x00f0, 0x5aa1, 0x0078, 0x5ab1, 0xa11a, 0x2308, 0x8210, 0x00f0,
- 0x5aa1, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
- 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x5ab5, 0x127e,
- 0x2091, 0x2200, 0x2079, 0xa5ab, 0x127f, 0x0d7e, 0x2069, 0xa5ab,
- 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a,
- 0x0d7f, 0x007c, 0x0c7e, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007,
- 0x0079, 0x5ada, 0x5ae4, 0x5b09, 0x5b64, 0x5aea, 0x5b09, 0x5ae4,
- 0x5ae2, 0x5ae2, 0x1078, 0x1328, 0x1078, 0x595a, 0x1078, 0x6109,
- 0x0c7f, 0x007c, 0x62c0, 0x82ff, 0x00c0, 0x5af0, 0x0c7f, 0x007c,
- 0x2011, 0x4129, 0x1078, 0x58d4, 0x7828, 0xa092, 0x00c8, 0x00c8,
- 0x5aff, 0x8000, 0x782a, 0x1078, 0x4168, 0x0078, 0x5aee, 0x1078,
- 0x4129, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0078,
- 0x5aee, 0x1078, 0x595a, 0x3c00, 0x007e, 0x2011, 0x0209, 0x20e1,
- 0x4000, 0x2214, 0x007f, 0x20e0, 0x82ff, 0x0040, 0x5b27, 0x62c0,
- 0x82ff, 0x00c0, 0x5b27, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040,
- 0x1328, 0x2009, 0x0013, 0x1078, 0x756c, 0x0c7f, 0x007c, 0x3900,
- 0xa082, 0xa6cd, 0x00c8, 0x5b2e, 0x1078, 0x728a, 0x0c7e, 0x7824,
- 0xa065, 0x1040, 0x1328, 0x7804, 0xa086, 0x0004, 0x0040, 0x5ba9,
- 0x7828, 0xa092, 0x2710, 0x00c8, 0x5b44, 0x8000, 0x782a, 0x0c7f,
- 0x1078, 0x6c33, 0x0078, 0x5b25, 0x6104, 0xa186, 0x0003, 0x00c0,
- 0x5b5b, 0x0e7e, 0x2071, 0xa300, 0x70d4, 0x0e7f, 0xd08c, 0x0040,
- 0x5b5b, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0xa300, 0x1078,
- 0x4171, 0x0e7f, 0x0c7f, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078,
- 0x756c, 0x0c7f, 0x0078, 0x5b25, 0x2001, 0xa5c7, 0x2003, 0x0000,
- 0x62c0, 0x82ff, 0x00c0, 0x5b78, 0x782b, 0x0000, 0x7824, 0xa065,
- 0x1040, 0x1328, 0x2009, 0x0013, 0x1078, 0x75c3, 0x0c7f, 0x007c,
- 0x0c7e, 0x0d7e, 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x5b81, 0x1078,
- 0x728a, 0x7824, 0xa005, 0x1040, 0x1328, 0x781c, 0xa06d, 0x1040,
- 0x1328, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x1078, 0x753d,
- 0x693c, 0x81ff, 0x1040, 0x1328, 0x8109, 0x693e, 0x6854, 0xa015,
- 0x0040, 0x5b9d, 0x7a1e, 0x0078, 0x5b9f, 0x7918, 0x791e, 0x7807,
- 0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, 0x1078, 0x6109, 0x0078,
- 0x5b76, 0x6104, 0xa186, 0x0002, 0x0040, 0x5bb4, 0xa186, 0x0004,
- 0x0040, 0x5bb4, 0x0078, 0x5b38, 0x7808, 0xac06, 0x0040, 0x5b38,
- 0x1078, 0x6010, 0x1078, 0x5c45, 0x0c7f, 0x1078, 0x6109, 0x0078,
- 0x5b25, 0x0c7e, 0x6027, 0x0002, 0x62c8, 0x82ff, 0x00c0, 0x5bdb,
- 0x62c4, 0x82ff, 0x00c0, 0x5bdb, 0x793c, 0xa1e5, 0x0000, 0x0040,
- 0x5bd5, 0x2009, 0x0049, 0x1078, 0x756c, 0x2011, 0xa5ca, 0x2013,
- 0x0000, 0x0c7f, 0x007c, 0x3908, 0xa192, 0xa6cd, 0x00c8, 0x5be2,
- 0x1078, 0x728a, 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5bd5,
- 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5bf4,
- 0x6017, 0x0012, 0x0078, 0x5bd9, 0x6017, 0x0016, 0x0078, 0x5bd9,
- 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000,
- 0x2c08, 0x2061, 0xa5ab, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
- 0x0040, 0x5c13, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f,
- 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x5c0e, 0x0d7e,
- 0x2069, 0xa5ab, 0x6000, 0xd0d4, 0x0040, 0x5c2c, 0x6820, 0x8000,
- 0x6822, 0xa086, 0x0001, 0x00c0, 0x5c27, 0x2c00, 0x681e, 0x6804,
- 0xa084, 0x0007, 0x0079, 0x6111, 0xc0d5, 0x6002, 0x6818, 0xa005,
- 0x0040, 0x5c3e, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00, 0x681a,
- 0x0d7f, 0x685a, 0x2069, 0xa5ab, 0x0078, 0x5c1e, 0x6056, 0x605a,
- 0x2c00, 0x681a, 0x681e, 0x0078, 0x5c1e, 0x007e, 0x017e, 0x0c7e,
- 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xa5ab,
- 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x5c60, 0xa080,
- 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c,
- 0x610e, 0x610a, 0x0078, 0x5c5b, 0x0c7e, 0x600f, 0x0000, 0x2c08,
- 0x2061, 0xa5ab, 0x6034, 0xa005, 0x0040, 0x5c74, 0xa080, 0x0003,
- 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078, 0x5c72,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x017e, 0x007e,
- 0x127e, 0x2071, 0xa5ab, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000,
- 0x8cff, 0x0040, 0x5ced, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
- 0x00c0, 0x5ce8, 0x87ff, 0x0040, 0x5c99, 0x6020, 0xa106, 0x00c0,
- 0x5ce8, 0x703c, 0xac06, 0x00c0, 0x5cab, 0x037e, 0x2019, 0x0001,
- 0x1078, 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
- 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x5cb1, 0x660c,
- 0x763a, 0x7034, 0xac36, 0x00c0, 0x5cbf, 0x2c00, 0xaf36, 0x0040,
- 0x5cbd, 0x2f00, 0x7036, 0x0078, 0x5cbf, 0x7037, 0x0000, 0x660c,
- 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5cc8, 0x7e0e, 0x0078, 0x5cc9,
- 0x2678, 0x600f, 0x0000, 0x1078, 0x8a44, 0x0040, 0x5ce3, 0x6010,
- 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5cf7, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078,
- 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5c88,
- 0x2c78, 0x600c, 0x2060, 0x0078, 0x5c88, 0x127f, 0x007f, 0x017f,
- 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c,
- 0xa086, 0x0006, 0x00c0, 0x5cd6, 0x1078, 0xa181, 0x1078, 0x9e70,
- 0x0078, 0x5ce3, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031,
- 0x0000, 0x127e, 0x2091, 0x8000, 0x2079, 0xa5ab, 0x7838, 0xa065,
- 0x0040, 0x5d41, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06,
- 0x00c0, 0x5d28, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x7833,
- 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x037f,
- 0x1078, 0x8a44, 0x0040, 0x5d3c, 0x6010, 0x2068, 0x601c, 0xa086,
- 0x0003, 0x00c0, 0x5d4a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
- 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x007f, 0x0078,
- 0x5d0f, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f,
- 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5d33, 0x1078,
- 0x9e70, 0x0078, 0x5d3c, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000,
- 0x1078, 0x5d6d, 0x1078, 0x5e21, 0x087f, 0x027f, 0x017f, 0x007c,
- 0x0f7e, 0x127e, 0x2079, 0xa5ab, 0x2091, 0x8000, 0x1078, 0x5ebc,
- 0x1078, 0x5f32, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
- 0x0c7e, 0x067e, 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
- 0xa5ab, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5e01, 0x6018,
- 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5dfc, 0x88ff, 0x0040,
- 0x5d8d, 0x6020, 0xa106, 0x00c0, 0x5dfc, 0x7024, 0xac06, 0x00c0,
- 0x5dbd, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x5db8, 0x1078,
- 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027,
- 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040,
- 0x5dad, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
- 0xd084, 0x0040, 0x5db5, 0x6827, 0x0001, 0x037f, 0x0078, 0x5dbd,
- 0x6003, 0x0009, 0x630a, 0x0078, 0x5dfc, 0x7014, 0xac36, 0x00c0,
- 0x5dc3, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5dd1, 0x2c00,
- 0xaf36, 0x0040, 0x5dcf, 0x2f00, 0x7012, 0x0078, 0x5dd1, 0x7013,
- 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5dda, 0x7e0e,
- 0x0078, 0x5ddb, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x5df5, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e0a,
- 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078,
- 0xa181, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078,
- 0x7045, 0x0c7f, 0x0078, 0x5d7c, 0x2c78, 0x600c, 0x2060, 0x0078,
- 0x5d7c, 0x127f, 0x007f, 0x017f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f,
- 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5e15, 0x1078,
- 0xa181, 0x1078, 0x9e70, 0x0078, 0x5df5, 0x601c, 0xa086, 0x0002,
- 0x00c0, 0x5df5, 0x6004, 0xa086, 0x0085, 0x0040, 0x5de8, 0x0078,
- 0x5df5, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0xa434,
- 0x2004, 0xa065, 0x0040, 0x5eb8, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e,
- 0x2071, 0xa5ab, 0x6654, 0x7018, 0xac06, 0x00c0, 0x5e38, 0x761a,
- 0x701c, 0xac06, 0x00c0, 0x5e44, 0x86ff, 0x00c0, 0x5e43, 0x7018,
- 0x701e, 0x0078, 0x5e44, 0x761e, 0x6058, 0xa07d, 0x0040, 0x5e49,
- 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x5e4f, 0x2f00, 0x685a, 0x6057,
- 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078,
- 0x4410, 0x0040, 0x5eb4, 0x7624, 0x86ff, 0x0040, 0x5ea2, 0xa680,
- 0x0004, 0x2004, 0xad06, 0x00c0, 0x5ea2, 0x0d7e, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0040, 0x5e99, 0x1078, 0x595a, 0x1078, 0x6c41,
- 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5e82, 0x6803, 0x0100,
- 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5e8a,
- 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040,
- 0x5e93, 0x8001, 0x603e, 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078,
- 0x5ea2, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f,
- 0x0078, 0x5e57, 0x8dff, 0x0040, 0x5eb0, 0x6837, 0x0103, 0x6b4a,
- 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078, 0x4982,
- 0x1078, 0x7045, 0x0078, 0x5e57, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e,
- 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x5f16, 0x600c, 0x007e,
- 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x5efb, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0040, 0x5ef5, 0x1078, 0x595a, 0x1078, 0x6c41,
- 0x68c3, 0x0000, 0x1078, 0x7188, 0x7827, 0x0000, 0x037e, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5eea, 0x6803, 0x0100,
- 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ef2,
- 0x6827, 0x0001, 0x037f, 0x0078, 0x5efb, 0x6003, 0x0009, 0x630a,
- 0x2c30, 0x0078, 0x5f13, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040,
- 0x5f0f, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5f1d, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078,
- 0x8c01, 0x1078, 0x7045, 0x007f, 0x0078, 0x5ec3, 0x7e16, 0x7e12,
- 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006,
- 0x00c0, 0x5f26, 0x1078, 0x9e70, 0x0078, 0x5f0f, 0x601c, 0xa086,
- 0x0002, 0x00c0, 0x5f0f, 0x6004, 0xa086, 0x0085, 0x0040, 0x5f06,
- 0x0078, 0x5f0f, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065,
- 0x0040, 0x5fa0, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000,
- 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x4410, 0x0040, 0x5f9d,
- 0x7e24, 0x86ff, 0x0040, 0x5f8f, 0xa680, 0x0004, 0x2004, 0xad06,
- 0x00c0, 0x5f8f, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040,
- 0x5f86, 0x1078, 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078,
- 0x7188, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384,
- 0x1000, 0x0040, 0x5f6f, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
- 0x0100, 0x6824, 0xd084, 0x0040, 0x5f77, 0x6827, 0x0001, 0x037f,
- 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5f80, 0x8001, 0x603e,
- 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5f8f, 0x0d7f, 0x0c7e,
- 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x5f44, 0x8dff,
- 0x0040, 0x5f99, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
- 0x4982, 0x1078, 0x7045, 0x0078, 0x5f44, 0x007f, 0x0078, 0x5f37,
- 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e,
- 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x5fc4, 0x604c, 0xa06d,
- 0x0040, 0x5fc4, 0x6848, 0xa606, 0x00c0, 0x5fc4, 0x2071, 0xa5ab,
- 0x7024, 0xa035, 0x0040, 0x5fc4, 0xa080, 0x0004, 0x2004, 0xad06,
- 0x00c0, 0x5fc4, 0x1078, 0x5fc8, 0x067f, 0x0d7f, 0x0e7f, 0x007c,
- 0x0f7e, 0x2079, 0x0100, 0x78c0, 0xa005, 0x00c0, 0x5fd7, 0x0c7e,
- 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x600e, 0x1078,
- 0x6c41, 0x78c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e,
- 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0040, 0x5feb, 0x7803,
- 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0040,
- 0x5ff3, 0x7827, 0x0001, 0x1078, 0x7188, 0x037f, 0x1078, 0x4410,
- 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5fff, 0x8001, 0x603e, 0x2660,
- 0x1078, 0x753d, 0x0c7f, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
- 0x1078, 0x8cb8, 0x1078, 0x4982, 0x1078, 0x7045, 0x0f7f, 0x007c,
- 0x0e7e, 0x0c7e, 0x2071, 0xa5ab, 0x7004, 0xa084, 0x0007, 0x0079,
- 0x6019, 0x6023, 0x6026, 0x603f, 0x605b, 0x60a0, 0x6023, 0x6023,
- 0x6021, 0x1078, 0x1328, 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065,
- 0x0040, 0x6034, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0040,
- 0x603b, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000,
- 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x6034, 0x6018,
- 0x2060, 0x1078, 0x4410, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001,
- 0x7022, 0x0040, 0x6050, 0x6054, 0xa015, 0x0040, 0x6057, 0x721e,
- 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218,
- 0x721e, 0x0078, 0x6050, 0x7024, 0xa065, 0x0040, 0x609d, 0x700c,
- 0xac06, 0x00c0, 0x6072, 0x1078, 0x7045, 0x600c, 0xa015, 0x0040,
- 0x606e, 0x720e, 0x600f, 0x0000, 0x0078, 0x609b, 0x720e, 0x720a,
- 0x0078, 0x609b, 0x7014, 0xac06, 0x00c0, 0x6085, 0x1078, 0x7045,
- 0x600c, 0xa015, 0x0040, 0x6081, 0x7216, 0x600f, 0x0000, 0x0078,
- 0x609b, 0x7216, 0x7212, 0x0078, 0x609b, 0x6018, 0x2060, 0x1078,
- 0x4410, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7045, 0x701c, 0xa065,
- 0x0040, 0x609b, 0x6054, 0xa015, 0x0040, 0x6099, 0x721e, 0x0078,
- 0x609b, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
- 0x7024, 0xa065, 0x0040, 0x60ad, 0x1078, 0x7045, 0x600c, 0xa015,
- 0x0040, 0x60b4, 0x720e, 0x600f, 0x0000, 0x1078, 0x7188, 0x7027,
- 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, 0x60ad,
- 0x0d7e, 0x2069, 0xa5ab, 0x6830, 0xa084, 0x0003, 0x0079, 0x60c0,
- 0x60c6, 0x60c8, 0x60ee, 0x60c6, 0x1078, 0x1328, 0x0d7f, 0x007c,
- 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x60e4, 0x683c, 0xa065,
- 0x0040, 0x60d9, 0x600c, 0xa015, 0x0040, 0x60e0, 0x6a3a, 0x600f,
- 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, 0x007c,
- 0x683a, 0x6836, 0x0078, 0x60d9, 0x6843, 0x0000, 0x6838, 0xa065,
- 0x0040, 0x60d9, 0x6003, 0x0003, 0x0078, 0x60d9, 0x0c7e, 0x6843,
- 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x6106, 0x600c,
- 0xa015, 0x0040, 0x6102, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
- 0x0078, 0x6106, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f,
- 0x007c, 0x0d7e, 0x2069, 0xa5ab, 0x6804, 0xa084, 0x0007, 0x0079,
- 0x6111, 0x611b, 0x61c2, 0x61c2, 0x61c2, 0x61c2, 0x61c4, 0x61c2,
- 0x6119, 0x1078, 0x1328, 0x6820, 0xa005, 0x00c0, 0x6121, 0x0d7f,
- 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x6130, 0x6807, 0x0004,
- 0x6826, 0x682b, 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c,
- 0x6814, 0xa065, 0x0040, 0x613e, 0x6807, 0x0001, 0x6826, 0x682b,
- 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e,
- 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x61bd, 0x704c, 0xa00d, 0x0040,
- 0x614d, 0x7088, 0xa005, 0x0040, 0x6165, 0x7054, 0xa075, 0x0040,
- 0x6156, 0xa20e, 0x0040, 0x61bd, 0x0078, 0x615b, 0x6818, 0xa20e,
- 0x0040, 0x61bd, 0x2070, 0x704c, 0xa00d, 0x0040, 0x614d, 0x7088,
- 0xa005, 0x00c0, 0x614d, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302,
- 0x00c8, 0x614d, 0x1078, 0x750c, 0x0040, 0x61bd, 0x8318, 0x733e,
- 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff,
- 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004,
- 0xa08a, 0x199a, 0x0048, 0x6186, 0x2001, 0x1999, 0x8003, 0x801b,
- 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc,
- 0x0040, 0x619f, 0x7100, 0xd1f4, 0x0040, 0x619b, 0x7114, 0xa18c,
- 0x00ff, 0x0078, 0x61a4, 0x2009, 0x0000, 0x0078, 0x61a4, 0xa1e0,
- 0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078,
- 0x679b, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26,
- 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040,
- 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f,
- 0x0078, 0x61bb, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040,
- 0x61d0, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x620a,
- 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa5ab, 0x6830,
- 0xa086, 0x0000, 0x00c0, 0x61f1, 0x6838, 0xa07d, 0x0040, 0x61f1,
- 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091,
- 0x2200, 0x027f, 0x1078, 0x1d28, 0x00c0, 0x61f4, 0x127f, 0x1078,
- 0x6ae5, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803,
- 0x0002, 0x780c, 0xa015, 0x0040, 0x6206, 0x6a3a, 0x780f, 0x0000,
- 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x61f1, 0x683a, 0x6836,
- 0x0078, 0x6200, 0x601c, 0xa084, 0x000f, 0x1079, 0x6210, 0x007c,
- 0x6219, 0x621e, 0x663f, 0x6758, 0x621e, 0x663f, 0x6758, 0x6219,
- 0x621e, 0x1078, 0x6010, 0x1078, 0x6109, 0x007c, 0x157e, 0x137e,
- 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, 0x10c8, 0x1328,
- 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x623b, 0x7900, 0xd1f4,
- 0x0040, 0x6237, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x6240, 0x2009,
- 0x0000, 0x0078, 0x6240, 0xa1f8, 0x293f, 0x2f0c, 0xa18c, 0x00ff,
- 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x00c8, 0x6292,
- 0x1079, 0x6250, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c,
- 0x62f8, 0x6340, 0x6368, 0x6403, 0x6433, 0x643b, 0x6462, 0x6473,
- 0x6484, 0x648c, 0x64a4, 0x648c, 0x650f, 0x6473, 0x6530, 0x6538,
- 0x6484, 0x6538, 0x6549, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290,
- 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6d05, 0x6d2a,
- 0x6d3f, 0x6d62, 0x6d83, 0x6462, 0x6290, 0x6462, 0x648c, 0x6290,
- 0x6368, 0x6403, 0x6290, 0x72ac, 0x648c, 0x6290, 0x72cc, 0x648c,
- 0x6290, 0x6290, 0x62f3, 0x62a1, 0x6290, 0x72f1, 0x7368, 0x7450,
- 0x6290, 0x7461, 0x645c, 0x747d, 0x6290, 0x6d98, 0x6290, 0x6290,
- 0x1078, 0x1328, 0x2100, 0x1079, 0x629b, 0x0f7f, 0x0c7f, 0x147f,
- 0x137f, 0x157f, 0x007c, 0x629f, 0x629f, 0x629f, 0x62d5, 0x1078,
- 0x1328, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6567, 0x7810, 0x2068,
- 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x0d7e, 0x7818,
- 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x62d2, 0xa085, 0x0001,
- 0x0d7f, 0x007c, 0xa006, 0x0078, 0x62d0, 0x0d7e, 0x20a1, 0x020b,
- 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8,
- 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814,
- 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x1078,
- 0x6c2d, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x5200, 0x20a3, 0x0000,
- 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd084, 0x0040, 0x6312, 0x6828,
- 0x20a3, 0x0000, 0x017e, 0x1078, 0x24fa, 0x21a2, 0x017f, 0x0d7f,
- 0x0078, 0x6317, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9,
- 0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301,
- 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048,
- 0x6331, 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078,
- 0x6337, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048, 0x6358,
- 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078, 0x635e,
- 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004,
- 0x2099, 0xa305, 0x53a6, 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x6567, 0x0c7e, 0x7818, 0x2060, 0x2001,
- 0x0000, 0x1078, 0x48a2, 0x0c7f, 0x7818, 0xa080, 0x0028, 0x2004,
- 0xa086, 0x007e, 0x00c0, 0x6383, 0x20a3, 0x0400, 0x620c, 0xc2b4,
- 0x620e, 0x0078, 0x6385, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x63d2, 0x2099,
- 0xa58c, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff,
- 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xa305, 0x53a6,
- 0x20a9, 0x0004, 0x2099, 0xa301, 0x53a6, 0x20a9, 0x0010, 0x20a3,
- 0x0000, 0x00f0, 0x63af, 0x2099, 0xa594, 0x3304, 0xc0dd, 0x20a2,
- 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040, 0x63ca, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004,
- 0x0078, 0x63cc, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0, 0x63cc,
- 0x0078, 0x63f2, 0x2099, 0xa58c, 0x20a9, 0x0008, 0x53a6, 0x20a9,
- 0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301,
- 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e3, 0x20a9,
- 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e9, 0x2099, 0xa594, 0x20a9,
- 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63f4,
- 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x63fa, 0x60c3, 0x0074,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
- 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006,
- 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351,
- 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x641f, 0xa085, 0x0020, 0xd1a4,
- 0x0040, 0x6424, 0xa085, 0x0010, 0xa085, 0x0002, 0x0d7e, 0x0078,
- 0x64ed, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
- 0x5000, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
- 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0014, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65ef,
- 0x0078, 0x6466, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3,
- 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
- 0x0008, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8,
- 0x20a3, 0x0200, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x65f8,
- 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0040, 0x649b,
- 0x20a2, 0x0078, 0x649d, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3,
- 0x0008, 0x1078, 0x6c2d, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
- 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818,
- 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x64ca, 0x6998, 0xa184,
- 0xc000, 0x00c0, 0x64c6, 0xd1ec, 0x0040, 0x64c2, 0x20a3, 0x2100,
- 0x0078, 0x64cc, 0x20a3, 0x0100, 0x0078, 0x64cc, 0x20a3, 0x0400,
- 0x0078, 0x64cc, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2,
- 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351, 0x7904, 0x0f7f, 0xd1ac,
- 0x00c0, 0x64dc, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x64e1, 0xa085,
- 0x0010, 0x2009, 0xa373, 0x210c, 0xd184, 0x0040, 0x64eb, 0x699c,
- 0xd18c, 0x0040, 0x64ed, 0xa085, 0x0002, 0x027e, 0x2009, 0xa371,
- 0x210c, 0xd1e4, 0x0040, 0x64fb, 0xc0c5, 0xa094, 0x0030, 0xa296,
- 0x0010, 0x0040, 0x6505, 0xd1ec, 0x0040, 0x6505, 0xa094, 0x0030,
- 0xa296, 0x0010, 0x0040, 0x6505, 0xc0bd, 0x027f, 0x20a2, 0x20a2,
- 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1,
- 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x0078, 0x62fe,
- 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6c2d,
- 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078,
- 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3,
- 0x0000, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x027e, 0x037e,
- 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, 0x656e, 0x027e,
- 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e,
- 0x00c0, 0x6581, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x0078,
- 0x65b6, 0xa286, 0x007f, 0x00c0, 0x658d, 0x0d7e, 0xa385, 0x00ff,
- 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x65a4, 0xd2bc, 0x0040, 0x65ac,
- 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x659c, 0xa385, 0x00ff, 0x20a2,
- 0x20a3, 0xfffc, 0x0078, 0x65a4, 0xa2e8, 0xa434, 0x2d6c, 0x6810,
- 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
- 0x2da6, 0x0d7f, 0x0078, 0x65ba, 0x0d7e, 0xa2e8, 0xa434, 0x2d6c,
- 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, 0x037f, 0x20a3,
- 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
- 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc,
- 0x22a2, 0x0d7e, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
- 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x65c1, 0x20a3, 0x0100,
- 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x007c, 0x027e,
- 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, 0x0078, 0x65ff,
- 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092,
- 0x007e, 0x0048, 0x661c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
- 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
- 0x2da6, 0x0d7f, 0x0078, 0x662a, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x047f,
- 0x037f, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
- 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e,
- 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c,
- 0x10c8, 0x1328, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x665d,
- 0x7900, 0xd1f4, 0x0040, 0x6659, 0x7914, 0xa18c, 0x00ff, 0x0078,
- 0x6662, 0x2009, 0x0000, 0x0078, 0x6662, 0xa1f8, 0x293f, 0x2f0c,
- 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085,
- 0x1079, 0x666d, 0x0f7f, 0x0c7f, 0x007c, 0x6676, 0x6681, 0x669c,
- 0x6674, 0x6674, 0x6674, 0x6676, 0x1078, 0x1328, 0x147e, 0x20a1,
- 0x020b, 0x1078, 0x66af, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f,
- 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x66e3, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
- 0x1078, 0x6c2d, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078,
- 0x6724, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0004, 0x1078, 0x6c2d, 0x147f, 0x007c, 0x027e,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
- 0xa092, 0x007e, 0x0048, 0x66ce, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a,
- 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x66dd, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
- 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3,
- 0x0000, 0x0078, 0x65c1, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6702,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
- 0x0078, 0x6711, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085,
- 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230,
- 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2,
- 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048,
- 0x6743, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8500,
- 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6,
- 0x0d7f, 0x0078, 0x6752, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
- 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x0078, 0x6715,
- 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x1048, 0x1328,
- 0xa08a, 0x0053, 0x10c8, 0x1328, 0x7918, 0x2160, 0x61a0, 0xd1bc,
- 0x0040, 0x6777, 0x6100, 0xd1f4, 0x0040, 0x6773, 0x6114, 0xa18c,
- 0x00ff, 0x0078, 0x677c, 0x2009, 0x0000, 0x0078, 0x677c, 0xa1e0,
- 0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082,
- 0x0040, 0x1079, 0x6786, 0x0f7f, 0x0c7f, 0x007c, 0x679b, 0x68a9,
- 0x684a, 0x6a59, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799,
- 0x6799, 0x6f5e, 0x6f6f, 0x6f80, 0x6f91, 0x6799, 0x748e, 0x6799,
- 0x6f4d, 0x1078, 0x1328, 0x0d7e, 0x157e, 0x147e, 0x780b, 0xffff,
- 0x20a1, 0x020b, 0x1078, 0x6806, 0x7910, 0x2168, 0x6948, 0x7922,
- 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f,
- 0x00c0, 0x67b6, 0x2001, 0x0005, 0x0078, 0x67c0, 0xd184, 0x0040,
- 0x67bd, 0x2001, 0x0004, 0x0078, 0x67c0, 0xa084, 0x0006, 0x8004,
- 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, 0xa105, 0x017f,
- 0x20a2, 0xd1ac, 0x0040, 0x67d0, 0x20a3, 0x0002, 0x0078, 0x67dc,
- 0xd1b4, 0x0040, 0x67d7, 0x20a3, 0x0001, 0x0078, 0x67dc, 0x20a3,
- 0x0000, 0x2230, 0x0078, 0x67de, 0x6a80, 0x6e7c, 0x20a9, 0x0008,
- 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x67e2,
- 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084,
- 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa5c7, 0x2003, 0x07d0,
- 0x2001, 0xa5c6, 0x2003, 0x0009, 0x2001, 0xa5cc, 0x2003, 0x0002,
- 0x1078, 0x157e, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294,
- 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc,
- 0x0040, 0x682c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085,
- 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
- 0x2da6, 0x0d7f, 0x0078, 0x683b, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3,
- 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2,
- 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
- 0x1078, 0x686a, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2,
- 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
- 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x147f, 0x137f, 0x157f,
- 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6888, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2,
- 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6897,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
- 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
- 0x0889, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
- 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
- 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, 0xa06d, 0x1078,
- 0x488f, 0x0040, 0x68bd, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020,
- 0x00c0, 0x68bd, 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078,
- 0x6a12, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
- 0xa084, 0xf000, 0x00c0, 0x68d4, 0x7810, 0xa084, 0x0700, 0x8007,
- 0x1079, 0x68dc, 0x0078, 0x68d7, 0xa006, 0x1079, 0x68dc, 0x147f,
- 0x137f, 0x157f, 0x0d7f, 0x007c, 0x68e6, 0x697e, 0x6989, 0x69b3,
- 0x69c7, 0x69e3, 0x69ee, 0x68e4, 0x1078, 0x1328, 0x017e, 0x037e,
- 0x694c, 0xa18c, 0x0003, 0x0040, 0x68f1, 0xa186, 0x0003, 0x00c0,
- 0x6900, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x68f7, 0xc3e5, 0x23a2,
- 0x6868, 0x20a2, 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x69be,
- 0xa186, 0x0001, 0x10c0, 0x1328, 0x6b78, 0x7824, 0xd0cc, 0x0040,
- 0x690a, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
- 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
- 0x0300, 0x0040, 0x6978, 0xd3c4, 0x0040, 0x6920, 0x687c, 0xa108,
- 0xd3cc, 0x0040, 0x6925, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d,
- 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x692a,
- 0x157f, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6978,
- 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6958, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
- 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6967,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f,
- 0x7b24, 0xd3cc, 0x0040, 0x6970, 0x20a3, 0x0889, 0x0078, 0x6972,
- 0x20a3, 0x0898, 0x20a2, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
- 0x61c2, 0x037f, 0x017f, 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008,
- 0x7824, 0xd0cc, 0x0040, 0x6985, 0xc2e5, 0x22a2, 0xa016, 0x0078,
- 0x69bc, 0x2011, 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6990, 0xc2e5,
- 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2,
- 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000,
- 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3,
- 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032,
- 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040,
- 0x69ba, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
- 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x007c, 0x2011,
- 0x0100, 0x7824, 0xd0cc, 0x0040, 0x69ce, 0xc2e5, 0x22a2, 0xa016,
- 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2,
- 0x7834, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020,
- 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040,
- 0x69ea, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x69bc, 0x037e, 0x7b10,
- 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6a01,
- 0x7824, 0xd0cc, 0x0040, 0x69fd, 0xc2e5, 0x22a2, 0x037f, 0x0078,
- 0x69bc, 0x047e, 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f,
- 0x0040, 0x6a0b, 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f,
- 0x0078, 0x69be, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a30, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
- 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a3f,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824,
- 0xd0cc, 0x0040, 0x6a47, 0x20a3, 0x0889, 0x0078, 0x6a49, 0x20a3,
- 0x0898, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
- 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
- 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810,
- 0xa084, 0x0700, 0x8007, 0x1079, 0x6a6c, 0x037f, 0x017f, 0x147f,
- 0x137f, 0x157f, 0x0d7f, 0x007c, 0x6a74, 0x6a74, 0x6a76, 0x6a74,
- 0x6a74, 0x6a74, 0x6a9b, 0x6a74, 0x1078, 0x1328, 0x7910, 0xa18c,
- 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
- 0x1078, 0x6aa5, 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd0bc, 0x0040,
- 0x6a90, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6a92,
- 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078,
- 0x6aa5, 0x20a3, 0x7f00, 0x0078, 0x6a93, 0x027e, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040,
- 0x6ac3, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0100,
- 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6,
- 0x0d7f, 0x0078, 0x6ad2, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
- 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078,
- 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e,
- 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0xa300, 0x6130,
- 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6afc, 0x6910,
- 0x6a14, 0x6430, 0x0078, 0x6b00, 0x6910, 0x6a14, 0x7368, 0x746c,
- 0x781c, 0xa086, 0x0006, 0x0040, 0x6b5f, 0xd5bc, 0x0040, 0x6b10,
- 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6b17,
- 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073,
- 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
- 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
- 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
- 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
- 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6b49, 0x6a00, 0xd2f4,
- 0x0040, 0x6b47, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6b49, 0x2011,
- 0x0000, 0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084,
- 0xfff0, 0xa005, 0x0040, 0x6b56, 0x2009, 0x1b58, 0x1078, 0x595f,
- 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810,
- 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6bb7,
- 0xd5bc, 0x0040, 0x6b73, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
- 0x646e, 0x0078, 0x6b7a, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b,
- 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
- 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
- 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
- 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080,
- 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
- 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6bb2, 0x6a00,
- 0xd2f4, 0x0040, 0x6bb0, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6bb2,
- 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x6b4c, 0xd5bc,
- 0x0040, 0x6bc2, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
- 0x0078, 0x6bc9, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000,
- 0x646e, 0x1078, 0x488f, 0x0040, 0x6bdf, 0x0d7e, 0x7810, 0xa06d,
- 0x684c, 0x0d7f, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6bdf,
- 0x7824, 0xc0cd, 0x7826, 0x6073, 0x0889, 0x0078, 0x6be1, 0x6073,
- 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
- 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082,
- 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca,
- 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0xa582, 0x0080, 0x0048, 0x6c0f, 0x6a00, 0xd2f4, 0x0040, 0x6c0d,
- 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6c0f, 0x2011, 0x0000, 0x629e,
- 0x7824, 0xd0cc, 0x0040, 0x6c18, 0x6017, 0x0016, 0x0078, 0x6b4c,
- 0x6017, 0x0012, 0x0078, 0x6b4c, 0x7a18, 0xa280, 0x0023, 0x2014,
- 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069,
- 0xa5ab, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3,
- 0x0056, 0x60a7, 0x9575, 0x1078, 0x6c38, 0x1078, 0x594f, 0x007c,
- 0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f,
- 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004,
- 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e,
- 0x017e, 0x027e, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194,
- 0x4000, 0x0040, 0x6c89, 0x1078, 0x6c41, 0x6803, 0x1000, 0x6803,
- 0x0000, 0x0c7e, 0x2061, 0xa5ab, 0x6128, 0xa192, 0x00c8, 0x00c8,
- 0x6c76, 0x8108, 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6c84,
- 0x1078, 0x594f, 0x1078, 0x6c38, 0x0078, 0x6c84, 0x6124, 0xa1e5,
- 0x0000, 0x0040, 0x6c81, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078,
- 0x756c, 0x0c7f, 0x0078, 0x6c84, 0x027f, 0x017f, 0x0d7f, 0x0c7f,
- 0x007c, 0x2001, 0xa5c7, 0x2004, 0xa005, 0x00c0, 0x6c84, 0x0c7e,
- 0x2061, 0xa5ab, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6c76, 0x8108,
- 0x612a, 0x0c7f, 0x1078, 0x594f, 0x1078, 0x4171, 0x0078, 0x6c84,
- 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5967, 0x2071,
- 0xa5ab, 0x713c, 0x81ff, 0x0040, 0x6cca, 0x2061, 0x0100, 0x2069,
- 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6cd0, 0x6803, 0x1000,
- 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x037f,
- 0x713c, 0x2160, 0x1078, 0xa241, 0x2009, 0x004a, 0x1078, 0x756c,
- 0x0078, 0x6cca, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
- 0x0078, 0x6cba, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, 0x047e,
- 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071,
- 0xa5ab, 0x7018, 0x2068, 0x8dff, 0x0040, 0x6cfc, 0x68a0, 0xa406,
- 0x0040, 0x6cee, 0x6854, 0x2068, 0x0078, 0x6ce3, 0x6010, 0x2060,
- 0x643c, 0x6540, 0x6e48, 0x2d60, 0x1078, 0x466a, 0x0040, 0x6cfc,
- 0x1078, 0x7045, 0xa085, 0x0001, 0x127f, 0x007f, 0x047f, 0x057f,
- 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, 0x020b, 0x1078,
- 0x6567, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c,
- 0xa086, 0x0004, 0x00c0, 0x6d17, 0x6098, 0x0078, 0x6d18, 0x6030,
- 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006,
- 0x20a2, 0x00f0, 0x6d20, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x1078,
- 0x6c2d, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6567,
- 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
- 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c, 0x157e,
- 0x147e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x20a3,
- 0x0000, 0x20a9, 0x0006, 0x2011, 0xa340, 0x2019, 0xa341, 0x23a6,
- 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, 0x6d4f, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x147f,
- 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b,
- 0x1078, 0x65cf, 0x1078, 0x65e6, 0x7810, 0xa080, 0x0000, 0x2004,
- 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
- 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6c2d, 0x027f, 0x017f,
- 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
- 0x6567, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
- 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c,
- 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x6567,
- 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808,
- 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x1078, 0x6c2d,
- 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, 0x0c7e, 0x007e,
- 0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x700c, 0x2060, 0x8cff,
- 0x0040, 0x6dd1, 0x1078, 0x8c3b, 0x00c0, 0x6dc8, 0x1078, 0x7a05,
- 0x600c, 0x007e, 0x1078, 0x753d, 0x1078, 0x7045, 0x0c7f, 0x0078,
- 0x6dbf, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, 0x007f, 0x0c7f,
- 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e,
- 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079,
- 0x0140, 0x2071, 0xa5ab, 0x7024, 0x2060, 0x8cff, 0x0040, 0x6e2a,
- 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x595a, 0x2009, 0x0013,
- 0x1078, 0x756c, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x6e0d,
- 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6e1f, 0x7803,
- 0x1000, 0x7803, 0x0000, 0x0078, 0x6e1f, 0xd084, 0x0040, 0x6e14,
- 0x6827, 0x0001, 0x0078, 0x6e16, 0x00f0, 0x6dfc, 0x7804, 0xa084,
- 0x1000, 0x0040, 0x6e1f, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
- 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
- 0x127f, 0x007c, 0x2001, 0xa300, 0x2004, 0xa096, 0x0001, 0x0040,
- 0x6e62, 0xa096, 0x0004, 0x0040, 0x6e62, 0x6817, 0x0008, 0x68c3,
- 0x0000, 0x2011, 0x4129, 0x1078, 0x58d4, 0x20a9, 0x01f4, 0x6824,
- 0xd094, 0x0040, 0x6e50, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000,
- 0x0040, 0x6e62, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x6e62,
- 0xd084, 0x0040, 0x6e57, 0x6827, 0x0001, 0x0078, 0x6e59, 0x00f0,
- 0x6e3f, 0x7804, 0xa084, 0x1000, 0x0040, 0x6e62, 0x7803, 0x0100,
- 0x7803, 0x0000, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f,
- 0x0f7f, 0x157f, 0x127f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e,
- 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069,
- 0x0100, 0x2079, 0x0140, 0x2071, 0xa5ab, 0x703c, 0x2060, 0x8cff,
- 0x0040, 0x6ee8, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0,
- 0x6e86, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x1078, 0x5967, 0x1078,
- 0x1f31, 0x047e, 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5,
- 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0,
- 0x6eb7, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079,
- 0x0020, 0x2071, 0xa602, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012,
- 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a,
- 0x057f, 0x047f, 0xa39d, 0x0000, 0x00c0, 0x6ec2, 0x2009, 0x0049,
- 0x1078, 0x756c, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x6ed5,
- 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6ee7, 0x7803,
- 0x1000, 0x7803, 0x0000, 0x0078, 0x6ee7, 0xd08c, 0x0040, 0x6edc,
- 0x6827, 0x0002, 0x0078, 0x6ede, 0x00f0, 0x6ec4, 0x7804, 0xa084,
- 0x1000, 0x0040, 0x6ee7, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
- 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
- 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa5ab,
- 0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000,
- 0x2069, 0xa5ab, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e,
- 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0xa5ab, 0x7614, 0x2660,
- 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x6f46, 0x601c, 0xa206,
- 0x00c0, 0x6f41, 0x7014, 0xac36, 0x00c0, 0x6f20, 0x660c, 0x7616,
- 0x7010, 0xac36, 0x00c0, 0x6f2e, 0x2c00, 0xaf36, 0x0040, 0x6f2c,
- 0x2f00, 0x7012, 0x0078, 0x6f2e, 0x7013, 0x0000, 0x660c, 0x067e,
- 0x2c00, 0xaf06, 0x0040, 0x6f37, 0x7e0e, 0x0078, 0x6f38, 0x2678,
- 0x600f, 0x0000, 0x1078, 0x8c01, 0x1078, 0x7045, 0x0c7f, 0x0078,
- 0x6f13, 0x2c78, 0x600c, 0x2060, 0x0078, 0x6f13, 0x127f, 0x007f,
- 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1,
- 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
- 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0078, 0x6fa0, 0x157e, 0x147e,
- 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2,
- 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0078, 0x6fa0, 0x157e,
- 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006,
- 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x6fa0,
- 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2,
- 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078,
- 0x6fa0, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
- 0x1078, 0x7050, 0x60c3, 0x0020, 0x1078, 0x6c2d, 0x147f, 0x157f,
- 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120,
- 0xd1b4, 0x00c0, 0x6fb8, 0xd1bc, 0x00c0, 0x7002, 0x0078, 0x7042,
- 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069,
- 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000,
- 0x0040, 0x6ff9, 0x6020, 0xd0b4, 0x0040, 0x6ff9, 0x6024, 0xd094,
- 0x00c0, 0x6ff9, 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0,
- 0x6ff9, 0x00f0, 0x6fc5, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107,
- 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b,
- 0xbc91, 0x6043, 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024,
- 0xd094, 0x00c0, 0x6ff8, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x6fef,
- 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000,
- 0x0078, 0x7042, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e,
- 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804,
- 0xa084, 0x4000, 0x0040, 0x703b, 0x6020, 0xd0bc, 0x0040, 0x703b,
- 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x703b, 0x00f0,
- 0x700f, 0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c,
- 0x00ff, 0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043,
- 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000,
- 0x00c0, 0x7035, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f,
- 0x200b, 0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa5ab,
- 0x7020, 0xa005, 0x0040, 0x704e, 0x8001, 0x7022, 0x0e7f, 0x007c,
- 0x20a9, 0x0008, 0x20a2, 0x00f0, 0x7052, 0x20a2, 0x20a2, 0x007c,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e,
- 0x2091, 0x8000, 0x2071, 0xa5ab, 0x7614, 0x2660, 0x2678, 0x2039,
- 0x0001, 0x87ff, 0x0040, 0x70f4, 0x8cff, 0x0040, 0x70f4, 0x601c,
- 0xa086, 0x0006, 0x00c0, 0x70ef, 0x88ff, 0x0040, 0x707f, 0x2800,
- 0xac06, 0x00c0, 0x70ef, 0x2039, 0x0000, 0x0078, 0x708a, 0x6018,
- 0xa206, 0x00c0, 0x70ef, 0x85ff, 0x0040, 0x708a, 0x6020, 0xa106,
- 0x00c0, 0x70ef, 0x7024, 0xac06, 0x00c0, 0x70ba, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0040, 0x70b5, 0x1078, 0x595a, 0x6817, 0x0008,
- 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x70aa, 0x6803, 0x0100,
- 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x70b2,
- 0x6827, 0x0001, 0x037f, 0x0078, 0x70ba, 0x6003, 0x0009, 0x630a,
- 0x0078, 0x70ef, 0x7014, 0xac36, 0x00c0, 0x70c0, 0x660c, 0x7616,
- 0x7010, 0xac36, 0x00c0, 0x70ce, 0x2c00, 0xaf36, 0x0040, 0x70cc,
- 0x2f00, 0x7012, 0x0078, 0x70ce, 0x7013, 0x0000, 0x660c, 0x067e,
- 0x2c00, 0xaf06, 0x0040, 0x70d7, 0x7e0e, 0x0078, 0x70d8, 0x2678,
- 0x89ff, 0x00c0, 0x70e7, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x70e5, 0x1078, 0x9e70, 0x1078, 0x8c01, 0x1078,
- 0x7045, 0x88ff, 0x00c0, 0x70fe, 0x0c7f, 0x0078, 0x7069, 0x2c78,
- 0x600c, 0x2060, 0x0078, 0x7069, 0xa006, 0x127f, 0x007f, 0x067f,
- 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000,
- 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x70f5, 0x0f7e, 0x0e7e, 0x0d7e,
- 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
- 0xa5ab, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x7177, 0x601c,
- 0xa086, 0x0006, 0x00c0, 0x7172, 0x87ff, 0x0040, 0x7125, 0x2700,
- 0xac06, 0x00c0, 0x7172, 0x0078, 0x7130, 0x6018, 0xa206, 0x00c0,
- 0x7172, 0x85ff, 0x0040, 0x7130, 0x6020, 0xa106, 0x00c0, 0x7172,
- 0x703c, 0xac06, 0x00c0, 0x7142, 0x037e, 0x2019, 0x0001, 0x1078,
- 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047,
- 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7148, 0x660c, 0x763a,
- 0x7034, 0xac36, 0x00c0, 0x7156, 0x2c00, 0xaf36, 0x0040, 0x7154,
- 0x2f00, 0x7036, 0x0078, 0x7156, 0x7037, 0x0000, 0x660c, 0x067e,
- 0x2c00, 0xaf06, 0x0040, 0x715f, 0x7e0e, 0x0078, 0x7160, 0x2678,
- 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x716a,
- 0x1078, 0x9e70, 0x1078, 0x8c01, 0x87ff, 0x00c0, 0x7181, 0x0c7f,
- 0x0078, 0x7114, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7114, 0xa006,
- 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7178,
- 0x0e7e, 0x2071, 0xa5ab, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002,
- 0x00c0, 0x7196, 0x7007, 0x0005, 0x0078, 0x7198, 0x7007, 0x0000,
- 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e,
- 0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x2c10, 0x7638, 0x2660,
- 0x2678, 0x8cff, 0x0040, 0x71d8, 0x2200, 0xac06, 0x00c0, 0x71d3,
- 0x7038, 0xac36, 0x00c0, 0x71b6, 0x660c, 0x763a, 0x7034, 0xac36,
- 0x00c0, 0x71c4, 0x2c00, 0xaf36, 0x0040, 0x71c2, 0x2f00, 0x7036,
- 0x0078, 0x71c4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040,
- 0x71cc, 0x7e0e, 0x0078, 0x71cd, 0x2678, 0x600f, 0x0000, 0xa085,
- 0x0001, 0x0078, 0x71d8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x71a9,
- 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091,
- 0x8000, 0x2071, 0xa5ab, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040,
- 0x7279, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7274,
- 0x7024, 0xac06, 0x00c0, 0x721f, 0x2069, 0x0100, 0x68c0, 0xa005,
- 0x0040, 0x724d, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188,
- 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
- 0x0040, 0x7216, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
- 0x6824, 0xd084, 0x0040, 0x721e, 0x6827, 0x0001, 0x037f, 0x700c,
- 0xac36, 0x00c0, 0x7225, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0,
- 0x7233, 0x2c00, 0xaf36, 0x0040, 0x7231, 0x2f00, 0x700a, 0x0078,
- 0x7233, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
- 0x723c, 0x7e0e, 0x0078, 0x723d, 0x2678, 0x600f, 0x0000, 0x1078,
- 0x8c27, 0x00c0, 0x7251, 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0,
- 0x726d, 0x1078, 0x7a05, 0x0078, 0x726d, 0x1078, 0x7188, 0x0078,
- 0x721f, 0x1078, 0x8c3b, 0x00c0, 0x7259, 0x1078, 0x7a05, 0x0078,
- 0x726d, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x726d, 0x601c,
- 0xa086, 0x0003, 0x00c0, 0x7281, 0x6837, 0x0103, 0x6b4a, 0x6847,
- 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078,
- 0x7045, 0x0c7f, 0x0078, 0x71ee, 0x2c78, 0x600c, 0x2060, 0x0078,
- 0x71ee, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x726d, 0x1078, 0x9e70,
- 0x0078, 0x726d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006,
- 0xa190, 0x0020, 0x221c, 0xa39e, 0x260c, 0x00c0, 0x729b, 0x8210,
- 0x8000, 0x0078, 0x7292, 0xa005, 0x0040, 0x72a7, 0x20a9, 0x0020,
- 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f,
- 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
- 0x65f8, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x2099, 0xa5a3, 0x20a9, 0x0004, 0x53a6,
- 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8,
- 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084,
- 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6c2d,
- 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x8ef5,
- 0x00c0, 0x7361, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x1300,
- 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040,
- 0x733d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0,
- 0x7317, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7352, 0xa286,
- 0x007f, 0x00c0, 0x7321, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078,
- 0x7352, 0xd2bc, 0x0040, 0x7337, 0xa286, 0x0080, 0x00c0, 0x732e,
- 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7352, 0xa2e8, 0xa434,
- 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7352, 0x20a3,
- 0x0000, 0x6098, 0x20a2, 0x0078, 0x7352, 0x7818, 0xa080, 0x0028,
- 0x2004, 0xa082, 0x007e, 0x0048, 0x734e, 0x0d7e, 0x2069, 0xa31a,
- 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7352, 0x20a3, 0x0000,
- 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x017f, 0x0d7f,
- 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c,
- 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040,
- 0x738a, 0xa186, 0x0003, 0x0040, 0x73e5, 0xa186, 0x0005, 0x0040,
- 0x73c8, 0xa186, 0x0004, 0x0040, 0x73b8, 0xa186, 0x0008, 0x0040,
- 0x73d2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7450, 0x027f,
- 0x0d7f, 0x007c, 0x1078, 0x740d, 0x2009, 0x4000, 0x6800, 0x0079,
- 0x7391, 0x73a4, 0x73b2, 0x73a6, 0x73b2, 0x73ad, 0x73a4, 0x73a4,
- 0x73b2, 0x73b2, 0x73b2, 0x73b2, 0x73a4, 0x73a4, 0x73a4, 0x73a4,
- 0x73a4, 0x73b2, 0x73a4, 0x73b2, 0x1078, 0x1328, 0x6824, 0xd0e4,
- 0x0040, 0x73ad, 0xd0cc, 0x0040, 0x73b0, 0xa00e, 0x0078, 0x73b2,
- 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x7403,
- 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
- 0x6a00, 0xa286, 0x0002, 0x00c0, 0x73c6, 0xa00e, 0x0078, 0x7403,
- 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
- 0x0078, 0x7403, 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x73e2, 0xa286, 0x0002,
- 0x00c0, 0x73e3, 0xa00e, 0x0078, 0x7403, 0x1078, 0x740d, 0x6810,
- 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2,
- 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040,
- 0x7401, 0xa08e, 0x0004, 0x0040, 0x7401, 0x2009, 0x4000, 0x0078,
- 0x7403, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018,
- 0x1078, 0x6c2d, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e,
- 0x067e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0xa006, 0x20a3, 0x0200,
- 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028,
- 0x2004, 0xa092, 0x007e, 0x0048, 0x7433, 0x0d7e, 0x2069, 0xa31a,
- 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa434, 0x2d6c, 0x6b10, 0x6c14,
- 0x0d7f, 0x0078, 0x7439, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000,
- 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0,
- 0x7447, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x744b, 0x23a2,
- 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d,
- 0x007c, 0x20a1, 0x020b, 0x1078, 0x655e, 0x20a3, 0x1400, 0x20a3,
- 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c,
- 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000,
- 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078,
- 0x65ef, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810,
- 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x147e, 0x20a1,
- 0x020b, 0x1078, 0x7499, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f,
- 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0xd0bc, 0x0040, 0x74b6, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a,
- 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x74be, 0x20a3, 0x0300,
- 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819,
- 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
- 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061,
- 0xaa00, 0x2a70, 0x7060, 0x7046, 0x704b, 0xaa00, 0x007c, 0x0e7e,
- 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582, 0x0010,
- 0x0048, 0x7509, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040,
- 0x74f5, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x74f1, 0x0078,
- 0x74e4, 0x2061, 0xaa00, 0x0078, 0x74e4, 0x6003, 0x0008, 0x8529,
- 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x7505, 0x754a,
- 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00, 0x0078,
- 0x7500, 0xa006, 0x0078, 0x7502, 0x0e7e, 0x2071, 0xa300, 0x7544,
- 0xa582, 0x0010, 0x0048, 0x753a, 0x7048, 0x2060, 0x6000, 0xa086,
- 0x0000, 0x0040, 0x7527, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
- 0x7523, 0x0078, 0x7516, 0x2061, 0xaa00, 0x0078, 0x7516, 0x6003,
- 0x0008, 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8,
- 0x7536, 0x754a, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704b, 0xaa00,
- 0x0078, 0x7532, 0xa006, 0x0078, 0x7534, 0xac82, 0xaa00, 0x1048,
- 0x1328, 0x2001, 0xa315, 0x2004, 0xac02, 0x10c8, 0x1328, 0xa006,
- 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000,
- 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036,
- 0x603a, 0x603e, 0x2061, 0xa300, 0x6044, 0x8000, 0x6046, 0xa086,
- 0x0001, 0x0040, 0x7564, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078,
- 0x6109, 0x127f, 0x0078, 0x7563, 0x601c, 0xa084, 0x000f, 0x0079,
- 0x7571, 0x757a, 0x758b, 0x75a7, 0x75c3, 0x8f2d, 0x8f49, 0x8f65,
- 0x757a, 0x758b, 0xa186, 0x0013, 0x00c0, 0x7583, 0x1078, 0x6010,
- 0x1078, 0x6109, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x758a, 0xa016,
- 0x1078, 0x15ec, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
- 0x1328, 0x1079, 0x7595, 0x067f, 0x007c, 0x75a5, 0x7891, 0x7a34,
- 0x75a5, 0x7ab8, 0x75df, 0x75a5, 0x75a5, 0x7823, 0x7e6d, 0x75a5,
- 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x1078, 0x1328, 0x067e,
- 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079, 0x75b1, 0x067f,
- 0x007c, 0x75c1, 0x8522, 0x75c1, 0x75c1, 0x75c1, 0x75c1, 0x75c1,
- 0x75c1, 0x84c5, 0x86a8, 0x75c1, 0x8552, 0x85d8, 0x8552, 0x85d8,
- 0x75c1, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
- 0x1328, 0x1079, 0x75cd, 0x067f, 0x007c, 0x75dd, 0x7eb4, 0x7f81,
- 0x80c6, 0x8242, 0x75dd, 0x75dd, 0x75dd, 0x7e8d, 0x846d, 0x8471,
- 0x75dd, 0x75dd, 0x75dd, 0x75dd, 0x84a1, 0x1078, 0x1328, 0xa1b6,
- 0x0015, 0x00c0, 0x75e7, 0x1078, 0x753d, 0x0078, 0x75ed, 0xa1b6,
- 0x0016, 0x10c0, 0x1328, 0x1078, 0x753d, 0x007c, 0x20a9, 0x000e,
- 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420,
- 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002,
- 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x75fc,
- 0x0e7e, 0x1078, 0x8a44, 0x0040, 0x7613, 0x6010, 0x2070, 0x7007,
- 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c, 0x0d7e,
- 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7624, 0x6018, 0x2068,
- 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x762e,
- 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x753d,
- 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c,
- 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a,
- 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3,
- 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078,
- 0x753d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68,
- 0x017e, 0x2009, 0x0035, 0x1078, 0x8ef5, 0x017f, 0x00c0, 0x766f,
- 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xa88c, 0x6b1c, 0xa386,
- 0x0003, 0x0040, 0x7673, 0xa386, 0x0006, 0x0040, 0x7677, 0x1078,
- 0x753d, 0x0078, 0x7679, 0x1078, 0x767c, 0x0078, 0x7679, 0x1078,
- 0x771e, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186,
- 0x0015, 0x0040, 0x7705, 0xa18e, 0x0016, 0x00c0, 0x771c, 0x700c,
- 0xa084, 0xff00, 0xa086, 0x1700, 0x00c0, 0x76e0, 0x8fff, 0x0040,
- 0x771a, 0x6808, 0xa086, 0xffff, 0x00c0, 0x7709, 0x784c, 0xa084,
- 0x0060, 0xa086, 0x0020, 0x00c0, 0x76a7, 0x797c, 0x7810, 0xa106,
- 0x00c0, 0x7709, 0x7980, 0x7814, 0xa106, 0x00c0, 0x7709, 0x1078,
- 0x8bf4, 0x6830, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e,
- 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x1078, 0x5a98, 0x7854,
- 0xa20a, 0x0048, 0x76bc, 0x8011, 0x7a56, 0x82ff, 0x027f, 0x00c0,
- 0x76c8, 0x0c7e, 0x2d60, 0x1078, 0x8832, 0x0c7f, 0x0078, 0x771a,
- 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, 0x00c0, 0x76d3, 0x1078,
- 0x4290, 0x0078, 0x76d5, 0x1078, 0x436e, 0x0d7f, 0x0c7f, 0x00c0,
- 0x7709, 0x0c7e, 0x2d60, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x771a,
- 0x7008, 0xa086, 0x000b, 0x00c0, 0x76fa, 0x6018, 0x200c, 0xc1bc,
- 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003,
- 0x000b, 0x601f, 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f,
- 0x0078, 0x771a, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7709, 0x2001,
- 0xa5a2, 0x2004, 0x683e, 0x0078, 0x771a, 0x1078, 0x7739, 0x0078,
- 0x771c, 0x8fff, 0x1040, 0x1328, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68,
- 0x684b, 0x0003, 0x1078, 0x8726, 0x1078, 0x8bf4, 0x1078, 0x8c01,
- 0x0d7f, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0xa186, 0x0015,
- 0x00c0, 0x7728, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x7736,
- 0xa18e, 0x0016, 0x00c0, 0x7738, 0x0c7e, 0x2d00, 0x2060, 0x1078,
- 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d, 0x0c7f, 0x1078, 0x753d,
- 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, 0x7b7c, 0xd2f4,
- 0x0040, 0x7748, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x77ac,
- 0x0c7e, 0x2d60, 0x1078, 0x874a, 0x0c7f, 0x6804, 0xa086, 0x0050,
- 0x00c0, 0x7760, 0x0c7e, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007,
- 0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x77ac,
- 0x6800, 0xa086, 0x000f, 0x0040, 0x7782, 0x8fff, 0x1040, 0x1328,
- 0x6824, 0xd0dc, 0x00c0, 0x7782, 0x6800, 0xa086, 0x0004, 0x00c0,
- 0x7787, 0x784c, 0xd0ac, 0x0040, 0x7787, 0x784c, 0xc0dc, 0xc0f4,
- 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e,
- 0x0078, 0x77a6, 0x2001, 0x0007, 0x682e, 0x0078, 0x77a6, 0x784c,
- 0xd0b4, 0x00c0, 0x7794, 0xd0ac, 0x0040, 0x7782, 0x784c, 0xd0f4,
- 0x00c0, 0x7782, 0x0078, 0x7775, 0xd2ec, 0x00c0, 0x7782, 0x7024,
- 0xa306, 0x00c0, 0x779f, 0x7020, 0xa406, 0x0040, 0x7782, 0x7020,
- 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x1078, 0x8d2b,
- 0x1078, 0x6109, 0x0078, 0x77ae, 0x1078, 0x753d, 0x047f, 0x037f,
- 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, 0x2068, 0x6a1c,
- 0xa286, 0x0007, 0x0040, 0x7806, 0xa286, 0x0002, 0x0040, 0x7806,
- 0xa286, 0x0000, 0x0040, 0x7806, 0x6808, 0x6338, 0xa306, 0x00c0,
- 0x7806, 0x2071, 0xa88c, 0xa186, 0x0015, 0x0040, 0x7800, 0xa18e,
- 0x0016, 0x00c0, 0x77e8, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001,
- 0x00c0, 0x77e8, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x77e8, 0x6034,
- 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0078, 0x7800,
- 0x0c7e, 0x6034, 0x2060, 0x6010, 0x2068, 0x1078, 0x8a44, 0x1040,
- 0x1328, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
- 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x7806,
- 0x6034, 0x2068, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x1078, 0x753d,
- 0x027f, 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98,
- 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7820, 0x6018,
- 0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802,
- 0x0d7f, 0x0078, 0x7608, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1328,
- 0xa1b2, 0x0040, 0x00c8, 0x7888, 0x0079, 0x782e, 0x787c, 0x7870,
- 0x787c, 0x787c, 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x787c,
- 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x786e, 0x1078, 0x1328,
- 0x6003, 0x0001, 0x6106, 0x1078, 0x5c45, 0x127e, 0x2091, 0x8000,
- 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
- 0x5c45, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c,
- 0x2600, 0x0079, 0x788b, 0x788f, 0x788f, 0x788f, 0x787c, 0x1078,
- 0x1328, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328, 0xa1b6, 0x0013,
- 0x00c0, 0x78a1, 0xa0b2, 0x0040, 0x00c8, 0x79fb, 0x2008, 0x0079,
- 0x7941, 0xa1b6, 0x0027, 0x00c0, 0x78fe, 0x1078, 0x6010, 0x6004,
- 0x1078, 0x8c27, 0x0040, 0x78be, 0x1078, 0x8c3b, 0x0040, 0x78f6,
- 0xa08e, 0x0021, 0x0040, 0x78fa, 0xa08e, 0x0022, 0x0040, 0x78f6,
- 0xa08e, 0x003d, 0x0040, 0x78fa, 0x0078, 0x78f1, 0x1078, 0x2839,
- 0x2001, 0x0007, 0x1078, 0x443f, 0x6018, 0xa080, 0x0028, 0x200c,
- 0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x78d3, 0x2001, 0xa332,
- 0x2014, 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019,
- 0x0028, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78,
- 0x0c7e, 0x6018, 0xa065, 0x0040, 0x78e7, 0x1078, 0x471b, 0x0c7f,
- 0x2c08, 0x1078, 0x9c38, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078,
- 0x44bc, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x7a05,
- 0x0078, 0x78f1, 0x1078, 0x7a28, 0x0078, 0x78f1, 0xa186, 0x0014,
- 0x00c0, 0x78f5, 0x1078, 0x6010, 0x1078, 0x2813, 0x1078, 0x8c27,
- 0x00c0, 0x791d, 0x1078, 0x2839, 0x6018, 0xa080, 0x0028, 0x200c,
- 0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x791b, 0x2001, 0xa332,
- 0x200c, 0xc185, 0x2102, 0x0078, 0x78f1, 0x1078, 0x8c3b, 0x00c0,
- 0x7925, 0x1078, 0x7a05, 0x0078, 0x78f1, 0x6004, 0xa08e, 0x0032,
- 0x00c0, 0x7936, 0x0e7e, 0x0f7e, 0x2071, 0xa381, 0x2079, 0x0000,
- 0x1078, 0x2b56, 0x0f7f, 0x0e7f, 0x0078, 0x78f1, 0x6004, 0xa08e,
- 0x0021, 0x0040, 0x7921, 0xa08e, 0x0022, 0x1040, 0x7a05, 0x0078,
- 0x78f1, 0x7983, 0x7985, 0x7989, 0x798d, 0x7991, 0x7995, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7999,
- 0x79ab, 0x7981, 0x79ad, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x79ab, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x79de, 0x79ab, 0x7981, 0x79a5, 0x7981,
- 0x7981, 0x7981, 0x79a7, 0x7981, 0x7981, 0x7981, 0x79ab, 0x7981,
- 0x7981, 0x1078, 0x1328, 0x0078, 0x79ab, 0x2001, 0x000b, 0x0078,
- 0x79b8, 0x2001, 0x0003, 0x0078, 0x79b8, 0x2001, 0x0005, 0x0078,
- 0x79b8, 0x2001, 0x0001, 0x0078, 0x79b8, 0x2001, 0x0009, 0x0078,
- 0x79b8, 0x1078, 0x6010, 0x6003, 0x0005, 0x2001, 0xa5a2, 0x2004,
- 0x603e, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0078, 0x79ab, 0x0078,
- 0x79ab, 0x1078, 0x443f, 0x0078, 0x79f0, 0x1078, 0x6010, 0x6003,
- 0x0004, 0x2001, 0xa5a0, 0x2004, 0x6016, 0x1078, 0x6109, 0x007c,
- 0x1078, 0x443f, 0x1078, 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e,
- 0x6003, 0x0002, 0x037e, 0x2019, 0xa35c, 0x2304, 0xa084, 0xff00,
- 0x00c0, 0x79cf, 0x2019, 0xa5a0, 0x231c, 0x0078, 0x79d8, 0x8007,
- 0xa09a, 0x0004, 0x0048, 0x79ca, 0x8003, 0x801b, 0x831b, 0xa318,
- 0x6316, 0x037f, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0e7e, 0x0f7e,
- 0x2071, 0xa381, 0x2079, 0x0000, 0x1078, 0x2b56, 0x0f7f, 0x0e7f,
- 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x0078, 0x79b7,
- 0x1078, 0x6010, 0x6003, 0x0002, 0x2001, 0xa5a0, 0x2004, 0x6016,
- 0x1078, 0x6109, 0x007c, 0x2600, 0x2008, 0x0079, 0x79ff, 0x7a03,
- 0x7a03, 0x7a03, 0x79f0, 0x1078, 0x1328, 0x0e7e, 0x1078, 0x8a44,
- 0x0040, 0x7a21, 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7a21,
- 0x7007, 0x0000, 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7a23,
- 0xa08e, 0x003d, 0x0040, 0x7a23, 0x017f, 0x7037, 0x0103, 0x7033,
- 0x0100, 0x0e7f, 0x007c, 0x017f, 0x1078, 0x7a28, 0x0078, 0x7a21,
- 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103,
- 0x7023, 0x8001, 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804,
- 0xa084, 0x00ff, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0x6604,
- 0xa6b6, 0x0043, 0x00c0, 0x7a48, 0x1078, 0x8e6d, 0x0078, 0x7aa7,
- 0x6604, 0xa6b6, 0x0033, 0x00c0, 0x7a51, 0x1078, 0x8e11, 0x0078,
- 0x7aa7, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x7a5a, 0x1078, 0x8c6a,
- 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7a63, 0x1078,
- 0x8c84, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7a6c,
- 0x1078, 0x75ee, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0000, 0x00c0,
- 0x7a75, 0x1078, 0x780c, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0022,
- 0x00c0, 0x7a7e, 0x1078, 0x7617, 0x0078, 0x7aa7, 0x6604, 0xa6b6,
- 0x0035, 0x00c0, 0x7a87, 0x1078, 0x7653, 0x0078, 0x7aa7, 0x6604,
- 0xa6b6, 0x0039, 0x00c0, 0x7a90, 0x1078, 0x77b2, 0x0078, 0x7aa7,
- 0x6604, 0xa6b6, 0x003d, 0x00c0, 0x7a99, 0x1078, 0x7633, 0x0078,
- 0x7aa7, 0xa1b6, 0x0015, 0x00c0, 0x7aa1, 0x1079, 0x7aac, 0x0078,
- 0x7aa7, 0xa1b6, 0x0016, 0x00c0, 0x7aa8, 0x1079, 0x7bfd, 0x007c,
- 0x1078, 0x7583, 0x0078, 0x7aa7, 0x7ad0, 0x7ad3, 0x7ad0, 0x7b1e,
- 0x7ad0, 0x7b91, 0x7c09, 0x7ad0, 0x7ad0, 0x7bd5, 0x7ad0, 0x7beb,
- 0xa1b6, 0x0048, 0x0040, 0x7ac4, 0x20e1, 0x0005, 0x3d18, 0x3e20,
- 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74,
- 0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c,
- 0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086,
- 0x0074, 0x00c0, 0x7b07, 0x1078, 0x9c0c, 0x00c0, 0x7af9, 0x0d7e,
- 0x6018, 0x2068, 0x7030, 0xd08c, 0x0040, 0x7aec, 0x6800, 0xd0bc,
- 0x0040, 0x7aec, 0xc0c5, 0x6802, 0x1078, 0x7b0b, 0x0d7f, 0x2001,
- 0x0006, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078,
- 0x7b09, 0x2001, 0x000a, 0x1078, 0x443f, 0x1078, 0x2839, 0x6003,
- 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7b09, 0x1078,
- 0x7b81, 0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x7b1d, 0x2001,
- 0x0000, 0x1078, 0x442b, 0x2069, 0xa351, 0x6804, 0xd0a4, 0x0040,
- 0x7b1d, 0x2001, 0x0006, 0x1078, 0x4472, 0x007c, 0x0d7e, 0x2011,
- 0xa31f, 0x2204, 0xa086, 0x0074, 0x00c0, 0x7b7d, 0x6018, 0x2068,
- 0x6aa0, 0xa286, 0x007e, 0x00c0, 0x7b31, 0x1078, 0x7d17, 0x0078,
- 0x7b7f, 0x1078, 0x7d0d, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014,
- 0xa286, 0x0080, 0x00c0, 0x7b55, 0x6813, 0x00ff, 0x6817, 0xfffc,
- 0x6010, 0xa005, 0x0040, 0x7b4b, 0x2068, 0x6807, 0x0000, 0x6837,
- 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078,
- 0x2839, 0x1078, 0x753d, 0x0078, 0x7b7f, 0x0e7e, 0x2071, 0xa332,
- 0x2e04, 0xd09c, 0x0040, 0x7b70, 0x2071, 0xa880, 0x7108, 0x720c,
- 0xa18c, 0x00ff, 0x00c0, 0x7b68, 0xa284, 0xff00, 0x0040, 0x7b70,
- 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x00c0, 0x7b70, 0x7112, 0x7216,
- 0x0e7f, 0x2001, 0x0004, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
- 0x0003, 0x1078, 0x5c45, 0x0078, 0x7b7f, 0x1078, 0x7b81, 0x0d7f,
- 0x007c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x0040, 0x7b8c,
- 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d,
- 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086, 0x0014, 0x00c0,
- 0x7bcf, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7ba4, 0x6010, 0xa005,
- 0x00c0, 0x7ba4, 0x1078, 0x35f7, 0x0d7e, 0x6018, 0x2068, 0x1078,
- 0x457d, 0x1078, 0x7b0b, 0x0d7f, 0x1078, 0x7dba, 0x00c0, 0x7bcf,
- 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x7bcf,
- 0x2001, 0x0006, 0x1078, 0x443f, 0x0e7e, 0x6010, 0xa005, 0x0040,
- 0x7bc8, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200,
- 0x0e7f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078, 0x7bd3, 0x1078,
- 0x7a05, 0x1078, 0x7b81, 0x0e7f, 0x007c, 0x2011, 0xa31f, 0x2204,
- 0xa086, 0x0014, 0x00c0, 0x7be8, 0x2001, 0x0002, 0x1078, 0x443f,
- 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7bea,
- 0x1078, 0x7b81, 0x007c, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0004,
- 0x00c0, 0x7bfa, 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x753d,
- 0x0078, 0x7bfc, 0x1078, 0x7b81, 0x007c, 0x7ad0, 0x7c11, 0x7ad0,
- 0x7c4e, 0x7ad0, 0x7cc0, 0x7c09, 0x7ad0, 0x7ad0, 0x7cd5, 0x7ad0,
- 0x7ce8, 0x6604, 0xa6b6, 0x001e, 0x00c0, 0x7c10, 0x1078, 0x753d,
- 0x007c, 0x0d7e, 0x0c7e, 0x1078, 0x7cfb, 0x00c0, 0x7c27, 0x2001,
- 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003,
- 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x0078, 0x7c4b, 0x2009,
- 0xa88e, 0x2104, 0xa086, 0x0009, 0x00c0, 0x7c3c, 0x6018, 0x2068,
- 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x7c49, 0x8001, 0x6842,
- 0x6017, 0x000a, 0x0078, 0x7c4b, 0x2009, 0xa88f, 0x2104, 0xa084,
- 0xff00, 0xa086, 0x1900, 0x00c0, 0x7c49, 0x1078, 0x753d, 0x0078,
- 0x7c4b, 0x1078, 0x7b81, 0x0c7f, 0x0d7f, 0x007c, 0x1078, 0x7d0a,
- 0x00c0, 0x7c62, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002,
- 0x1078, 0x443f, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45,
- 0x0078, 0x7c8e, 0x1078, 0x7a05, 0x2009, 0xa88e, 0x2134, 0xa6b4,
- 0x00ff, 0xa686, 0x0005, 0x0040, 0x7c8f, 0xa686, 0x000b, 0x0040,
- 0x7c8c, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0x00c0, 0x7c7c,
- 0xa686, 0x0009, 0x0040, 0x7c8f, 0xa086, 0x1900, 0x00c0, 0x7c8c,
- 0xa686, 0x0009, 0x0040, 0x7c8f, 0x2001, 0x0004, 0x1078, 0x443f,
- 0x1078, 0x753d, 0x0078, 0x7c8e, 0x1078, 0x7b81, 0x007c, 0x0d7e,
- 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x7c9d, 0x6838, 0xd0fc,
- 0x0040, 0x7c9d, 0x0d7f, 0x0078, 0x7c8c, 0x6018, 0x2068, 0x6840,
- 0xa084, 0x00ff, 0xa005, 0x0040, 0x7cae, 0x8001, 0x6842, 0x6017,
- 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x7c8e, 0x68a0, 0xa086,
- 0x007e, 0x00c0, 0x7cbb, 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5,
- 0x0e7f, 0x0078, 0x7cbd, 0x1078, 0x2813, 0x0d7f, 0x0078, 0x7c8c,
- 0x1078, 0x7d0a, 0x00c0, 0x7cd0, 0x2001, 0x0004, 0x1078, 0x443f,
- 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x5c45, 0x0078, 0x7cd4,
- 0x1078, 0x7a05, 0x1078, 0x7b81, 0x007c, 0x1078, 0x7d0a, 0x00c0,
- 0x7ce5, 0x2001, 0x0008, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
- 0x0005, 0x1078, 0x5c45, 0x0078, 0x7ce7, 0x1078, 0x7b81, 0x007c,
- 0x1078, 0x7d0a, 0x00c0, 0x7cf8, 0x2001, 0x000a, 0x1078, 0x443f,
- 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7cfa,
- 0x1078, 0x7b81, 0x007c, 0x2009, 0xa88e, 0x2104, 0xa086, 0x0003,
- 0x00c0, 0x7d09, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0xa086,
- 0x2a00, 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88,
- 0x0006, 0x2164, 0x1078, 0x4513, 0x017f, 0x0c7f, 0x007c, 0x0f7e,
- 0x0e7e, 0x0d7e, 0x037e, 0x017e, 0x6018, 0x2068, 0x2071, 0xa332,
- 0x2e04, 0xa085, 0x0003, 0x2072, 0x1078, 0x7d8b, 0x0040, 0x7d50,
- 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x7d39, 0xa006, 0x2020,
- 0x2009, 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195,
- 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x27e2, 0x2071,
- 0xa300, 0x1078, 0x260d, 0x0c7e, 0x157e, 0x20a9, 0x0081, 0x2009,
- 0x007f, 0x1078, 0x2921, 0x8108, 0x00f0, 0x7d49, 0x157f, 0x0c7f,
- 0x1078, 0x7d0d, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xa880,
- 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa31a, 0x206a,
- 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa31b, 0x206a, 0x78ea,
- 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa325, 0x200a, 0x2069,
- 0xa88e, 0x2071, 0xa59c, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818,
- 0x700a, 0x681c, 0x700e, 0x1078, 0x8da9, 0x2001, 0x0006, 0x1078,
- 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x017f, 0x037f, 0x0d7f,
- 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, 0x2019,
- 0xa325, 0x231c, 0x83ff, 0x0040, 0x7db5, 0x2071, 0xa880, 0x2e14,
- 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x00c0,
- 0x7db5, 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078,
- 0x7e55, 0x00c0, 0x7db5, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9,
- 0x0004, 0x1078, 0x7e55, 0x00c0, 0x7db5, 0x157f, 0x0e7f, 0x037f,
- 0x027f, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7004, 0xa086, 0x0014,
- 0x00c0, 0x7ddd, 0x7008, 0xa086, 0x0800, 0x00c0, 0x7ddd, 0x700c,
- 0xd0ec, 0x0040, 0x7ddb, 0xa084, 0x0f00, 0xa086, 0x0100, 0x00c0,
- 0x7ddb, 0x7024, 0xd0a4, 0x00c0, 0x7dd8, 0xd0ac, 0x0040, 0x7ddb,
- 0xa006, 0x0078, 0x7ddd, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e,
- 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e,
- 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba, 0x2424,
- 0x2061, 0xaa00, 0x2071, 0xa300, 0x7244, 0x7060, 0xa202, 0x00c8,
- 0x7e43, 0x1078, 0x9ee5, 0x0040, 0x7e3b, 0x671c, 0xa786, 0x0001,
- 0x0040, 0x7e3b, 0xa786, 0x0007, 0x0040, 0x7e3b, 0x2500, 0xac06,
- 0x0040, 0x7e3b, 0x2400, 0xac06, 0x0040, 0x7e3b, 0x0c7e, 0x6000,
- 0xa086, 0x0004, 0x00c0, 0x7e16, 0x1078, 0x1749, 0xa786, 0x0008,
- 0x00c0, 0x7e25, 0x1078, 0x8c3b, 0x00c0, 0x7e25, 0x0c7f, 0x1078,
- 0x7a05, 0x1078, 0x8c01, 0x0078, 0x7e3b, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x7e38, 0xa786, 0x0003, 0x00c0, 0x7e4d, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4,
- 0x1078, 0x8c01, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
- 0x7e43, 0x0078, 0x7df4, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f,
- 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
- 0x7e2f, 0x1078, 0x9e70, 0x0078, 0x7e38, 0x220c, 0x2304, 0xa106,
- 0x00c0, 0x7e60, 0x8210, 0x8318, 0x00f0, 0x7e55, 0xa006, 0x007c,
- 0x2304, 0xa102, 0x0048, 0x7e68, 0x2001, 0x0001, 0x0078, 0x7e6a,
- 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0044,
- 0x10c8, 0x1328, 0x1078, 0x8c27, 0x0040, 0x7e7c, 0x1078, 0x8c3b,
- 0x0040, 0x7e89, 0x0078, 0x7e82, 0x1078, 0x2839, 0x1078, 0x8c3b,
- 0x0040, 0x7e89, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109,
- 0x007c, 0x1078, 0x7a05, 0x0078, 0x7e82, 0xa182, 0x0040, 0x0079,
- 0x7e91, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4,
- 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x7ea6, 0x7ea6, 0x7ea6,
- 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x1078, 0x1328, 0x600b, 0xffff,
- 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000,
- 0x1078, 0x6109, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x7ebd,
- 0x6004, 0xa082, 0x0040, 0x0079, 0x7f48, 0xa186, 0x0027, 0x00c0,
- 0x7edf, 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168,
- 0x1078, 0x8a44, 0x0040, 0x7ed9, 0x6837, 0x0103, 0x684b, 0x0029,
- 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4982, 0x1078,
- 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0xa186,
- 0x0014, 0x00c0, 0x7ee8, 0x6004, 0xa082, 0x0040, 0x0079, 0x7f10,
- 0xa186, 0x0046, 0x0040, 0x7ef4, 0xa186, 0x0045, 0x0040, 0x7ef4,
- 0xa186, 0x0047, 0x10c0, 0x1328, 0x2001, 0x0109, 0x2004, 0xd084,
- 0x0040, 0x7f0d, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e,
- 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086,
- 0x0002, 0x00c0, 0x7f0d, 0x0078, 0x7f81, 0x1078, 0x7583, 0x007c,
- 0x7f25, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23,
- 0x7f23, 0x7f23, 0x7f23, 0x7f41, 0x7f41, 0x7f41, 0x7f41, 0x7f23,
- 0x7f41, 0x7f23, 0x7f41, 0x1078, 0x1328, 0x1078, 0x6010, 0x0d7e,
- 0x6110, 0x2168, 0x1078, 0x8a44, 0x0040, 0x7f3b, 0x6837, 0x0103,
- 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x1078,
- 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109,
- 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c,
- 0x7f5d, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b,
- 0x7f5b, 0x7f5b, 0x7f5b, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f5b,
- 0x7f7a, 0x7f5b, 0x7f6f, 0x1078, 0x1328, 0x1078, 0x6010, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x6109, 0x6010,
- 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078,
- 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x000f, 0x1078,
- 0x6109, 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109,
- 0x007c, 0xa182, 0x0040, 0x0079, 0x7f85, 0x7f98, 0x7f98, 0x7f98,
- 0x7f98, 0x7f98, 0x7f9a, 0x8095, 0x80b7, 0x7f98, 0x7f98, 0x7f98,
- 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98,
- 0x1078, 0x1328, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2071, 0xa880,
- 0x7124, 0x610a, 0x2071, 0xa88c, 0x6110, 0x2168, 0x7614, 0xa6b4,
- 0x0fff, 0x86ff, 0x0040, 0x8058, 0xa68c, 0x0c00, 0x0040, 0x7fd1,
- 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x7fcd, 0x684c,
- 0xd0ac, 0x0040, 0x7fcd, 0x6024, 0xd0dc, 0x00c0, 0x7fcd, 0x6850,
- 0xd0bc, 0x00c0, 0x7fcd, 0x7318, 0x6814, 0xa306, 0x00c0, 0x806f,
- 0x731c, 0x6810, 0xa306, 0x00c0, 0x806f, 0x7318, 0x6b62, 0x731c,
- 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x8004, 0xa186,
- 0x0028, 0x00c0, 0x7fe1, 0x1078, 0x8c15, 0x684b, 0x001c, 0x0078,
- 0x8006, 0xd6dc, 0x0040, 0x7ffd, 0x684b, 0x0015, 0x684c, 0xd0ac,
- 0x0040, 0x7ffb, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x7ffb,
- 0x7018, 0xa106, 0x00c0, 0x7ff8, 0x701c, 0xa206, 0x0040, 0x7ffb,
- 0x6962, 0x6a5e, 0xc6dc, 0x0078, 0x8006, 0xd6d4, 0x0040, 0x8004,
- 0x684b, 0x0007, 0x0078, 0x8006, 0x684b, 0x0000, 0x6837, 0x0103,
- 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x802f, 0xa686, 0x0100, 0x00c0,
- 0x801a, 0x2001, 0xa899, 0x2004, 0xa005, 0x00c0, 0x801a, 0xc6c4,
- 0x0078, 0x7fa9, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x802f,
- 0xa38a, 0x0009, 0x0048, 0x8026, 0x2019, 0x0008, 0x037e, 0x2308,
- 0x2019, 0xa898, 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc,
- 0x0040, 0x8085, 0x7124, 0x695a, 0x81ff, 0x0040, 0x8085, 0xa192,
- 0x0021, 0x00c8, 0x8046, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18,
- 0xad90, 0x001d, 0x1078, 0x8739, 0x0078, 0x8085, 0x6838, 0xd0fc,
- 0x0040, 0x804f, 0x2009, 0x0020, 0x695a, 0x0078, 0x803b, 0x0f7e,
- 0x2d78, 0x1078, 0x86d1, 0x0f7f, 0x1078, 0x8726, 0x0078, 0x8087,
- 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8075, 0x684c,
- 0xd0ac, 0x0040, 0x8075, 0x6024, 0xd0dc, 0x00c0, 0x8075, 0x6850,
- 0xd0bc, 0x00c0, 0x8075, 0x684c, 0xd0f4, 0x00c0, 0x8075, 0x1078,
- 0x8cfa, 0x0d7f, 0x0e7f, 0x0078, 0x8094, 0x684b, 0x0000, 0x6837,
- 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x8085, 0x6810, 0x6914,
- 0xa115, 0x0040, 0x8085, 0x1078, 0x8233, 0x1078, 0x4982, 0x6218,
- 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x1078, 0x8cc4, 0x0d7f, 0x0e7f,
- 0x00c0, 0x8094, 0x1078, 0x753d, 0x007c, 0x0f7e, 0x6003, 0x0003,
- 0x2079, 0xa88c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
- 0x784c, 0xd0ac, 0x0040, 0x80a8, 0x6003, 0x0002, 0x0f7f, 0x007c,
- 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x603f, 0x0000, 0x2c10,
- 0x1078, 0x1cab, 0x1078, 0x5c64, 0x1078, 0x61d3, 0x007c, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005,
- 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0xa182, 0x0040,
- 0x0079, 0x80ca, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80df,
- 0x8182, 0x80dd, 0x80dd, 0x8198, 0x8209, 0x80dd, 0x80dd, 0x80dd,
- 0x80dd, 0x8218, 0x80dd, 0x80dd, 0x80dd, 0x1078, 0x1328, 0x077e,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xa88c, 0x6110, 0x2178, 0x7614,
- 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268,
- 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x817d, 0xa694, 0xff00,
- 0xa284, 0x0c00, 0x0040, 0x8100, 0x7018, 0x7862, 0x701c, 0x785e,
- 0xa284, 0x0300, 0x0040, 0x817d, 0x1078, 0x1381, 0x1040, 0x1328,
- 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838,
- 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
- 0x0040, 0x811e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
- 0xa186, 0x0002, 0x0040, 0x813a, 0xa186, 0x0028, 0x00c0, 0x812c,
- 0x684b, 0x001c, 0x0078, 0x813c, 0xd6dc, 0x0040, 0x8133, 0x684b,
- 0x0015, 0x0078, 0x813c, 0xd6d4, 0x0040, 0x813a, 0x684b, 0x0007,
- 0x0078, 0x813c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
- 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x815a, 0x7328, 0x732c, 0x6b56,
- 0x83ff, 0x0040, 0x815a, 0xa38a, 0x0009, 0x0048, 0x8151, 0x2019,
- 0x0008, 0x037e, 0x2308, 0x2019, 0xa898, 0xad90, 0x0019, 0x1078,
- 0x8739, 0x037f, 0xd6cc, 0x0040, 0x817d, 0x7124, 0x695a, 0x81ff,
- 0x0040, 0x817d, 0xa192, 0x0021, 0x00c8, 0x8171, 0x2071, 0xa898,
- 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x8739, 0x0078,
- 0x817d, 0x7838, 0xd0fc, 0x0040, 0x817a, 0x2009, 0x0020, 0x695a,
- 0x0078, 0x8166, 0x2d78, 0x1078, 0x86d1, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xa88c, 0x7c04,
- 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a,
- 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x6c26, 0x007c,
- 0x0d7e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x81a4,
- 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x60b8,
- 0x1078, 0x61d3, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x8207,
- 0xd1cc, 0x0040, 0x81de, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x81d6,
- 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198,
- 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318,
- 0x8210, 0x00f0, 0x81c5, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e,
- 0x017f, 0x2168, 0x1078, 0x13aa, 0x0078, 0x8201, 0x017e, 0x1078,
- 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8201, 0x6837, 0x0103,
- 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x81fd, 0xa086,
- 0x0028, 0x00c0, 0x81ef, 0x684b, 0x001c, 0x0078, 0x81ff, 0xd1dc,
- 0x0040, 0x81f6, 0x684b, 0x0015, 0x0078, 0x81ff, 0xd1d4, 0x0040,
- 0x81fd, 0x684b, 0x0007, 0x0078, 0x81ff, 0x684b, 0x0000, 0x1078,
- 0x4982, 0x1078, 0x8cc4, 0x00c0, 0x8207, 0x1078, 0x753d, 0x0d7f,
- 0x007c, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x6003, 0x0002, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x1078, 0x60b8, 0x1078, 0x61d3, 0x007c,
- 0x1078, 0x60b8, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168, 0x1078,
- 0x8a44, 0x0040, 0x822d, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847,
- 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d,
- 0x1078, 0x61d3, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x823f,
- 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962,
- 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x8246, 0x8259, 0x8259,
- 0x8259, 0x8259, 0x8259, 0x825b, 0x8259, 0x8333, 0x833f, 0x8259,
- 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259,
- 0x8259, 0x1078, 0x1328, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071,
- 0xa88c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x0f7f, 0x0040, 0x827e, 0xa684, 0x00ff, 0x00c0,
- 0x827e, 0x6024, 0xd0f4, 0x00c0, 0x827a, 0x7808, 0xa086, 0x0000,
- 0x00c0, 0x827e, 0x1078, 0x8cfa, 0x0078, 0x832e, 0x7e46, 0x7f4c,
- 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff,
- 0x0040, 0x8323, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x8294,
- 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x8320,
- 0xa686, 0x0100, 0x00c0, 0x82a6, 0x2001, 0xa899, 0x2004, 0xa005,
- 0x00c0, 0x82a6, 0xc6c4, 0x7e46, 0x0078, 0x8287, 0x1078, 0x1381,
- 0x1040, 0x1328, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e,
- 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842,
- 0x6e46, 0xa68c, 0x0c00, 0x0040, 0x82c1, 0x7318, 0x6b62, 0x731c,
- 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x82dd, 0xa186,
- 0x0028, 0x00c0, 0x82cf, 0x684b, 0x001c, 0x0078, 0x82df, 0xd6dc,
- 0x0040, 0x82d6, 0x684b, 0x0015, 0x0078, 0x82df, 0xd6d4, 0x0040,
- 0x82dd, 0x684b, 0x0007, 0x0078, 0x82df, 0x684b, 0x0000, 0x6f4e,
- 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x82fd,
- 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x82fd, 0xa38a, 0x0009,
- 0x0048, 0x82f4, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xa898,
- 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc, 0x0040, 0x8320,
- 0x7124, 0x695a, 0x81ff, 0x0040, 0x8320, 0xa192, 0x0021, 0x00c8,
- 0x8314, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d,
- 0x1078, 0x8739, 0x0078, 0x8320, 0x7838, 0xd0fc, 0x0040, 0x831d,
- 0x2009, 0x0020, 0x695a, 0x0078, 0x8309, 0x2d78, 0x1078, 0x86d1,
- 0xd6dc, 0x00c0, 0x8326, 0xa006, 0x0078, 0x832c, 0x2001, 0x0001,
- 0x2071, 0xa88c, 0x7218, 0x731c, 0x1078, 0x1645, 0x0d7f, 0x0e7f,
- 0x0f7f, 0x077f, 0x007c, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x20e1,
- 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168,
- 0x694c, 0xd1e4, 0x0040, 0x846b, 0x603f, 0x0000, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8385, 0x6814, 0x6910, 0xa115,
- 0x0040, 0x8385, 0x6a60, 0xa206, 0x00c0, 0x8362, 0x685c, 0xa106,
- 0x0040, 0x8385, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863,
- 0x0000, 0x685f, 0x0000, 0x6024, 0xd0f4, 0x00c0, 0x837a, 0x697c,
- 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6024,
- 0xc0f5, 0x6026, 0x0d7e, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
- 0x0d7f, 0x1078, 0x8cfa, 0x0078, 0x846b, 0x694c, 0xd1cc, 0x0040,
- 0x8430, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x83ea, 0x017e, 0x684c,
- 0x007e, 0x6850, 0x007e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x0040, 0x83bf, 0xa086, 0x0028, 0x00c0, 0x83a6,
- 0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x83ca, 0xd1dc, 0x0040,
- 0x83b6, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040,
- 0x83b4, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x83ca, 0xd1d4, 0x0040,
- 0x83bf, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x83ca, 0x684c,
- 0xd0ac, 0x0040, 0x83ca, 0x6810, 0x6914, 0xa115, 0x0040, 0x83ca,
- 0x1078, 0x8233, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e,
- 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8,
- 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, 0x83d8, 0x157f, 0x0f7f,
- 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x13aa,
- 0x0078, 0x8465, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x0040, 0x8417, 0xa086, 0x0028, 0x00c0, 0x83fe,
- 0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x8422, 0xd1dc, 0x0040,
- 0x840e, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040,
- 0x840c, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x8422, 0xd1d4, 0x0040,
- 0x8417, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x8422, 0x684c,
- 0xd0ac, 0x0040, 0x8422, 0x6810, 0x6914, 0xa115, 0x0040, 0x8422,
- 0x1078, 0x8233, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e,
- 0x0f7f, 0x1078, 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8465,
- 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040,
- 0x8456, 0xa086, 0x0028, 0x00c0, 0x8441, 0x684b, 0x001c, 0x0078,
- 0x8463, 0xd1dc, 0x0040, 0x844f, 0x684b, 0x0015, 0x1078, 0x8ea5,
- 0x0040, 0x844d, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8463, 0xd1d4,
- 0x0040, 0x8456, 0x684b, 0x0007, 0x0078, 0x8463, 0x684b, 0x0000,
- 0x684c, 0xd0ac, 0x0040, 0x8463, 0x6810, 0x6914, 0xa115, 0x0040,
- 0x8463, 0x1078, 0x8233, 0x1078, 0x4982, 0x1078, 0x8cc4, 0x00c0,
- 0x846b, 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x6010, 0x0078,
- 0x8473, 0x1078, 0x60b8, 0x1078, 0x8a44, 0x0040, 0x8492, 0x0d7e,
- 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa30c, 0x210c, 0xd18c,
- 0x00c0, 0x849d, 0xd184, 0x00c0, 0x8499, 0x6108, 0x694a, 0xa18e,
- 0x0029, 0x00c0, 0x848d, 0x1078, 0xa181, 0x6847, 0x0000, 0x1078,
- 0x4982, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x1078, 0x61d3,
- 0x007c, 0x684b, 0x0004, 0x0078, 0x848d, 0x684b, 0x0004, 0x0078,
- 0x848d, 0xa182, 0x0040, 0x0079, 0x84a5, 0x84b8, 0x84b8, 0x84b8,
- 0x84b8, 0x84b8, 0x84ba, 0x84b8, 0x84bd, 0x84b8, 0x84b8, 0x84b8,
- 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8,
- 0x1078, 0x1328, 0x1078, 0x753d, 0x007c, 0x007e, 0x027e, 0xa016,
- 0x1078, 0x15ec, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079,
- 0x84c9, 0x84d2, 0x84d0, 0x84d0, 0x84de, 0x84d0, 0x84d0, 0x84d0,
- 0x1078, 0x1328, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x057e,
- 0x0d7e, 0x0e7e, 0x2071, 0xa880, 0x7224, 0x6212, 0x7220, 0x1078,
- 0x8a30, 0x0040, 0x8503, 0x2268, 0x6800, 0xa086, 0x0000, 0x0040,
- 0x8503, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x8503, 0x0c7e, 0x2d60,
- 0x1078, 0x874a, 0x0c7f, 0x0040, 0x8503, 0x6803, 0x0002, 0x6007,
- 0x0086, 0x0078, 0x8505, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x0f7e, 0x2278, 0x1078, 0x4893, 0x0f7f,
- 0x0040, 0x851d, 0x6824, 0xd0ec, 0x0040, 0x851d, 0x0c7e, 0x2260,
- 0x603f, 0x0000, 0x1078, 0x8cfa, 0x0c7f, 0x0e7f, 0x0d7f, 0x057f,
- 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x8533, 0x6004, 0xa08a,
- 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c, 0x10c8, 0x1328, 0xa082,
- 0x0085, 0x0079, 0x8542, 0xa186, 0x0027, 0x0040, 0x853b, 0xa186,
- 0x0014, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0x8549, 0x854b, 0x854b, 0x8549, 0x8549, 0x8549,
- 0x8549, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0xa186, 0x0013, 0x00c0, 0x855c, 0x6004, 0xa082,
- 0x0085, 0x2008, 0x0078, 0x8597, 0xa186, 0x0027, 0x00c0, 0x857f,
- 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b,
- 0x0029, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d,
- 0x1078, 0x6109, 0x007c, 0x1078, 0x7583, 0x0078, 0x857a, 0xa186,
- 0x0014, 0x00c0, 0x857b, 0x1078, 0x6010, 0x0d7e, 0x6010, 0x2068,
- 0x1078, 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000,
- 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8571, 0x0079,
- 0x8599, 0x85a2, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85bd,
- 0x1078, 0x1328, 0x1078, 0x6010, 0x6030, 0xa08c, 0xff00, 0x810f,
- 0xa186, 0x0039, 0x0040, 0x85b0, 0xa186, 0x0035, 0x00c0, 0x85b4,
- 0x2001, 0xa5a0, 0x0078, 0x85b6, 0x2001, 0xa5a1, 0x2004, 0x6016,
- 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x6030,
- 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x85cb, 0xa186,
- 0x0035, 0x00c0, 0x85cf, 0x2001, 0xa5a0, 0x0078, 0x85d1, 0x2001,
- 0xa5a1, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x6109, 0x007c,
- 0xa182, 0x008c, 0x00c8, 0x85e2, 0xa182, 0x0085, 0x0048, 0x85e2,
- 0x0079, 0x85e5, 0x1078, 0x7583, 0x007c, 0x85ec, 0x85ec, 0x85ec,
- 0x85ec, 0x85ee, 0x8643, 0x85ec, 0x1078, 0x1328, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8601, 0x6030, 0xa08c, 0xff00,
- 0x810f, 0xa186, 0x0039, 0x0040, 0x865a, 0xa186, 0x0035, 0x0040,
- 0x865a, 0x0d7e, 0x1078, 0x8bf4, 0x1078, 0x8a44, 0x0040, 0x8625,
- 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8616,
- 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x8621, 0xd0bc, 0x0040,
- 0x861d, 0x684b, 0x0002, 0x0078, 0x8621, 0x684b, 0x0005, 0x1078,
- 0x8cc0, 0x6847, 0x0000, 0x1078, 0x4982, 0x2c68, 0x1078, 0x74d7,
- 0x0040, 0x863e, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xa88e,
- 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x6918, 0x611a,
- 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5bf8, 0x2d60, 0x1078,
- 0x753d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f,
- 0x0040, 0x8680, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035,
- 0x0040, 0x865a, 0xa186, 0x001e, 0x0040, 0x865a, 0xa186, 0x0039,
- 0x00c0, 0x8680, 0x0d7e, 0x2c68, 0x1078, 0x8ef5, 0x00c0, 0x86a4,
- 0x1078, 0x74d7, 0x0040, 0x867d, 0x6106, 0x6003, 0x0001, 0x601f,
- 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930,
- 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6920,
- 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x2d60, 0x0078, 0x86a4,
- 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86a4, 0x6837,
- 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8693, 0xc0ec, 0x6852, 0x684b,
- 0x0006, 0x0078, 0x869e, 0xd0bc, 0x0040, 0x869a, 0x684b, 0x0002,
- 0x0078, 0x869e, 0x684b, 0x0005, 0x1078, 0x8cc0, 0x6847, 0x0000,
- 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x007c,
- 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86b8,
- 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, 0x4982,
- 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x86ca, 0xa186, 0x0014,
- 0x0040, 0x86ca, 0xa186, 0x0027, 0x0040, 0x86ca, 0x1078, 0x7583,
- 0x0078, 0x86d0, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109,
- 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182,
- 0x0101, 0x00c8, 0x86dd, 0x0078, 0x86df, 0x2009, 0x0100, 0x2130,
- 0x2069, 0xa898, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
- 0x001d, 0x1078, 0x8739, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040,
- 0x86f3, 0x1078, 0x13aa, 0x1078, 0x1381, 0x0040, 0x871d, 0x8528,
- 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d,
- 0x00c8, 0x8709, 0x2608, 0xad90, 0x000f, 0x1078, 0x8739, 0x0078,
- 0x871d, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f,
- 0x1078, 0x8739, 0x0078, 0x86f3, 0x0f7f, 0x852f, 0xa5ad, 0x0003,
- 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x8722, 0x0f7f, 0x852f, 0xa5ad,
- 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff,
- 0x0040, 0x8737, 0x6804, 0xa07d, 0x0040, 0x8735, 0x6807, 0x0000,
- 0x1078, 0x4982, 0x2f68, 0x0078, 0x872a, 0x1078, 0x4982, 0x0f7f,
- 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x873f, 0x8108, 0x810c,
- 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x8741,
- 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, 0x0001,
- 0x601c, 0xa084, 0x000f, 0x1079, 0x8766, 0x127f, 0x067f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, 0xa084,
- 0x000f, 0x1079, 0x8766, 0x067f, 0x127f, 0x007c, 0x8780, 0x876e,
- 0x877b, 0x879c, 0x876e, 0x877b, 0x879c, 0x877b, 0x1078, 0x1328,
- 0x037e, 0x2019, 0x0010, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003,
- 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
- 0x0d7e, 0x86ff, 0x00c0, 0x8797, 0x6010, 0x2068, 0x1078, 0x8a44,
- 0x0040, 0x8799, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4a60, 0x1078,
- 0x8cc0, 0x1078, 0x4982, 0x1078, 0x753d, 0xa085, 0x0001, 0x0d7f,
- 0x007c, 0xa006, 0x0078, 0x8797, 0x6000, 0xa08a, 0x0010, 0x10c8,
- 0x1328, 0x1079, 0x87a4, 0x007c, 0x87b4, 0x87d4, 0x87b6, 0x87f7,
- 0x87d0, 0x87b4, 0x877b, 0x8780, 0x8780, 0x877b, 0x877b, 0x877b,
- 0x877b, 0x877b, 0x877b, 0x877b, 0x1078, 0x1328, 0x86ff, 0x00c0,
- 0x87cd, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x87c2,
- 0x1078, 0x8cc0, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
- 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0xa085, 0x0001, 0x007c,
- 0x1078, 0x1749, 0x0078, 0x87b6, 0x0e7e, 0x2071, 0xa5ab, 0x7024,
- 0xac06, 0x00c0, 0x87dd, 0x1078, 0x6dda, 0x601c, 0xa084, 0x000f,
- 0xa086, 0x0006, 0x00c0, 0x87ef, 0x087e, 0x097e, 0x2049, 0x0001,
- 0x2c40, 0x1078, 0x7058, 0x097f, 0x087f, 0x0078, 0x87f1, 0x1078,
- 0x6cd2, 0x0e7f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c, 0x037e,
- 0x0e7e, 0x2071, 0xa5ab, 0x703c, 0xac06, 0x00c0, 0x8807, 0x2019,
- 0x0000, 0x1078, 0x6e6c, 0x0e7f, 0x037f, 0x0078, 0x87b6, 0x1078,
- 0x719a, 0x0e7f, 0x037f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c,
- 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x8818, 0x0c7f, 0x007c,
- 0x8827, 0x8895, 0x89cd, 0x8832, 0x8c01, 0x8827, 0x9a5b, 0x753d,
- 0x8895, 0x1078, 0x8c3b, 0x00c0, 0x8827, 0x1078, 0x7a05, 0x007c,
- 0x1078, 0x6010, 0x1078, 0x6109, 0x1078, 0x753d, 0x007c, 0x6017,
- 0x0001, 0x007c, 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a,
- 0x0010, 0x10c8, 0x1328, 0x1079, 0x883e, 0x007c, 0x884e, 0x8850,
- 0x8872, 0x8884, 0x8891, 0x884e, 0x8827, 0x8827, 0x8827, 0x8884,
- 0x8884, 0x884e, 0x884e, 0x884e, 0x884e, 0x888e, 0x1078, 0x1328,
- 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0xa5ab,
- 0x7024, 0xac06, 0x0040, 0x886e, 0x1078, 0x6cd2, 0x6007, 0x0085,
- 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa5a1, 0x2004, 0x6016,
- 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x6017, 0x0001,
- 0x0078, 0x886c, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852,
- 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010,
- 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x753d,
- 0x007c, 0x1078, 0x1749, 0x0078, 0x8872, 0x6000, 0xa08a, 0x0010,
- 0x10c8, 0x1328, 0x1079, 0x889d, 0x007c, 0x88ad, 0x882f, 0x88af,
- 0x88ad, 0x88af, 0x88af, 0x8828, 0x88ad, 0x8821, 0x8821, 0x88ad,
- 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x1078, 0x1328, 0x0d7e,
- 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c,
- 0x10c8, 0x1328, 0x1079, 0x88bd, 0x007c, 0x88c9, 0x8971, 0x88cb,
- 0x890b, 0x88cb, 0x890b, 0x88cb, 0x88d8, 0x88c9, 0x890b, 0x88c9,
- 0x88f5, 0x1078, 0x1328, 0x6004, 0xa08e, 0x0016, 0x0040, 0x8906,
- 0xa08e, 0x0004, 0x0040, 0x8906, 0xa08e, 0x0002, 0x0040, 0x8906,
- 0x6004, 0x1078, 0x8c3b, 0x0040, 0x898c, 0xa08e, 0x0021, 0x0040,
- 0x8990, 0xa08e, 0x0022, 0x0040, 0x898c, 0xa08e, 0x003d, 0x0040,
- 0x8990, 0xa08e, 0x0039, 0x0040, 0x8994, 0xa08e, 0x0035, 0x0040,
- 0x8994, 0xa08e, 0x001e, 0x0040, 0x8908, 0xa08e, 0x0001, 0x00c0,
- 0x8904, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f,
- 0xa086, 0x0006, 0x0040, 0x8906, 0x1078, 0x2813, 0x1078, 0x7a05,
- 0x1078, 0x8c01, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016,
- 0x0040, 0x8961, 0xa186, 0x0002, 0x00c0, 0x8934, 0x6018, 0x2068,
- 0x68a0, 0xd0bc, 0x00c0, 0x89b8, 0x6840, 0xa084, 0x00ff, 0xa005,
- 0x0040, 0x8934, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007,
- 0x6017, 0x0398, 0x1078, 0x74d7, 0x0040, 0x8934, 0x2d00, 0x601a,
- 0x601f, 0x0001, 0x0078, 0x8961, 0x0d7f, 0x0c7f, 0x6004, 0xa08e,
- 0x0002, 0x00c0, 0x8952, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086,
- 0x007e, 0x00c0, 0x8952, 0x2009, 0xa332, 0x2104, 0xc085, 0x200a,
- 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x0e7f, 0x1078, 0x7a05,
- 0x0078, 0x8956, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x2839, 0x127f, 0x0e7f, 0x1078, 0x8c01,
- 0x007c, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
- 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0d7f, 0x0c7f, 0x0078,
- 0x8960, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x8961,
- 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x8934,
- 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078, 0x6109,
- 0x0d7f, 0x0c7f, 0x0078, 0x8960, 0x1078, 0x7a05, 0x0078, 0x8908,
- 0x1078, 0x7a28, 0x0078, 0x8908, 0x0d7e, 0x2c68, 0x6104, 0x1078,
- 0x8ef5, 0x0d7f, 0x0040, 0x89a0, 0x1078, 0x753d, 0x0078, 0x89b7,
- 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007,
- 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001,
- 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c,
- 0x0d7f, 0x0c7f, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x2839, 0x6013, 0x0000, 0x601f, 0x0007,
- 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, 0xa08a, 0x0010,
- 0x10c8, 0x1328, 0x1079, 0x89d5, 0x007c, 0x89e5, 0x89e5, 0x89e5,
- 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x8827, 0x89e5,
- 0x882f, 0x89e7, 0x882f, 0x89f5, 0x89e5, 0x1078, 0x1328, 0x6004,
- 0xa086, 0x008b, 0x0040, 0x89f5, 0x6007, 0x008b, 0x6003, 0x000d,
- 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c, 0x1078, 0x8bf4, 0x1078,
- 0x8a44, 0x0040, 0x8a2d, 0x1078, 0x2813, 0x0d7e, 0x1078, 0x8a44,
- 0x0040, 0x8a0f, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
- 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, 0x4982, 0x2c68,
- 0x1078, 0x74d7, 0x0040, 0x8a1d, 0x6818, 0x601a, 0x0c7e, 0x2d60,
- 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x8a1e, 0x2d60, 0x0d7f, 0x6013,
- 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
- 0x5c45, 0x1078, 0x6109, 0x0078, 0x8a2f, 0x1078, 0x8c01, 0x007c,
- 0xa284, 0x000f, 0x00c0, 0x8a41, 0xa282, 0xaa00, 0x0048, 0x8a41,
- 0x2001, 0xa315, 0x2004, 0xa202, 0x00c8, 0x8a41, 0xa085, 0x0001,
- 0x007c, 0xa006, 0x0078, 0x8a40, 0x027e, 0x0e7e, 0x2071, 0xa300,
- 0x6210, 0x7058, 0xa202, 0x0048, 0x8a56, 0x705c, 0xa202, 0x00c8,
- 0x8a56, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, 0xa006, 0x0078,
- 0x8a53, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, 0x2091, 0x8000,
- 0x2061, 0xaa00, 0x2071, 0xa300, 0x7344, 0x7060, 0xa302, 0x00c8,
- 0x8a83, 0x601c, 0xa206, 0x00c0, 0x8a7b, 0x1078, 0x8d66, 0x0040,
- 0x8a7b, 0x1078, 0x8c3b, 0x00c0, 0x8a77, 0x1078, 0x7a05, 0x0c7e,
- 0x1078, 0x753d, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
- 0x8a83, 0x0078, 0x8a64, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f,
- 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa434, 0x210c, 0x81ff,
- 0x0040, 0x8aa1, 0x2061, 0xaa00, 0x2071, 0xa300, 0x017e, 0x1078,
- 0x74d7, 0x017f, 0x0040, 0x8aa4, 0x611a, 0x1078, 0x2813, 0x1078,
- 0x753d, 0xa006, 0x0078, 0x8aa6, 0xa085, 0x0001, 0x017f, 0x0c7f,
- 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e,
- 0x1078, 0x74d7, 0x057f, 0x0040, 0x8ac3, 0x6612, 0x651a, 0x601f,
- 0x0003, 0x2009, 0x004b, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
- 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8abf, 0x0c7e, 0x057e,
- 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x74d7, 0x057f,
- 0x0040, 0x8af1, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e,
- 0x2560, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2009,
- 0x004c, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f,
- 0x007c, 0xa006, 0x0078, 0x8aed, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e,
- 0x1078, 0x74d7, 0x2c78, 0x0c7f, 0x0040, 0x8b0e, 0x7e12, 0x2c00,
- 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60,
- 0x2009, 0x004d, 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f,
- 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7,
- 0x2c78, 0x0c7f, 0x0040, 0x8b2c, 0x7e12, 0x2c00, 0x781a, 0x781f,
- 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x004e,
- 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c,
- 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7, 0x2c78, 0x0c7f,
- 0x0040, 0x8b4a, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021,
- 0x0004, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x0052, 0x1078, 0x756c,
- 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, 0x097e, 0x077e,
- 0x127e, 0x2091, 0x8000, 0x1078, 0x46a7, 0x0040, 0x8b5b, 0x2001,
- 0x8b53, 0x0078, 0x8b61, 0x1078, 0x466d, 0x0040, 0x8b6a, 0x2001,
- 0x8b5b, 0x007e, 0xa00e, 0x2400, 0x1078, 0x4a60, 0x1078, 0x4982,
- 0x007f, 0x007a, 0x2418, 0x1078, 0x5fa7, 0x62a0, 0x087e, 0x2041,
- 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, 0x5d6d, 0x087f, 0x1078,
- 0x5c78, 0x2f08, 0x2648, 0x1078, 0x9c38, 0x613c, 0x81ff, 0x1040,
- 0x5e21, 0x127f, 0x077f, 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091,
- 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8b9e, 0x660a,
- 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078,
- 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
- 0x8b9b, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7,
- 0x017f, 0x0040, 0x8bba, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00,
- 0x6012, 0x2009, 0x0021, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
- 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8bb7, 0x0c7e, 0x127e, 0x2091,
- 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8bd6, 0x660a,
- 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078,
- 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
- 0x8bd3, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7,
- 0x017f, 0x0040, 0x8bf1, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
- 0x2009, 0x0000, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f,
- 0x007c, 0xa006, 0x0078, 0x8bee, 0x027e, 0x0d7e, 0x6218, 0x2268,
- 0x6a3c, 0x82ff, 0x0040, 0x8bfe, 0x8211, 0x6a3e, 0x0d7f, 0x027f,
- 0x007c, 0x007e, 0x6000, 0xa086, 0x0000, 0x0040, 0x8c13, 0x6013,
- 0x0000, 0x601f, 0x0007, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078,
- 0xa134, 0x603f, 0x0000, 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e,
- 0x2031, 0xa352, 0x2634, 0xd6e4, 0x0040, 0x8c23, 0x6618, 0x2660,
- 0x6e48, 0x1078, 0x461b, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e,
- 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x8c38, 0xa08e, 0x0003,
- 0x0040, 0x8c38, 0xa08e, 0x0004, 0x0040, 0x8c38, 0xa085, 0x0001,
- 0x017f, 0x007f, 0x007c, 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040,
- 0x8c48, 0x6838, 0xd0fc, 0x0040, 0x8c48, 0xa006, 0x0078, 0x8c4a,
- 0xa085, 0x0001, 0x0d7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091,
- 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8c67, 0x611a,
- 0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x2813, 0x2009, 0x0028,
- 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
- 0x0078, 0x8c64, 0xa186, 0x0015, 0x00c0, 0x8c7f, 0x2011, 0xa31f,
- 0x2204, 0xa086, 0x0074, 0x00c0, 0x8c7f, 0x1078, 0x7d0d, 0x6003,
- 0x0001, 0x6007, 0x0029, 0x1078, 0x5c45, 0x0078, 0x8c83, 0x1078,
- 0x7a05, 0x1078, 0x753d, 0x007c, 0xa186, 0x0016, 0x00c0, 0x8c8e,
- 0x2001, 0x0004, 0x1078, 0x443f, 0x0078, 0x8caf, 0xa186, 0x0015,
- 0x00c0, 0x8cb3, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0014, 0x00c0,
- 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x457d, 0x0d7f, 0x1078,
- 0x7dba, 0x00c0, 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f,
- 0xa005, 0x0040, 0x8cb3, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078,
- 0x7608, 0x0078, 0x8cb7, 0x1078, 0x7a05, 0x1078, 0x753d, 0x007c,
- 0x6848, 0xa086, 0x0005, 0x00c0, 0x8cbf, 0x1078, 0x8cc0, 0x007c,
- 0x6850, 0xc0ad, 0x6852, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7014,
- 0xd0e4, 0x0040, 0x8cd5, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007,
- 0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x0c7e,
- 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8ce4, 0x601c,
- 0xa084, 0x000f, 0x1079, 0x8ce6, 0x0c7f, 0x007c, 0x8827, 0x8cf1,
- 0x8cf4, 0x8cf7, 0x9f00, 0x9f1c, 0x9f1f, 0x8827, 0x8827, 0x1078,
- 0x1328, 0x0005, 0x0005, 0x007c, 0x0005, 0x0005, 0x007c, 0x1078,
- 0x8cfa, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0040, 0x8d29,
- 0x1078, 0x74d7, 0x00c0, 0x8d0a, 0x2001, 0xa5a2, 0x2004, 0x783e,
- 0x0078, 0x8d29, 0x7818, 0x601a, 0x781c, 0xa086, 0x0003, 0x0040,
- 0x8d17, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0078, 0x8d1b, 0x7808,
- 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035,
- 0x6003, 0x0001, 0x7920, 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109,
- 0x2f60, 0x0f7f, 0x007c, 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e,
- 0x0001, 0x0040, 0x8d3c, 0xa086, 0x0005, 0x0040, 0x8d40, 0xa006,
- 0x602a, 0x602e, 0x0078, 0x8d51, 0x6824, 0xc0f4, 0xc0d5, 0x6826,
- 0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103,
- 0x00c8, 0x8d37, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a,
- 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6920,
- 0x6122, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x6803, 0x0002, 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e,
- 0x6004, 0xa08e, 0x0034, 0x0040, 0x8d8b, 0xa08e, 0x0035, 0x0040,
- 0x8d8b, 0xa08e, 0x0036, 0x0040, 0x8d8b, 0xa08e, 0x0037, 0x0040,
- 0x8d8b, 0xa08e, 0x0038, 0x0040, 0x8d8b, 0xa08e, 0x0039, 0x0040,
- 0x8d8b, 0xa08e, 0x003a, 0x0040, 0x8d8b, 0xa08e, 0x003b, 0x0040,
- 0x8d8b, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x00c0, 0x8d98, 0xa085, 0x0001, 0x0078, 0x8da7,
- 0x6024, 0xd0f4, 0x00c0, 0x8da6, 0xc0f5, 0x6026, 0x6010, 0x2078,
- 0x7828, 0x603a, 0x782c, 0x6036, 0x1078, 0x1749, 0xa006, 0x0f7f,
- 0x007c, 0x007e, 0x017e, 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa59c,
- 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x1078, 0x5a98, 0x2001,
- 0xa5a0, 0x82ff, 0x00c0, 0x8dbe, 0x2011, 0x0002, 0x2202, 0x2001,
- 0xa59e, 0x200c, 0x8000, 0x2014, 0x2071, 0xa58c, 0x711a, 0x721e,
- 0x2001, 0x0064, 0x1078, 0x5a98, 0x2001, 0xa5a1, 0x82ff, 0x00c0,
- 0x8dd3, 0x2011, 0x0002, 0x2202, 0x2009, 0xa5a2, 0xa280, 0x000a,
- 0x200a, 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e,
- 0x0e7e, 0x2001, 0xa5a0, 0x2003, 0x0028, 0x2001, 0xa5a1, 0x2003,
- 0x0014, 0x2071, 0xa58c, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001,
- 0xa5a2, 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e,
- 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8e0e,
- 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078,
- 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
- 0x8e0b, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa300, 0xa186, 0x0015,
- 0x00c0, 0x8e40, 0x707c, 0xa086, 0x0018, 0x00c0, 0x8e40, 0x6010,
- 0x2068, 0x6a3c, 0xd2e4, 0x00c0, 0x8e34, 0x2c78, 0x1078, 0x62c6,
- 0x0040, 0x8e48, 0x7068, 0x6a50, 0xa206, 0x00c0, 0x8e3c, 0x706c,
- 0x6a54, 0xa206, 0x00c0, 0x8e3c, 0x6218, 0xa290, 0x0028, 0x2214,
- 0x2009, 0x0000, 0x1078, 0x285b, 0x1078, 0x7608, 0x0078, 0x8e44,
- 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c,
- 0x704c, 0xa080, 0x293f, 0x2004, 0x6a54, 0xa206, 0x0040, 0x8e34,
- 0x0078, 0x8e3c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
- 0x74d7, 0x017f, 0x0040, 0x8e6a, 0x611a, 0x601f, 0x0001, 0x2d00,
- 0x6012, 0x2009, 0x0043, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
- 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e67, 0x0d7e, 0x0e7e, 0x0f7e,
- 0x2071, 0xa300, 0xa186, 0x0015, 0x00c0, 0x8e93, 0x707c, 0xa086,
- 0x0004, 0x00c0, 0x8e93, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078,
- 0x62c6, 0x0040, 0x8e9b, 0x7068, 0x6a08, 0xa206, 0x00c0, 0x8e8f,
- 0x706c, 0x6a0c, 0xa206, 0x00c0, 0x8e8f, 0x1078, 0x2813, 0x1078,
- 0x7608, 0x0078, 0x8e97, 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f,
- 0x0e7f, 0x0d7f, 0x007c, 0x704c, 0xa080, 0x293f, 0x2004, 0x6a0c,
- 0xa206, 0x0040, 0x8e8d, 0x0078, 0x8e8f, 0x017e, 0x027e, 0x684c,
- 0xd0ac, 0x0040, 0x8ebd, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040,
- 0x8ebd, 0x6860, 0xa106, 0x00c0, 0x8eb9, 0x685c, 0xa206, 0x0040,
- 0x8ebd, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c,
- 0x0e7e, 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582,
- 0x0001, 0x0048, 0x8ef2, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000,
- 0x0040, 0x8ede, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x8eda,
- 0x0078, 0x8ecd, 0x2061, 0xaa00, 0x0078, 0x8ecd, 0x6003, 0x0008,
- 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x8eee,
- 0x754a, 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00,
- 0x0078, 0x8ee9, 0xa006, 0x0078, 0x8eeb, 0x0c7e, 0x027e, 0x017e,
- 0xa186, 0x0035, 0x0040, 0x8eff, 0x6a34, 0x0078, 0x8f00, 0x6a28,
- 0x1078, 0x8a30, 0x0040, 0x8f29, 0x2260, 0x611c, 0xa186, 0x0003,
- 0x0040, 0x8f0e, 0xa186, 0x0006, 0x00c0, 0x8f25, 0x6834, 0xa206,
- 0x0040, 0x8f1d, 0x6838, 0xa206, 0x00c0, 0x8f25, 0x6108, 0x6834,
- 0xa106, 0x00c0, 0x8f25, 0x0078, 0x8f22, 0x6008, 0x6938, 0xa106,
- 0x00c0, 0x8f25, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f,
- 0x007c, 0xa085, 0x0001, 0x0078, 0x8f25, 0x067e, 0x6000, 0xa0b2,
- 0x0010, 0x10c8, 0x1328, 0x1079, 0x8f37, 0x067f, 0x007c, 0x8f47,
- 0x93bb, 0x94d3, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f81,
- 0x955e, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x1078,
- 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079,
- 0x8f53, 0x067f, 0x007c, 0x8f63, 0x99f6, 0x8f63, 0x8f63, 0x8f63,
- 0x8f63, 0x8f63, 0x8f63, 0x99b4, 0x9a44, 0x8f63, 0xa053, 0xa087,
- 0xa053, 0xa087, 0x8f63, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2,
- 0x0010, 0x10c8, 0x1328, 0x1079, 0x8f6f, 0x067f, 0x007c, 0x8f7f,
- 0x969f, 0x976a, 0x9798, 0x9813, 0x8f7f, 0x9919, 0x98c1, 0x956a,
- 0x9988, 0x999e, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x1078,
- 0x1328, 0xa1b2, 0x0044, 0x10c8, 0x1328, 0x2100, 0x0079, 0x8f88,
- 0x8fc8, 0x919a, 0x8fc8, 0x8fc8, 0x8fc8, 0x91a2, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fca,
- 0x902d, 0x9038, 0x9081, 0x909c, 0x911b, 0x918b, 0x8fc8, 0x8fc8,
- 0x91a6, 0x8fc8, 0x8fc8, 0x91b5, 0x91bc, 0x8fc8, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x91ea, 0x8fc8, 0x8fc8, 0x91f5, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x920a, 0x8fc8, 0x8fc8, 0x8fc8,
- 0x9291, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x9305,
- 0x1078, 0x1328, 0x1078, 0x4897, 0x00c0, 0x8fd7, 0x2001, 0xa332,
- 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x8fdf, 0x6007,
- 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195, 0x1078,
- 0x4887, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270,
- 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x017f,
- 0x2e60, 0x1078, 0x471b, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
- 0x6618, 0x0c7e, 0x2660, 0x1078, 0x4513, 0x0c7f, 0xa6b0, 0x0001,
- 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x901f, 0x1078,
- 0x9b6c, 0x00c0, 0x907b, 0x1078, 0x9afd, 0x00c0, 0x901b, 0x6007,
- 0x0008, 0x0078, 0x9195, 0x6007, 0x0009, 0x0078, 0x9195, 0x1078,
- 0x9d45, 0x0040, 0x9029, 0x1078, 0x9b6c, 0x0040, 0x9013, 0x0078,
- 0x907b, 0x6013, 0x1900, 0x0078, 0x901b, 0x6106, 0x1078, 0x9aa8,
- 0x6007, 0x0006, 0x0078, 0x9195, 0x6007, 0x0007, 0x0078, 0x9195,
- 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x0d7e, 0x6618, 0x2668, 0x6e04,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x905d, 0xa686,
- 0x0004, 0x0040, 0x905d, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
- 0x0040, 0x905d, 0xa686, 0x0004, 0x0040, 0x905d, 0xa686, 0x0005,
- 0x0040, 0x905d, 0x0d7f, 0x0078, 0x907b, 0x1078, 0x9bd2, 0x00c0,
- 0x9076, 0xa686, 0x0006, 0x00c0, 0x906f, 0x027e, 0x6218, 0xa290,
- 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f, 0x1078,
- 0x457d, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x9195, 0x6007, 0x000b,
- 0x0d7f, 0x0078, 0x9195, 0x1078, 0x2813, 0x6007, 0x0001, 0x0078,
- 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x6618, 0x0d7e, 0x2668,
- 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x907b, 0x027e, 0x6218,
- 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f,
- 0x6007, 0x000c, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x90a9,
- 0x2001, 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0,
- 0x90b1, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078,
- 0x9195, 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684,
- 0x00ff, 0xa082, 0x0006, 0x0048, 0x90f5, 0xa6b4, 0xff00, 0x8637,
- 0xa686, 0x0004, 0x0040, 0x90c8, 0xa686, 0x0006, 0x00c0, 0x907b,
- 0x1078, 0x9be1, 0x00c0, 0x90d0, 0x6007, 0x000e, 0x0078, 0x9195,
- 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427,
- 0x047e, 0x1078, 0x2813, 0x047f, 0x017e, 0xa006, 0x2009, 0xa352,
- 0x210c, 0xd1a4, 0x0040, 0x90ef, 0x2009, 0x0029, 0x1078, 0x9ec0,
- 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f,
- 0x047f, 0x6007, 0x0001, 0x0078, 0x9195, 0x2001, 0x0001, 0x1078,
- 0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019,
- 0xa305, 0x2011, 0xa890, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f,
- 0x157f, 0xa005, 0x0040, 0x9115, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0006, 0x0040, 0x90c8, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007,
- 0x0009, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x9128, 0x2001,
- 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x9130,
- 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195,
- 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff,
- 0xa082, 0x0006, 0x0048, 0x9178, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0004, 0x0040, 0x9147, 0xa686, 0x0006, 0x00c0, 0x907b, 0x1078,
- 0x9c0c, 0x00c0, 0x9153, 0x1078, 0x9afd, 0x00c0, 0x9153, 0x6007,
- 0x0010, 0x0078, 0x9195, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424,
- 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2813, 0x047f, 0x017e,
- 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040, 0x9172, 0x2009,
- 0x0029, 0x1078, 0x9ec0, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5,
- 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x9195,
- 0x1078, 0x9d45, 0x0040, 0x9185, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0006, 0x0040, 0x9147, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007,
- 0x0009, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x1078,
- 0x9343, 0x00c0, 0x907b, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078,
- 0x5c45, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45,
- 0x0078, 0x9199, 0x6007, 0x0005, 0x0078, 0x919c, 0x1078, 0xa0bf,
- 0x00c0, 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6007, 0x0020,
- 0x6003, 0x0001, 0x1078, 0x5c45, 0x007c, 0x6007, 0x0023, 0x6003,
- 0x0001, 0x1078, 0x5c45, 0x007c, 0x1078, 0xa0bf, 0x00c0, 0x9340,
- 0x1078, 0x9343, 0x00c0, 0x907b, 0x017e, 0x027e, 0x2011, 0xa890,
- 0x2214, 0x2c08, 0x1078, 0x9e8c, 0x00c0, 0x91de, 0x2160, 0x6007,
- 0x0026, 0x6013, 0x1700, 0x2011, 0xa889, 0x2214, 0xa296, 0xffff,
- 0x00c0, 0x91e3, 0x6007, 0x0025, 0x0078, 0x91e3, 0x1078, 0x753d,
- 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5c45, 0x027f,
- 0x017f, 0x007c, 0x6106, 0x1078, 0x9363, 0x6007, 0x002b, 0x0078,
- 0x9195, 0x6007, 0x002c, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0,
- 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6106, 0x1078, 0x9368,
- 0x00c0, 0x9206, 0x6007, 0x002e, 0x0078, 0x9195, 0x6007, 0x002f,
- 0x0078, 0x9195, 0x0e7e, 0x0d7e, 0x0c7e, 0x6018, 0xa080, 0x0001,
- 0x200c, 0xa184, 0x00ff, 0xa086, 0x0006, 0x0040, 0x9223, 0xa184,
- 0xff00, 0x8007, 0xa086, 0x0006, 0x0040, 0x9223, 0x0c7f, 0x0d7f,
- 0x0e7f, 0x0078, 0x919a, 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040,
- 0x928d, 0x2071, 0xa88c, 0x7010, 0x6036, 0x7014, 0x603a, 0x7108,
- 0x720c, 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9241, 0x6018,
- 0x2068, 0x6810, 0xa106, 0x00c0, 0x9241, 0x6814, 0xa206, 0x0040,
- 0x9265, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x9281, 0x2069,
- 0xa300, 0x686c, 0xa206, 0x00c0, 0x9281, 0x6868, 0xa106, 0x00c0,
- 0x9281, 0x7210, 0x1078, 0x8a30, 0x0040, 0x9287, 0x1078, 0x9f31,
- 0x0040, 0x9287, 0x622a, 0x6007, 0x0036, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7214, 0xa286, 0xffff,
- 0x0040, 0x9277, 0x1078, 0x8a30, 0x0040, 0x9287, 0xa280, 0x0002,
- 0x2004, 0x7110, 0xa106, 0x00c0, 0x9287, 0x0078, 0x9252, 0x7210,
- 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x2160, 0x0040, 0x9287, 0x0078,
- 0x9252, 0x6007, 0x0037, 0x6013, 0x1500, 0x0078, 0x925d, 0x6007,
- 0x0037, 0x6013, 0x1700, 0x0078, 0x925d, 0x6007, 0x0012, 0x0078,
- 0x925d, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007,
- 0xa086, 0x0006, 0x00c0, 0x919a, 0x0e7e, 0x0d7e, 0x0c7e, 0x2001,
- 0xa371, 0x2004, 0xd0e4, 0x0040, 0x92fd, 0x2069, 0xa300, 0x2071,
- 0xa88c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x00c0,
- 0x92ba, 0x7208, 0x0c7e, 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x0c7f,
- 0x0040, 0x92f1, 0x1078, 0x8a30, 0x0040, 0x92f1, 0x0c7e, 0x027e,
- 0x2260, 0x1078, 0x874a, 0x027f, 0x0c7f, 0x7118, 0xa18c, 0xff00,
- 0x810f, 0xa186, 0x0001, 0x0040, 0x92db, 0xa186, 0x0005, 0x0040,
- 0x92d5, 0xa186, 0x0007, 0x00c0, 0x92e5, 0xa280, 0x0004, 0x2004,
- 0xa005, 0x0040, 0x92e5, 0x057e, 0x7510, 0x7614, 0x1078, 0x9f46,
- 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x6007, 0x003b, 0x602b,
- 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x0078,
- 0x92e1, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, 0x6003,
- 0x0001, 0x1078, 0x5bf8, 0x0078, 0x92e1, 0x6007, 0x003b, 0x602b,
- 0x000b, 0x6013, 0x0000, 0x0078, 0x925d, 0x0e7e, 0x027e, 0x1078,
- 0x4897, 0x0040, 0x933a, 0x1078, 0x4887, 0x1078, 0xa148, 0x00c0,
- 0x9338, 0x2071, 0xa300, 0x70c8, 0xc085, 0x70ca, 0x0f7e, 0x2079,
- 0x0100, 0x7294, 0xa284, 0x00ff, 0x706a, 0x78e6, 0xa284, 0xff00,
- 0x726c, 0xa205, 0x706e, 0x78ea, 0x0f7f, 0x70d3, 0x0000, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9331, 0x2011, 0xa5c4, 0x2013,
- 0x07d0, 0xd0ac, 0x00c0, 0x933a, 0x1078, 0x260d, 0x0078, 0x933a,
- 0x1078, 0xa178, 0x027f, 0x0e7f, 0x1078, 0x753d, 0x0078, 0x9199,
- 0x1078, 0x753d, 0x007c, 0x0d7e, 0x067e, 0x6618, 0x2668, 0x6e04,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x9360, 0xa686,
- 0x0004, 0x0040, 0x9360, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
- 0x0040, 0x9360, 0xa686, 0x0004, 0x0040, 0x9360, 0xa085, 0x0001,
- 0x067f, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x9397, 0x0d7f, 0x007c,
- 0x0d7e, 0x1078, 0x93a6, 0x00c0, 0x9390, 0x680c, 0xa08c, 0xff00,
- 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4,
- 0x0040, 0x937e, 0x2009, 0x0001, 0x0078, 0x938c, 0xd1ec, 0x0040,
- 0x9390, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x1078, 0x24e3, 0x00c0,
- 0x9390, 0x2110, 0x2009, 0x0000, 0x1078, 0x285b, 0x0078, 0x9394,
- 0xa085, 0x0001, 0x0078, 0x9395, 0xa006, 0x0d7f, 0x007c, 0x2069,
- 0xa88d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x93a4, 0x6013, 0x0000,
- 0xa085, 0x0001, 0x0078, 0x93a5, 0xa006, 0x007c, 0x6013, 0x0000,
- 0x2069, 0xa88c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x00c0,
- 0x93ba, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0040, 0x93ba,
- 0xa08e, 0x0010, 0x007c, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328,
- 0xa1b6, 0x0013, 0x00c0, 0x93c7, 0x2008, 0x0079, 0x93da, 0xa1b6,
- 0x0027, 0x0040, 0x93cf, 0xa1b6, 0x0014, 0x10c0, 0x1328, 0x2001,
- 0x0007, 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0x941a, 0x941c, 0x941a, 0x941a, 0x941a, 0x941c,
- 0x9424, 0x94ae, 0x9471, 0x94ae, 0x9485, 0x94ae, 0x9424, 0x94ae,
- 0x94a6, 0x94ae, 0x94a6, 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a,
- 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a,
- 0x941c, 0x941a, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x941a, 0x94ae,
- 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a,
- 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941c,
- 0x94ae, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a, 0x941a,
- 0x941a, 0x941a, 0x1078, 0x1328, 0x1078, 0x6010, 0x6003, 0x0002,
- 0x1078, 0x6109, 0x0078, 0x94b4, 0x0f7e, 0x2079, 0xa351, 0x7804,
- 0x0f7f, 0xd0ac, 0x00c0, 0x94ae, 0x2001, 0x0000, 0x1078, 0x442b,
- 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x94ae,
- 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9448, 0x6010,
- 0xa005, 0x0040, 0x9448, 0x0c7f, 0x1078, 0x35f7, 0x0078, 0x94ae,
- 0x0c7f, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002, 0x00c0, 0x9457,
- 0x0f7e, 0x2079, 0xa300, 0x788c, 0x8000, 0x788e, 0x0f7f, 0x2001,
- 0x0002, 0x1078, 0x443f, 0x1078, 0x6010, 0x601f, 0x0001, 0x6003,
- 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0c7e,
- 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x58e1, 0x0c7f, 0x0078,
- 0x94b4, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00,
- 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0xa686, 0x0004, 0x0040,
- 0x94ae, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0xa300, 0x2004,
- 0xa086, 0x0003, 0x00c0, 0x948e, 0x1078, 0x35f7, 0x2001, 0x0006,
- 0x1078, 0x94b5, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4,
- 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0x2001, 0x0006,
- 0x0078, 0x94ac, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0x0006,
- 0x1078, 0x94b5, 0x0078, 0x94ae, 0x1078, 0x4472, 0x1078, 0x6010,
- 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x017e, 0x0d7e, 0x6118,
- 0x2168, 0x6900, 0xd184, 0x0040, 0x94d0, 0x6104, 0xa18e, 0x000a,
- 0x00c0, 0x94c8, 0x699c, 0xd1a4, 0x00c0, 0x94c8, 0x2001, 0x0007,
- 0x1078, 0x443f, 0x2001, 0x0000, 0x1078, 0x442b, 0x1078, 0x2839,
- 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084,
- 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0xa1b6,
- 0x0015, 0x00c0, 0x94e7, 0x1079, 0x94ee, 0x0078, 0x94ed, 0xa1b6,
- 0x0016, 0x10c0, 0x1328, 0x1079, 0x94fa, 0x007c, 0x7ad0, 0x7ad0,
- 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x9547, 0x9506, 0x7ad0, 0x7ad0,
- 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0,
- 0x9547, 0x954f, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x0f7e, 0x2079,
- 0xa351, 0x7804, 0xd0ac, 0x00c0, 0x952d, 0x6018, 0xa07d, 0x0040,
- 0x952d, 0x7800, 0xd0f4, 0x00c0, 0x9519, 0x7810, 0xa005, 0x00c0,
- 0x952d, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078,
- 0x443f, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
- 0x5c45, 0x1078, 0x6109, 0x0078, 0x9545, 0x2011, 0xa883, 0x2204,
- 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x9545, 0x0c7e, 0x1078,
- 0x4501, 0x0040, 0x9540, 0x0c7f, 0x1078, 0x753d, 0x0078, 0x9545,
- 0x1078, 0x4235, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0x6604,
- 0xa6b6, 0x001e, 0x00c0, 0x954e, 0x1078, 0x753d, 0x007c, 0x1078,
- 0x7d0a, 0x00c0, 0x955b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
- 0x5c45, 0x0078, 0x955d, 0x1078, 0x753d, 0x007c, 0x6004, 0xa08a,
- 0x0044, 0x10c8, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0xa182, 0x0040, 0x0079, 0x956e, 0x9581, 0x9581,
- 0x9581, 0x9581, 0x9583, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581,
- 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581,
- 0x9581, 0x1078, 0x1328, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e,
- 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x9594,
- 0x2021, 0x0000, 0x1078, 0xa111, 0x6106, 0x2071, 0xa880, 0x7444,
- 0xa4a4, 0xff00, 0x0040, 0x95eb, 0xa486, 0x2000, 0x00c0, 0x95a6,
- 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5a6d, 0x1078, 0x1381,
- 0x1040, 0x1328, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803,
- 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2,
- 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084,
- 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4982,
- 0x017f, 0xa486, 0x2000, 0x00c0, 0x95d3, 0x2019, 0x0017, 0x1078,
- 0x9e3b, 0x0078, 0x9645, 0xa486, 0x0400, 0x00c0, 0x95dd, 0x2019,
- 0x0002, 0x1078, 0x9dec, 0x0078, 0x9645, 0xa486, 0x0200, 0x00c0,
- 0x95e3, 0x1078, 0x9dd1, 0xa486, 0x1000, 0x00c0, 0x95e9, 0x1078,
- 0x9e20, 0x0078, 0x9645, 0x2069, 0xa62d, 0x6a00, 0xd284, 0x0040,
- 0x969b, 0xa284, 0x0300, 0x00c0, 0x9693, 0x6804, 0xa005, 0x0040,
- 0x9683, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1366, 0x0040, 0x964c,
- 0x7800, 0xd08c, 0x00c0, 0x9607, 0x7804, 0x8001, 0x7806, 0x6013,
- 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008,
- 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
- 0x6986, 0x6846, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286,
- 0x0002, 0x00c0, 0x9627, 0x684f, 0x0040, 0x0078, 0x9631, 0xa286,
- 0x0001, 0x00c0, 0x962f, 0x684f, 0x0080, 0x0078, 0x9631, 0x684f,
- 0x0000, 0x20a9, 0x000a, 0x2001, 0xa890, 0xad90, 0x0015, 0x200c,
- 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x9637, 0x200c, 0x6982,
- 0x8000, 0x200c, 0x697e, 0x1078, 0x4982, 0x027f, 0x047f, 0x157f,
- 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, 0x0001,
- 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645,
- 0x2069, 0xa892, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x00c0,
- 0x9677, 0x2069, 0xa880, 0x686c, 0xa084, 0x00ff, 0x017e, 0x6110,
- 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, 0x6007,
- 0x0043, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645, 0x6013,
- 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078,
- 0x6109, 0x0078, 0x9645, 0x6013, 0x0300, 0x0078, 0x9689, 0x6013,
- 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078,
- 0x6109, 0x0078, 0x9645, 0x6013, 0x0500, 0x0078, 0x9689, 0x6013,
- 0x0600, 0x0078, 0x9658, 0x6013, 0x0200, 0x0078, 0x9658, 0xa186,
- 0x0013, 0x00c0, 0x96b1, 0x6004, 0xa08a, 0x0040, 0x1048, 0x1328,
- 0xa08a, 0x0053, 0x10c8, 0x1328, 0xa082, 0x0040, 0x2008, 0x0079,
- 0x9725, 0xa186, 0x0051, 0x0040, 0x96be, 0xa186, 0x0047, 0x00c0,
- 0x96d7, 0x6004, 0xa086, 0x0041, 0x0040, 0x96e5, 0x2001, 0x0109,
- 0x2004, 0xd084, 0x0040, 0x96e5, 0x127e, 0x2091, 0x2200, 0x007e,
- 0x017e, 0x027e, 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f,
- 0x6000, 0xa086, 0x0002, 0x00c0, 0x96e5, 0x0078, 0x976a, 0xa186,
- 0x0027, 0x0040, 0x96df, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6004,
- 0xa082, 0x0040, 0x2008, 0x0079, 0x96e8, 0x1078, 0x7583, 0x007c,
- 0x96fb, 0x96fd, 0x96fd, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb,
- 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb,
- 0x96fb, 0x96fb, 0x96fb, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078,
- 0x6109, 0x037e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x9722, 0xad84,
- 0xf000, 0x0040, 0x9722, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc,
- 0x00c0, 0x9722, 0x2019, 0x0004, 0x1078, 0x9e70, 0x6013, 0x0000,
- 0x6014, 0xa005, 0x00c0, 0x9720, 0x2001, 0xa5a1, 0x2004, 0x6016,
- 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, 0x9738, 0x9757, 0x9741,
- 0x9764, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738,
- 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738,
- 0x1078, 0x1328, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400,
- 0x200a, 0x1078, 0x6010, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4,
- 0x0040, 0x9752, 0x6003, 0x0007, 0x2009, 0x0043, 0x1078, 0x756c,
- 0x0078, 0x9754, 0x6003, 0x0002, 0x1078, 0x6109, 0x007c, 0x1078,
- 0x6010, 0x1078, 0xa0c6, 0x00c0, 0x9761, 0x1078, 0x5a41, 0x1078,
- 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x2009, 0x0041,
- 0x0078, 0x98c1, 0xa182, 0x0040, 0x0079, 0x976e, 0x9781, 0x9783,
- 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9784, 0x9781, 0x9781,
- 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x978f,
- 0x9781, 0x1078, 0x1328, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1,
- 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0d7e,
- 0x1078, 0x5a41, 0x0d7f, 0x1078, 0xa134, 0x1078, 0x753d, 0x007c,
- 0xa182, 0x0040, 0x0079, 0x979c, 0x97af, 0x97af, 0x97af, 0x97af,
- 0x97af, 0x97af, 0x97af, 0x97b1, 0x97af, 0x97b4, 0x97df, 0x97af,
- 0x97af, 0x97af, 0x97af, 0x97df, 0x97af, 0x97af, 0x97af, 0x1078,
- 0x1328, 0x1078, 0x7583, 0x007c, 0x1078, 0x60b8, 0x1078, 0x61d3,
- 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x97ca, 0xa08c,
- 0x0003, 0xa18e, 0x0002, 0x0040, 0x97d2, 0x2009, 0x0041, 0x0d7f,
- 0x0078, 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41,
- 0x0d7f, 0x007c, 0x1078, 0xa0c6, 0x0040, 0x97d8, 0x0d7f, 0x007c,
- 0x1078, 0x5a41, 0x1078, 0x753d, 0x0d7f, 0x0078, 0x97d1, 0x037e,
- 0x1078, 0x60b8, 0x1078, 0x61d3, 0x6010, 0x0d7e, 0x2068, 0x6018,
- 0x2004, 0xd0bc, 0x0040, 0x97ff, 0x684c, 0xa084, 0x0003, 0xa086,
- 0x0002, 0x0040, 0x97fb, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880,
- 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0078, 0x9810, 0x2019,
- 0x0004, 0x1078, 0x9e70, 0x6014, 0xa005, 0x00c0, 0x980c, 0x2001,
- 0xa5a1, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007,
- 0x0d7f, 0x037f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9821, 0x6004,
- 0xa086, 0x0042, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x6109,
- 0x007c, 0xa186, 0x0027, 0x0040, 0x9829, 0xa186, 0x0014, 0x00c0,
- 0x9839, 0x6004, 0xa086, 0x0042, 0x10c0, 0x1328, 0x2001, 0x0007,
- 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109,
- 0x007c, 0xa182, 0x0040, 0x0079, 0x983d, 0x9850, 0x9850, 0x9850,
- 0x9850, 0x9850, 0x9850, 0x9850, 0x9852, 0x985e, 0x9850, 0x9850,
- 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850,
- 0x1078, 0x1328, 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20,
- 0x2c10, 0x1078, 0x15ec, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e,
- 0x2068, 0x6810, 0x6a14, 0x6118, 0x210c, 0xd1bc, 0x0040, 0x987d,
- 0x6124, 0xd1f4, 0x00c0, 0x987d, 0x007e, 0x047e, 0x057e, 0x6c7c,
- 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028,
- 0xa529, 0x652a, 0x057f, 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9891,
- 0x684c, 0xd0fc, 0x0040, 0x9889, 0x2009, 0x0041, 0x0d7f, 0x0078,
- 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41, 0x0d7f,
- 0x007c, 0x007e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x007f,
- 0x0040, 0x989e, 0x6003, 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa30d,
- 0x210c, 0xd19c, 0x0040, 0x98a8, 0x6003, 0x0007, 0x0078, 0x98aa,
- 0x6003, 0x0006, 0x1078, 0x98b0, 0x1078, 0x5a43, 0x0d7f, 0x007c,
- 0xd2fc, 0x0040, 0x98bc, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000,
- 0x2009, 0x0009, 0x0078, 0x98be, 0x2009, 0x0015, 0x6a6a, 0x6866,
- 0x007c, 0xa182, 0x0040, 0x0048, 0x98c7, 0x0079, 0x98d4, 0xa186,
- 0x0013, 0x0040, 0x98cf, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6024,
- 0xd0dc, 0x1040, 0x1328, 0x007c, 0x98e7, 0x98ee, 0x98fa, 0x9906,
- 0x98e7, 0x98e7, 0x98e7, 0x9915, 0x98e7, 0x98e9, 0x98e9, 0x98e7,
- 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x1078,
- 0x1328, 0x6024, 0xd0dc, 0x1040, 0x1328, 0x007c, 0x6003, 0x0001,
- 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109,
- 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0003,
- 0x6106, 0x2c10, 0x1078, 0x1cab, 0x127e, 0x2091, 0x8000, 0x1078,
- 0x5c64, 0x1078, 0x61d3, 0x127f, 0x007c, 0xa016, 0x1078, 0x15ec,
- 0x007c, 0x127e, 0x2091, 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040,
- 0x1079, 0x9926, 0x0d7f, 0x037f, 0x127f, 0x007c, 0x9936, 0x9938,
- 0x994d, 0x996c, 0x9936, 0x9936, 0x9936, 0x9984, 0x9936, 0x9936,
- 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x1078, 0x1328,
- 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003,
- 0xa39e, 0x0003, 0x0040, 0x9962, 0x6003, 0x0001, 0x6106, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c,
- 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040,
- 0x9962, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x1078, 0x6109,
- 0x0078, 0x9987, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004,
- 0x1078, 0x9e70, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c, 0xd0fc,
- 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9962,
- 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x5c64,
- 0x1078, 0x61d3, 0x0078, 0x9987, 0xa016, 0x1078, 0x15ec, 0x007c,
- 0x1078, 0x6010, 0x6110, 0x81ff, 0x0040, 0x9999, 0x0d7e, 0x2168,
- 0x1078, 0xa181, 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f,
- 0x0d7f, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x1078, 0x60b8,
- 0x6110, 0x81ff, 0x0040, 0x99af, 0x0d7e, 0x2168, 0x1078, 0xa181,
- 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f, 0x0d7f, 0x1078,
- 0x8c01, 0x1078, 0x61d3, 0x007c, 0xa182, 0x0085, 0x0079, 0x99b8,
- 0x99c1, 0x99bf, 0x99bf, 0x99cd, 0x99bf, 0x99bf, 0x99bf, 0x1078,
- 0x1328, 0x6003, 0x000b, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091,
- 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078,
- 0xa0bf, 0x0040, 0x99d7, 0x1078, 0x753d, 0x0078, 0x99f3, 0x2071,
- 0xa880, 0x7224, 0x6212, 0x7220, 0x1078, 0x9d10, 0x0040, 0x99e4,
- 0x6007, 0x0086, 0x0078, 0x99ed, 0x6007, 0x0087, 0x7224, 0xa296,
- 0xffff, 0x00c0, 0x99ed, 0x6007, 0x0086, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013,
- 0x00c0, 0x9a07, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a,
- 0x008c, 0x10c8, 0x1328, 0xa082, 0x0085, 0x0079, 0x9a1e, 0xa186,
- 0x0027, 0x0040, 0x9a13, 0xa186, 0x0014, 0x0040, 0x9a13, 0x1078,
- 0x7583, 0x0078, 0x9a1d, 0x2001, 0x0007, 0x1078, 0x4472, 0x1078,
- 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x9a25, 0x9a27,
- 0x9a27, 0x9a25, 0x9a25, 0x9a25, 0x9a25, 0x1078, 0x1328, 0x1078,
- 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0xa182, 0x0085,
- 0x1048, 0x1328, 0xa182, 0x008c, 0x10c8, 0x1328, 0xa182, 0x0085,
- 0x0079, 0x9a3a, 0x9a41, 0x9a41, 0x9a41, 0x9a43, 0x9a41, 0x9a41,
- 0x9a41, 0x1078, 0x1328, 0x007c, 0xa186, 0x0013, 0x0040, 0x9a54,
- 0xa186, 0x0014, 0x0040, 0x9a54, 0xa186, 0x0027, 0x0040, 0x9a54,
- 0x1078, 0x7583, 0x0078, 0x9a5a, 0x1078, 0x6010, 0x1078, 0x8c01,
- 0x1078, 0x6109, 0x007c, 0x037e, 0x1078, 0xa134, 0x603f, 0x0000,
- 0x2019, 0x000b, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003, 0x0007,
- 0x037f, 0x007c, 0x127e, 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40,
- 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x00c0,
- 0x9aa5, 0x077e, 0x2c38, 0x1078, 0x7105, 0x077f, 0x00c0, 0x9aa5,
- 0x6000, 0xa086, 0x0000, 0x0040, 0x9aa5, 0x601c, 0xa086, 0x0007,
- 0x0040, 0x9aa5, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x9a96,
- 0x1078, 0xa134, 0x601f, 0x0007, 0x1078, 0x1749, 0x6010, 0x2068,
- 0x1078, 0x8a44, 0x0040, 0x9a9e, 0x1078, 0x9e70, 0x0d7f, 0x6013,
- 0x0000, 0x1078, 0xa134, 0x601f, 0x0007, 0x037f, 0x127f, 0x007c,
- 0x0f7e, 0x0c7e, 0x037e, 0x157e, 0x2079, 0xa880, 0x7938, 0x783c,
- 0x1078, 0x24e3, 0x00c0, 0x9af6, 0x017e, 0x0c7e, 0x1078, 0x4501,
- 0x00c0, 0x9af6, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9, 0x0004,
- 0x1078, 0x7e55, 0x00c0, 0x9af6, 0x017f, 0x027f, 0x027e, 0x017e,
- 0x2019, 0x0029, 0x1078, 0x71e0, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x077f, 0x017f, 0x077e, 0x2039, 0x0000,
- 0x1078, 0x9c38, 0x077f, 0x1078, 0x471b, 0x027e, 0x6204, 0xa294,
- 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9aea, 0xa286, 0x0004,
- 0x00c0, 0x9aed, 0x62a0, 0x1078, 0x28d5, 0x027f, 0x017f, 0x1078,
- 0x4235, 0x6612, 0x6516, 0xa006, 0x0078, 0x9af8, 0x0c7f, 0x017f,
- 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x0e7e,
- 0x017e, 0x2009, 0xa31f, 0x2104, 0xa086, 0x0074, 0x00c0, 0x9b60,
- 0x2069, 0xa88e, 0x690c, 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908,
- 0xa184, 0x8000, 0x0040, 0x9b5c, 0x6018, 0x2070, 0x7010, 0xa084,
- 0x00ff, 0x0040, 0x9b1f, 0x7000, 0xd0f4, 0x0040, 0x9b23, 0xa184,
- 0x0800, 0x0040, 0x9b5c, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54,
- 0x6914, 0x2069, 0xa8ae, 0x6904, 0x81ff, 0x00c0, 0x9b48, 0x690c,
- 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908, 0x81ff, 0x00c0, 0x9b4c,
- 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54, 0x6918, 0xa18a, 0x0001,
- 0x0048, 0x9b5c, 0x0078, 0x9b66, 0x6013, 0x0100, 0x0078, 0x9b62,
- 0x6013, 0x0300, 0x0078, 0x9b62, 0x6013, 0x0500, 0x0078, 0x9b62,
- 0x6013, 0x0700, 0x0078, 0x9b62, 0x6013, 0x0900, 0x0078, 0x9b62,
- 0x6013, 0x0b00, 0x0078, 0x9b62, 0x6013, 0x0f00, 0x0078, 0x9b62,
- 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x9b67, 0xa006, 0x017f,
- 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e,
- 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006,
- 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040, 0x9b90, 0xa394, 0xff00,
- 0x8217, 0xa286, 0x0006, 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040,
- 0x9b90, 0x0c7e, 0x2d60, 0x1078, 0x4513, 0x0c7f, 0x0078, 0x9bcb,
- 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55,
- 0x00c0, 0x9bcc, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9, 0x0004,
- 0x1078, 0x7e55, 0x00c0, 0x9bcc, 0x047e, 0x017e, 0x6aa0, 0xa294,
- 0x00ff, 0x8227, 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040,
- 0x9bb8, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6800, 0xc0e5, 0x6802,
- 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078,
- 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2001, 0x0007, 0x1078,
- 0x4472, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f,
- 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xa88e, 0x6800, 0xa086, 0x0800,
- 0x0040, 0x9bde, 0x6013, 0x0000, 0x0078, 0x9bdf, 0xa006, 0x0d7f,
- 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079,
- 0xa88c, 0x7930, 0x7834, 0x1078, 0x24e3, 0x00c0, 0x9c05, 0x1078,
- 0x4501, 0x00c0, 0x9c05, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9,
- 0x0004, 0x1078, 0x7e55, 0x00c0, 0x9c05, 0x2011, 0xa894, 0xac98,
- 0x0006, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x157f, 0x037f, 0x027f,
- 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e,
- 0x037e, 0x157e, 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078,
- 0x24e3, 0x00c0, 0x9c31, 0x1078, 0x4501, 0x00c0, 0x9c31, 0x2011,
- 0xa896, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0,
- 0x9c31, 0x2011, 0xa89a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078,
- 0x7e55, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c,
- 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e,
- 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, 0xa5b4, 0x252c, 0x2021,
- 0xa5ba, 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060,
- 0x81ff, 0x0040, 0x9c59, 0x8001, 0xa602, 0x00c8, 0x9cc3, 0x0078,
- 0x9c5c, 0xa606, 0x0040, 0x9cc3, 0x2100, 0xac06, 0x0040, 0x9cb9,
- 0x1078, 0x9ee5, 0x0040, 0x9cb9, 0x671c, 0xa786, 0x0001, 0x0040,
- 0x9cde, 0xa786, 0x0004, 0x0040, 0x9cde, 0xa786, 0x0007, 0x0040,
- 0x9cb9, 0x2500, 0xac06, 0x0040, 0x9cb9, 0x2400, 0xac06, 0x0040,
- 0x9cb9, 0x1078, 0x9ef9, 0x00c0, 0x9cb9, 0x88ff, 0x0040, 0x9c84,
- 0x6020, 0xa906, 0x00c0, 0x9cb9, 0x0d7e, 0x6000, 0xa086, 0x0004,
- 0x00c0, 0x9c8e, 0x017e, 0x1078, 0x1749, 0x017f, 0xa786, 0x0008,
- 0x00c0, 0x9c9d, 0x1078, 0x8c3b, 0x00c0, 0x9c9d, 0x1078, 0x7a05,
- 0x0d7f, 0x1078, 0x8c01, 0x0078, 0x9cb9, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x9cb6, 0xa786, 0x0003, 0x00c0, 0x9ccd, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa181, 0x017e, 0x1078,
- 0x8cb8, 0x1078, 0x4982, 0x017f, 0x1078, 0x8bf4, 0x0d7f, 0x1078,
- 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8,
- 0x9cc3, 0x0078, 0x9c4c, 0x127f, 0x027f, 0x047f, 0x057f, 0x067f,
- 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
- 0x9ca7, 0xa386, 0x0005, 0x0040, 0x9cdb, 0x1078, 0xa181, 0x1078,
- 0x9e70, 0x0078, 0x9cb6, 0x0d7f, 0x0078, 0x9cb9, 0x1078, 0x9ef9,
- 0x00c0, 0x9cb9, 0x81ff, 0x0040, 0x9cb9, 0xa180, 0x0001, 0x2004,
- 0xa086, 0x0018, 0x0040, 0x9cf3, 0xa180, 0x0001, 0x2004, 0xa086,
- 0x002d, 0x00c0, 0x9cb9, 0x6000, 0xa086, 0x0002, 0x00c0, 0x9cb9,
- 0x1078, 0x8c27, 0x0040, 0x9d04, 0x1078, 0x8c3b, 0x00c0, 0x9cb9,
- 0x1078, 0x7a05, 0x0078, 0x9d0c, 0x1078, 0x2839, 0x1078, 0x8c3b,
- 0x00c0, 0x9d0c, 0x1078, 0x7a05, 0x1078, 0x8c01, 0x0078, 0x9cb9,
- 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x9e8c, 0x017f,
- 0x0040, 0x9d1f, 0x601c, 0xa084, 0x000f, 0x1079, 0x9d22, 0x0e7f,
- 0x0c7f, 0x007c, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a,
- 0x9d2c, 0x9d2a, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080,
- 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020,
- 0x1078, 0x9ec0, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078,
- 0x9a6a, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078,
- 0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019,
- 0xa305, 0x2011, 0xa896, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f,
- 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x087e, 0x077e,
- 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2061, 0xaa00,
- 0x2079, 0x0001, 0x8fff, 0x0040, 0x9dc3, 0x2071, 0xa300, 0x7644,
- 0x7060, 0x8001, 0xa602, 0x00c8, 0x9dc3, 0x88ff, 0x0040, 0x9d7e,
- 0x2800, 0xac06, 0x00c0, 0x9db9, 0x2079, 0x0000, 0x1078, 0x9ee5,
- 0x0040, 0x9db9, 0x2400, 0xac06, 0x0040, 0x9db9, 0x671c, 0xa786,
- 0x0006, 0x00c0, 0x9db9, 0xa786, 0x0007, 0x0040, 0x9db9, 0x88ff,
- 0x00c0, 0x9d9d, 0x6018, 0xa206, 0x00c0, 0x9db9, 0x85ff, 0x0040,
- 0x9d9d, 0x6020, 0xa106, 0x00c0, 0x9db9, 0x0d7e, 0x6000, 0xa086,
- 0x0004, 0x00c0, 0x9da9, 0x1078, 0xa134, 0x601f, 0x0007, 0x1078,
- 0x1749, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x9db3, 0x047e,
- 0x1078, 0x9e70, 0x047f, 0x0d7f, 0x1078, 0x8c01, 0x88ff, 0x00c0,
- 0x9dcd, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8,
- 0x9dc3, 0x0078, 0x9d6a, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f,
- 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078,
- 0x9dc4, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001,
- 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, 0x0000, 0x1078,
- 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x1078,
- 0x9d5b, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e,
- 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000,
- 0x017e, 0x037e, 0x1078, 0x4501, 0x00c0, 0x9e14, 0x2c10, 0x057e,
- 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x097e, 0x2049,
- 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078,
- 0x7105, 0x1078, 0x9d5b, 0x057f, 0x037f, 0x017f, 0x8108, 0x00f0,
- 0x9df8, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c,
- 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001,
- 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f,
- 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x2c20, 0x1078, 0x9d5b,
- 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e, 0x0c7e,
- 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x037e,
- 0x1078, 0x4501, 0x00c0, 0x9e64, 0x2c10, 0x087e, 0x2041, 0x0000,
- 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa111, 0x047f, 0x097e,
- 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000,
- 0x1078, 0x7105, 0x1078, 0x9d5b, 0x037f, 0x017f, 0x8108, 0x00f0,
- 0x9e46, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c,
- 0x017e, 0x0f7e, 0xad82, 0xca00, 0x0048, 0x9e89, 0xad82, 0xffff,
- 0x00c8, 0x9e89, 0x6800, 0xa07d, 0x0040, 0x9e86, 0x6803, 0x0000,
- 0x6b52, 0x1078, 0x4982, 0x2f68, 0x0078, 0x9e7a, 0x6b52, 0x1078,
- 0x4982, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061,
- 0xaa00, 0x2071, 0xa300, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8,
- 0x9ebb, 0x2100, 0xac06, 0x0040, 0x9ead, 0x6000, 0xa086, 0x0000,
- 0x0040, 0x9ead, 0x6008, 0xa206, 0x00c0, 0x9ead, 0x6018, 0xa1a0,
- 0x0006, 0x2424, 0xa406, 0x0040, 0x9eb7, 0xace0, 0x0010, 0x2001,
- 0xa315, 0x2004, 0xac02, 0x00c8, 0x9ebb, 0x0078, 0x9e91, 0xa085,
- 0x0001, 0x0078, 0x9ebc, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c,
- 0x0d7e, 0x007e, 0x1078, 0x1381, 0x007f, 0x1040, 0x1328, 0x6837,
- 0x010d, 0x685e, 0x027e, 0x2010, 0x1078, 0x8a30, 0x2001, 0x0000,
- 0x0040, 0x9ed6, 0x2200, 0xa080, 0x0008, 0x2004, 0x027f, 0x684a,
- 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a,
- 0x685a, 0x1078, 0x4982, 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000,
- 0x0040, 0x9ef8, 0xa786, 0x0001, 0x0040, 0x9ef8, 0xa786, 0x000a,
- 0x0040, 0x9ef8, 0xa786, 0x0009, 0x0040, 0x9ef8, 0xa085, 0x0001,
- 0x007c, 0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c,
- 0x017e, 0x6004, 0xa08e, 0x001e, 0x00c0, 0x9f1a, 0x8007, 0x6130,
- 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b,
- 0x601f, 0x0005, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8,
- 0x1078, 0x6109, 0x017f, 0x007c, 0x0005, 0x0005, 0x007c, 0x6024,
- 0xd0e4, 0x0040, 0x9f30, 0xd0cc, 0x0040, 0x9f2a, 0x1078, 0x8cfa,
- 0x0078, 0x9f30, 0x1078, 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d,
- 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0079, 0x9f38,
- 0x9f41, 0x9f41, 0x9f41, 0x9f43, 0x9f41, 0x9f43, 0x9f43, 0x9f41,
- 0x9f43, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa280, 0x0007,
- 0x2004, 0xa084, 0x000f, 0x0079, 0x9f4d, 0x9f56, 0x9f56, 0x9f56,
- 0x9f56, 0x9f56, 0x9f56, 0x9f61, 0x9f56, 0x9f56, 0x6007, 0x003b,
- 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8,
- 0x007c, 0x0c7e, 0x2260, 0x1078, 0xa134, 0x603f, 0x0000, 0x6024,
- 0xc0f4, 0xc0cc, 0x6026, 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007,
- 0x00c0, 0x9fc2, 0x6810, 0xa005, 0x0040, 0x9f7f, 0xa080, 0x0013,
- 0x2004, 0xd0fc, 0x00c0, 0x9f7f, 0x0d7f, 0x0078, 0x9f56, 0x6007,
- 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7e,
- 0x2d60, 0x6100, 0xa186, 0x0002, 0x00c0, 0xa050, 0x6010, 0xa005,
- 0x00c0, 0x9f99, 0x6000, 0xa086, 0x0007, 0x10c0, 0x1328, 0x0078,
- 0xa050, 0xa08c, 0xf000, 0x00c0, 0x9fa5, 0x0078, 0x9fa5, 0x2068,
- 0x6800, 0xa005, 0x00c0, 0x9f9f, 0x2d00, 0xa080, 0x0013, 0x2004,
- 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, 0x9fbe, 0x6010, 0x2068,
- 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852,
- 0x2009, 0x0043, 0x1078, 0x98c1, 0x0078, 0xa050, 0x2009, 0x0041,
- 0x0078, 0xa04a, 0xa186, 0x0005, 0x00c0, 0xa009, 0x6810, 0xa080,
- 0x0013, 0x2004, 0xd0bc, 0x00c0, 0x9fd0, 0x0d7f, 0x0078, 0x9f56,
- 0xd0b4, 0x0040, 0x9fd8, 0xd0fc, 0x1040, 0x1328, 0x0078, 0x9f72,
- 0x6007, 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109,
- 0x0c7e, 0x2d60, 0x6100, 0xa186, 0x0002, 0x0040, 0x9feb, 0xa186,
- 0x0004, 0x00c0, 0xa050, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0003,
- 0x00c0, 0x9ff8, 0x7004, 0xac06, 0x00c0, 0x9ff8, 0x7003, 0x0000,
- 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000,
- 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078,
- 0xa04a, 0x037e, 0x0d7e, 0x0d7e, 0x1078, 0x1381, 0x037f, 0x1040,
- 0x1328, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b,
- 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872,
- 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6018, 0xa080, 0x0028, 0x2004,
- 0xa084, 0x00ff, 0x8007, 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000,
- 0x6d6a, 0x6e66, 0x686f, 0x0001, 0x1078, 0x4982, 0x2019, 0x0045,
- 0x6008, 0x2068, 0x1078, 0x9a6a, 0x2d00, 0x600a, 0x601f, 0x0006,
- 0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f,
- 0x0078, 0xa051, 0x603f, 0x0000, 0x6003, 0x0007, 0x1078, 0x98c1,
- 0x0c7f, 0x0d7f, 0x007c, 0xa186, 0x0013, 0x00c0, 0xa05d, 0x6004,
- 0xa082, 0x0085, 0x2008, 0x0079, 0xa077, 0xa186, 0x0027, 0x00c0,
- 0xa070, 0x1078, 0x6010, 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019,
- 0x0004, 0x1078, 0x9e70, 0x0d7f, 0x037f, 0x1078, 0x6109, 0x007c,
- 0xa186, 0x0014, 0x0040, 0xa061, 0x1078, 0x7583, 0x007c, 0xa080,
- 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa080, 0x1078, 0x1328,
- 0x1078, 0x6010, 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0xa182,
- 0x008c, 0x00c8, 0xa091, 0xa182, 0x0085, 0x0048, 0xa091, 0x0079,
- 0xa094, 0x1078, 0x7583, 0x007c, 0xa09b, 0xa09b, 0xa09b, 0xa09b,
- 0xa09d, 0xa0bc, 0xa09b, 0x1078, 0x1328, 0x0d7e, 0x2c68, 0x1078,
- 0x74d7, 0x0040, 0xa0b7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009,
- 0xa88e, 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x600b,
- 0xffff, 0x6918, 0x611a, 0x601f, 0x0004, 0x1078, 0x5bf8, 0x2d60,
- 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x753d, 0x007c, 0x0e7e,
- 0x6018, 0x2070, 0x7000, 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa080,
- 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa110, 0x2001, 0xa371, 0x2004,
- 0xd0ec, 0x0040, 0xa110, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026,
- 0xd1ac, 0x0040, 0xa0ee, 0x0f7e, 0x2c78, 0x1078, 0x488f, 0x0f7f,
- 0x0040, 0xa0ee, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x2009, 0xa371,
- 0x210c, 0xd1f4, 0x00c0, 0xa10e, 0x0078, 0xa100, 0x2009, 0xa371,
- 0x210c, 0xd1f4, 0x0040, 0xa0fa, 0x6024, 0xc0e4, 0x6026, 0xa006,
- 0x0078, 0xa110, 0x2001, 0xa5a2, 0x200c, 0x8103, 0xa100, 0x603e,
- 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa10b, 0xa088,
- 0x0003, 0x0078, 0xa103, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001,
- 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, 0x2e04,
- 0x2060, 0x8cff, 0x0040, 0xa130, 0x84ff, 0x00c0, 0xa123, 0x6020,
- 0xa106, 0x00c0, 0xa12b, 0x600c, 0x2072, 0x1078, 0x5a41, 0x1078,
- 0x753d, 0x0078, 0xa12d, 0xacf0, 0x0003, 0x2e64, 0x0078, 0xa119,
- 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, 0x002b,
- 0x2d04, 0xa005, 0x0040, 0xa146, 0xac06, 0x0040, 0xa144, 0x2d04,
- 0xa0e8, 0x0003, 0x0078, 0xa138, 0x600c, 0x206a, 0x0d7f, 0x007c,
- 0x027e, 0x037e, 0x157e, 0x2011, 0xa325, 0x2204, 0xa084, 0x00ff,
- 0x2019, 0xa88e, 0x2334, 0xa636, 0x00c0, 0xa174, 0x8318, 0x2334,
- 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa174, 0x2011, 0xa890,
- 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0,
- 0xa174, 0x2011, 0xa894, 0x6018, 0xa098, 0x0006, 0x20a9, 0x0004,
- 0x1078, 0x7e55, 0x00c0, 0xa174, 0x157f, 0x037f, 0x027f, 0x007c,
- 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x1078, 0x260d, 0x0e7f,
- 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, 0xa18a,
- 0x1078, 0xa18c, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, 0x007c,
- 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x017e,
- 0x127e, 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba,
- 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060, 0xa606,
- 0x0040, 0xa1e4, 0x671c, 0xa786, 0x0001, 0x0040, 0xa1b3, 0xa786,
- 0x0008, 0x00c0, 0xa1da, 0x2500, 0xac06, 0x0040, 0xa1da, 0x2400,
- 0xac06, 0x0040, 0xa1da, 0x1078, 0x9ee5, 0x0040, 0xa1da, 0x1078,
- 0x9ef9, 0x00c0, 0xa1da, 0x6000, 0xa086, 0x0004, 0x00c0, 0xa1cc,
- 0x017e, 0x1078, 0x1749, 0x017f, 0x1078, 0x8c27, 0x00c0, 0xa1d2,
- 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0, 0xa1d8, 0x1078, 0x7a05,
- 0x1078, 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02,
- 0x00c8, 0xa1e4, 0x0078, 0xa1a3, 0x127f, 0x017f, 0x027f, 0x047f,
- 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x007e,
- 0x0e7e, 0x2091, 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa1fb,
- 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa201, 0x7030, 0x8000,
- 0x7032, 0xd5ac, 0x0040, 0xa208, 0x2071, 0xa34a, 0x1078, 0xa237,
- 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
- 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa219, 0x7034, 0x8000,
- 0x7036, 0xd5b4, 0x0040, 0xa21f, 0x7030, 0x8000, 0x7032, 0xd5ac,
- 0x0040, 0xa226, 0x2071, 0xa34a, 0x1078, 0xa237, 0x0e7f, 0x007f,
- 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
- 0xa342, 0x1078, 0xa237, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04,
- 0x8000, 0x2072, 0x00c8, 0xa240, 0x8e70, 0x2e04, 0x8000, 0x2072,
- 0x007c, 0x0e7e, 0x2071, 0xa340, 0x1078, 0xa237, 0x0e7f, 0x007c,
- 0x0e7e, 0x2071, 0xa344, 0x1078, 0xa237, 0x0e7f, 0x007c, 0x0001,
- 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
- 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x6286
-};
-
-/************************************************************************
- * *
- * --- ISP2200 Initiator/Target Firmware --- *
- * with Fabric (Public Loop), Point-point, and *
- * expanded LUN addressing for FCTAPE *
- * *
- ************************************************************************
- Copyright (C) 2000 and 2100 Qlogic Corporation
- (www.qlogic.com)
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-************************************************************************/
-
-/*
- * Firmware Version 2.01.27 (11:07 Dec 18, 2000)
- */
-
-static unsigned short risc_code_length2200 = 0x9cbf;
-static unsigned short risc_code2200[] = {
- 0x0470, 0x0000, 0x0000, 0x9cbf, 0x0000, 0x0002, 0x0001, 0x001b,
- 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
- 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
- 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972,
- 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
- 0x322e, 0x3031, 0x2e32, 0x3720, 0x2020, 0x2020, 0x2400, 0x20c1,
- 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xb1ff, 0x2091,
- 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x27b5,
- 0x2051, 0xad00, 0x2a70, 0x2029, 0xe400, 0x2031, 0xffff, 0x2039,
- 0xe3e9, 0x2021, 0x0200, 0x0804, 0x1449, 0x20a1, 0xacbf, 0xa00e,
- 0x20a9, 0x0741, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466,
- 0x746a, 0x20a1, 0xb400, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d,
- 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4,
- 0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218,
- 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xad00,
- 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001,
- 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0,
- 0x2009, 0xad00, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
- 0x41a4, 0x080c, 0x13fc, 0x080c, 0x1613, 0x080c, 0x17ac, 0x080c,
- 0x1e67, 0x080c, 0x492e, 0x080c, 0x801a, 0x080c, 0x159c, 0x080c,
- 0x2ce6, 0x080c, 0x5a01, 0x080c, 0x5045, 0x080c, 0x6487, 0x080c,
- 0x236a, 0x080c, 0x6686, 0x080c, 0x5fae, 0x080c, 0x226b, 0x080c,
- 0x2338, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820,
- 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b,
- 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
- 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3c98, 0x080c,
- 0x2d0d, 0x080c, 0x5a4f, 0x080c, 0x51f4, 0x080c, 0x64a2, 0x0c80,
- 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1203, 0x10e2, 0x12cc, 0x13f9,
- 0x13fa, 0x13fb, 0x080c, 0x14f6, 0x0005, 0x0126, 0x00f6, 0x2091,
- 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11d1, 0x080c, 0x1569,
- 0x080c, 0x574f, 0x0150, 0x080c, 0x5775, 0x1580, 0x2079, 0x0100,
- 0x7828, 0xa085, 0x1800, 0x782a, 0x0448, 0x080c, 0x569a, 0x7000,
- 0xa086, 0x0001, 0x1904, 0x11d1, 0x7088, 0xa086, 0x0028, 0x1904,
- 0x11d1, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f,
- 0x7a2a, 0x2011, 0x566e, 0x080c, 0x650d, 0x2011, 0x567b, 0x080c,
- 0x650d, 0x2011, 0x481b, 0x080c, 0x650d, 0x2011, 0x8030, 0x2019,
- 0x0000, 0x7087, 0x0000, 0x080c, 0x1d0f, 0x00e8, 0x080c, 0x41d1,
- 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11d1, 0x2011, 0x481b,
- 0x080c, 0x650d, 0x2011, 0x567b, 0x080c, 0x650d, 0x080c, 0x1d0f,
- 0x2001, 0xaf8c, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842,
- 0x2011, 0x8010, 0x73c8, 0x080c, 0x3c5c, 0x7238, 0xc284, 0x723a,
- 0x2001, 0xad0c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x79bd, 0x2011,
- 0x0004, 0x080c, 0x959c, 0x080c, 0x4f71, 0x080c, 0x574f, 0x0158,
- 0x080c, 0x4917, 0x0140, 0x7087, 0x0001, 0x70c3, 0x0000, 0x080c,
- 0x436e, 0x0804, 0x11d1, 0x080c, 0x502d, 0x0120, 0x7a0c, 0xc2b4,
- 0x7a0e, 0x0050, 0x080c, 0x9937, 0x70d0, 0xd09c, 0x1128, 0x709c,
- 0xa005, 0x0110, 0x080c, 0x48f5, 0x70db, 0x0000, 0x70d7, 0x0000,
- 0x72d0, 0x080c, 0x574f, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c,
- 0x2744, 0x2019, 0xaf8e, 0x211a, 0x001e, 0x704f, 0xffff, 0x7053,
- 0x00ef, 0x7073, 0x0000, 0x2079, 0xad51, 0x7804, 0xd0ac, 0x0108,
- 0xc295, 0x72d2, 0x080c, 0x574f, 0x0118, 0xa296, 0x0004, 0x0508,
- 0x2011, 0x0001, 0x080c, 0x959c, 0x7097, 0x0000, 0x709b, 0xffff,
- 0x7003, 0x0002, 0x00fe, 0x080c, 0x28fa, 0x2011, 0x0005, 0x080c,
- 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148, 0x00c6, 0x2061,
- 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e, 0x00ce, 0x012e,
- 0x00d0, 0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011,
- 0x0005, 0x080c, 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148,
- 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e,
- 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1118,
- 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x574f, 0x1118,
- 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x0016, 0x0026, 0x0036,
- 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x7cf4, 0x002e, 0x080c,
- 0xac07, 0x003e, 0x002e, 0x001e, 0x080c, 0x2bc9, 0x8108, 0x1f04,
- 0x11e5, 0x00ce, 0x706f, 0x0000, 0x7070, 0xa084, 0x00ff, 0x7072,
- 0x709f, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, 0xa086,
- 0x0002, 0x1904, 0x12ca, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c,
- 0x28fa, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d0, 0xd0ac, 0x1110,
- 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, 0x0103,
- 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0,
- 0x70d4, 0xa086, 0xffff, 0x0190, 0x080c, 0x2a56, 0x080c, 0x6c50,
- 0x70d0, 0xd094, 0x1904, 0x12ca, 0x2011, 0x0001, 0x2019, 0x0000,
- 0x080c, 0x2a8c, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d8, 0xa005,
- 0x1904, 0x12ca, 0x7094, 0xa005, 0x1904, 0x12ca, 0x70d0, 0xd0a4,
- 0x0118, 0xd0b4, 0x0904, 0x12ca, 0x080c, 0x502d, 0x1904, 0x12ca,
- 0x2001, 0xad52, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1118, 0x6000,
- 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x125b, 0x00ce, 0x015e,
- 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12ca, 0x0006, 0x0016,
- 0x2001, 0x0103, 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e,
- 0xa006, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xafb5, 0x40a1,
- 0x706c, 0x8007, 0x7170, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x2009,
- 0x0000, 0x080c, 0x14dc, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002,
- 0x40a1, 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, 0xafc5,
- 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709b, 0xffff,
- 0x080c, 0x1562, 0xa006, 0x080c, 0x261e, 0x080c, 0x3cce, 0x00f6,
- 0x2079, 0x0100, 0x080c, 0x5775, 0x0150, 0x080c, 0x574f, 0x7828,
- 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe,
- 0x2001, 0xafc8, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000,
- 0x080c, 0x7adf, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c, 0x6c50,
- 0x080c, 0x6d0d, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126,
- 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xad33, 0x2104, 0xa005,
- 0x1110, 0x080c, 0x2770, 0x2009, 0x00f7, 0x080c, 0x48de, 0x7940,
- 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040,
- 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954,
- 0xd1ac, 0x1904, 0x133a, 0x080c, 0x5761, 0x0158, 0x080c, 0x5775,
- 0x1128, 0x2001, 0xaf9d, 0x2003, 0x0000, 0x0070, 0x080c, 0x5757,
- 0x0dc0, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003,
- 0x0001, 0x080c, 0x569a, 0x0058, 0x080c, 0x574f, 0x0140, 0x2009,
- 0x00f8, 0x080c, 0x48de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
- 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x574f, 0x0138, 0x7824,
- 0xd0ac, 0x1904, 0x13e0, 0x1f04, 0x1319, 0x0070, 0x7824, 0x080c,
- 0x576b, 0x0118, 0xd0ac, 0x1904, 0x13e0, 0xa084, 0x1800, 0x0d98,
- 0x7003, 0x0001, 0x0804, 0x13e0, 0x2001, 0x0001, 0x080c, 0x261e,
- 0x0804, 0x13ef, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020,
- 0x20a9, 0x0046, 0x1d04, 0x1342, 0x2091, 0x6000, 0x1f04, 0x1342,
- 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000,
- 0x080c, 0x5761, 0x0158, 0x080c, 0x5775, 0x1128, 0x2001, 0xaf9d,
- 0x2003, 0x0000, 0x0070, 0x080c, 0x5757, 0x0dc0, 0x2001, 0xaf9d,
- 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x080c, 0x569a,
- 0x0020, 0x2009, 0x00f8, 0x080c, 0x48de, 0x20a9, 0x000e, 0xe000,
- 0x1f04, 0x136f, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852,
- 0x080c, 0x574f, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021,
- 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x574f,
- 0x05b8, 0x7824, 0xd0ac, 0x1904, 0x13e0, 0x080c, 0x5775, 0x1508,
- 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8,
- 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x139c, 0x2091, 0x6000,
- 0x1f04, 0x139c, 0x7824, 0xa084, 0x0068, 0x15a8, 0x2001, 0xaf9d,
- 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x7003, 0x0001,
- 0x0478, 0x8319, 0x1980, 0x2009, 0xad33, 0x2104, 0x8000, 0x200a,
- 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x2770, 0x00d8,
- 0x080c, 0x5761, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5726,
- 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, 0x7824,
- 0x080c, 0x576b, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09c8,
- 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x261e, 0x0048,
- 0x2001, 0xad33, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d,
- 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x015e,
- 0x003e, 0x000e, 0x080c, 0x1539, 0x012e, 0x00fe, 0x004e, 0x001e,
- 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2001, 0xaf9d, 0x2003,
- 0x0000, 0x7087, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002,
- 0x0218, 0x704f, 0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff,
- 0x706f, 0x0000, 0x7073, 0x0000, 0x080c, 0x9937, 0x2061, 0xaf8d,
- 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200,
- 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0,
- 0x2061, 0xaf95, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000,
- 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001,
- 0x601f, 0x0000, 0x2061, 0xafa6, 0x6003, 0x514c, 0x6007, 0x4f47,
- 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xad27, 0x2003, 0x0000,
- 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001,
- 0x1148, 0x2031, 0x8fff, 0x2039, 0xcc01, 0x2021, 0x0100, 0x2029,
- 0xcc00, 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8,
- 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009,
- 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011,
- 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800,
- 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011,
- 0x0003, 0x2019, 0x1485, 0x0804, 0x14d6, 0x2019, 0xaaaa, 0x2061,
- 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262,
- 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x1498, 0x04f0,
- 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000,
- 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff,
- 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002,
- 0x2019, 0x14b3, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14,
- 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14,
- 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061,
- 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011,
- 0x0001, 0x2019, 0x14d4, 0x0010, 0x0804, 0x144a, 0x3800, 0xa084,
- 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x4cdc,
- 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4,
- 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210,
- 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000,
- 0x0e04, 0x14f8, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084,
- 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900,
- 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126,
- 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, 0xb0c8, 0x2091, 0x2000,
- 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010,
- 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1,
- 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e,
- 0x2079, 0xad00, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8,
- 0x0005, 0x0006, 0x080c, 0x1584, 0x1518, 0x00f6, 0x2079, 0xad23,
- 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a,
- 0x2079, 0xad25, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a,
- 0x0070, 0x2079, 0xad25, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03,
- 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe,
- 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080,
- 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005,
- 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009,
- 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff,
- 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04,
- 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126,
- 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x1593, 0x2091, 0x6000, 0x1f04,
- 0x1593, 0x012e, 0x015e, 0x0005, 0x2071, 0xad00, 0x715c, 0x712e,
- 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7060,
- 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800,
- 0xd08c, 0x0148, 0x7060, 0xa086, 0xad00, 0x0128, 0x7063, 0xad00,
- 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, 0x74ae, 0x74b2, 0x0005,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x70b0, 0xa0ea,
- 0x0010, 0x0268, 0x8001, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e,
- 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e,
- 0x0cd8, 0x00e6, 0x2071, 0xad00, 0x0126, 0x2091, 0x8000, 0x70b0,
- 0x8001, 0x0260, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b,
- 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x702c, 0x206a,
- 0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x012e, 0x00ee, 0x0005,
- 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de,
- 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xad00, 0x70b0, 0xa08a, 0x0010,
- 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7007, 0x0000,
- 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085,
- 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000,
- 0x2071, 0xafec, 0x7018, 0xa088, 0xaff5, 0x220a, 0x8000, 0xa084,
- 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010,
- 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7004,
- 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee,
- 0x0005, 0x7000, 0x0002, 0x164f, 0x16b3, 0x16d0, 0x16d0, 0x7018,
- 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180,
- 0xaff5, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e,
- 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a,
- 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de,
- 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002,
- 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182,
- 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822,
- 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016,
- 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014,
- 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210,
- 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
- 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e,
- 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xadf9,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
- 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
- 0x7002, 0x700b, 0xadf4, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
- 0x0136, 0x0146, 0x0156, 0x2001, 0xae28, 0x209c, 0x20a1, 0x0014,
- 0x7803, 0x0026, 0x2001, 0xae29, 0x20ac, 0x53a6, 0x2099, 0xae2a,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
- 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
- 0x7002, 0x700b, 0xae25, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
- 0x0016, 0x00e6, 0x2071, 0xafec, 0x00f6, 0x2079, 0x0010, 0x7904,
- 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023,
- 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1649, 0x1713, 0x1741, 0x176b,
- 0x179b, 0x1712, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146,
- 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010,
- 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c,
- 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x167a,
- 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000,
- 0x080c, 0x1649, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200,
- 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830,
- 0x7832, 0x7834, 0x7836, 0x080c, 0x168f, 0x0005, 0x7008, 0xa080,
- 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005,
- 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
- 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000,
- 0x080c, 0x1649, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146,
- 0x0156, 0x2001, 0xadf7, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099,
- 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xadf9,
- 0x2004, 0xd0bc, 0x0148, 0x2001, 0xae02, 0x2004, 0xa080, 0x000d,
- 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007,
- 0x0000, 0x080c, 0x5ae6, 0x080c, 0x1649, 0x0005, 0x2011, 0x8003,
- 0x080c, 0x3c5c, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xae27,
- 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005, 0x2011,
- 0x8004, 0x080c, 0x3c5c, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079,
- 0x0030, 0x2071, 0xaffd, 0x7003, 0x0000, 0x700f, 0xb003, 0x7013,
- 0xb003, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934,
- 0xa184, 0x0007, 0x0002, 0x17cb, 0x1809, 0x17cb, 0x17cb, 0x17cb,
- 0x17f1, 0x17d8, 0x17cf, 0xa085, 0x0001, 0x0804, 0x1823, 0x684c,
- 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8,
- 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58,
- 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d,
- 0x2004, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832, 0x6858,
- 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac,
- 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
- 0xa080, 0x2186, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858,
- 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17cb, 0xa006, 0x682e, 0x682a,
- 0x6858, 0xa18c, 0x000f, 0xa188, 0x2186, 0x210d, 0x6932, 0x2d08,
- 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
- 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000,
- 0x2001, 0x020a, 0x2004, 0x82ff, 0x01a8, 0xa280, 0x0004, 0x00d6,
- 0x206c, 0x684c, 0xd0dc, 0x1150, 0x080c, 0x17bf, 0x0138, 0x00de,
- 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000,
- 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200,
- 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a,
- 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb01e, 0x0210,
- 0x2009, 0xb003, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118,
- 0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005,
- 0x7206, 0x2001, 0x1866, 0x0006, 0x2260, 0x0804, 0x197a, 0x0126,
- 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e,
- 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62,
- 0x6b5e, 0xa005, 0x0904, 0x18c8, 0x6808, 0xa005, 0x0904, 0x18ff,
- 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904,
- 0x1907, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c,
- 0x0168, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010, 0xa080,
- 0x0002, 0x2004, 0xa005, 0x0904, 0x18ff, 0x0c10, 0x2001, 0x0207,
- 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086,
- 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803,
- 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004,
- 0x1904, 0x1907, 0x2009, 0x0048, 0x080c, 0x80a7, 0x0804, 0x1907,
- 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110,
- 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004,
- 0xd08c, 0x0160, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010,
- 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207,
- 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50,
- 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818,
- 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100,
- 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x80a7, 0x00ce,
- 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046,
- 0x0056, 0x080c, 0x1d86, 0x0026, 0x0056, 0x2071, 0xaffd, 0x7000,
- 0xa086, 0x0000, 0x0580, 0x7004, 0xac06, 0x11f8, 0x2079, 0x0030,
- 0x7000, 0xa086, 0x0003, 0x01c8, 0x7804, 0xd0fc, 0x1198, 0x2001,
- 0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803, 0x0004, 0x7804, 0xd0ac,
- 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007,
- 0x0000, 0x0018, 0x080c, 0x1a6c, 0x08d0, 0x0156, 0x20a9, 0x0009,
- 0x2009, 0xb003, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003,
- 0x1f04, 0x1942, 0x015e, 0x005e, 0x002e, 0x2001, 0x015d, 0x201c,
- 0x831a, 0x2302, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202,
- 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c,
- 0x7110, 0xa106, 0x0904, 0x19dd, 0x2104, 0x7006, 0x2060, 0x8108,
- 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb01e, 0x0210, 0x2009,
- 0xb003, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2744, 0x2001,
- 0x0138, 0x2102, 0x8cff, 0x0588, 0x6010, 0x2068, 0x2d58, 0x6828,
- 0xa406, 0x1580, 0x682c, 0xa306, 0x1568, 0x7004, 0x2060, 0x6020,
- 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813,
- 0xffff, 0x00d8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810,
- 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
- 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x04c9, 0x0118,
- 0x2009, 0x0001, 0x04a9, 0x2d58, 0x0005, 0x080c, 0x1ced, 0x0904,
- 0x195f, 0x0cd0, 0x6020, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034,
- 0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046,
- 0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303,
- 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0x98cb, 0x09f0, 0x601c,
- 0xa08e, 0x0008, 0x0904, 0x1985, 0xa08e, 0x000a, 0x0904, 0x1985,
- 0x080c, 0x21a6, 0x1990, 0x0804, 0x1985, 0x7003, 0x0000, 0x0005,
- 0x8aff, 0x0904, 0x1a46, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8,
- 0xd0f4, 0x1528, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1a30,
- 0x1a15, 0x1a15, 0x1a30, 0x1a30, 0x1a29, 0x1a30, 0x1a15, 0x1a30,
- 0x1a1a, 0x1a1a, 0x1a30, 0x1a30, 0x1a30, 0x1a21, 0x1a1a, 0x7803,
- 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6,
- 0xd99c, 0x0548, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0420, 0xc0f4,
- 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0428, 0x6b08, 0x6a0c, 0x6d00,
- 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c,
- 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
- 0x1138, 0x00de, 0x080c, 0x2148, 0x1904, 0x19e0, 0xa00e, 0x00b0,
- 0x00de, 0x080c, 0x14f6, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a,
- 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300,
- 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x2148, 0x0005, 0x080c,
- 0x14f6, 0x080c, 0x1e1a, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068,
- 0x7003, 0x0000, 0x080c, 0x1d22, 0x080c, 0x9596, 0x0170, 0x6808,
- 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff,
- 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c,
- 0x0804, 0x1c5e, 0x080c, 0x14f6, 0x0126, 0x2091, 0x2200, 0x0006,
- 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184,
- 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000,
- 0x0002, 0x1a89, 0x1a8f, 0x1b92, 0x1c39, 0x1c4d, 0x1a89, 0x1a89,
- 0x1a89, 0x7804, 0xd09c, 0x1904, 0x1c5e, 0x080c, 0x14f6, 0x8001,
- 0x7002, 0xa184, 0x0880, 0x1190, 0xd19c, 0x1904, 0x1b20, 0x8aff,
- 0x0904, 0x1b20, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0904, 0x1c5e,
- 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7803, 0x0004,
- 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b00, 0x0026, 0x0036, 0x7c20,
- 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001,
- 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803,
- 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, 0x1c62, 0x6b28, 0x6a2c,
- 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e,
- 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236,
- 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x215e, 0x2a00,
- 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852,
- 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004,
- 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7, 0x7000, 0xa086, 0x0004,
- 0x0904, 0x1c5e, 0x7003, 0x0000, 0x080c, 0x195f, 0x0804, 0x1c5e,
- 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xac73, 0x005e, 0x080c,
- 0x1d22, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5029, 0x0118, 0x7820,
- 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808,
- 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1c5e,
- 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0128, 0x6808,
- 0x8001, 0x680a, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x7a1c, 0x6a16,
- 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, 0x2004,
- 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1aa6, 0x684c, 0xc0f5,
- 0x684e, 0x7814, 0xa005, 0x1180, 0x7003, 0x0000, 0x6808, 0x8001,
- 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7,
- 0x080c, 0x195f, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x781c, 0x6816,
- 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214,
- 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b,
- 0x810b, 0x080c, 0x1da5, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803,
- 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004,
- 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048,
- 0x080c, 0x80a7, 0x080c, 0x1dd7, 0x0958, 0x7908, 0xd1ec, 0x1118,
- 0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902, 0x7003, 0x0003,
- 0x0804, 0x1c5e, 0x8001, 0x7002, 0xd194, 0x01a8, 0x7804, 0xd0fc,
- 0x1904, 0x1c2c, 0xd09c, 0x0130, 0x7804, 0xd0fc, 0x1904, 0x1a74,
- 0xd09c, 0x11a8, 0x8aff, 0x0904, 0x1c5e, 0x2009, 0x0001, 0x080c,
- 0x19e0, 0x0804, 0x1c5e, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904,
- 0x1c5e, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7818,
- 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1b3e, 0x7803, 0x0004,
- 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1c0f, 0x6834, 0xa084, 0x00ff,
- 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1b3e, 0x0026, 0x0036,
- 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816,
- 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128,
- 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1c62,
- 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6, 0x2805, 0xac68,
- 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020,
- 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1ac8,
- 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001,
- 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1b50, 0x0056,
- 0x7d0c, 0x080c, 0xac73, 0x005e, 0x080c, 0x1d22, 0x00f6, 0x7004,
- 0x2078, 0x080c, 0x5029, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe,
- 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c,
- 0x791a, 0x6980, 0x791e, 0x0490, 0x7804, 0xd09c, 0x0904, 0x1a74,
- 0x7c20, 0x7824, 0xa405, 0x1904, 0x1a74, 0x7803, 0x0002, 0x0804,
- 0x1bb7, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0150,
- 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048,
- 0x080c, 0x80a7, 0x080c, 0x195f, 0x0088, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808,
- 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x197a, 0x001e, 0x000e,
- 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ce1, 0x7004,
- 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ce1, 0x00d6, 0x00c6,
- 0x216c, 0x2d00, 0xa005, 0x0904, 0x1cdf, 0x6820, 0xd0d4, 0x1904,
- 0x1cdf, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104,
- 0x6b2c, 0xa306, 0x1904, 0x1cdf, 0x8108, 0x2104, 0x6a28, 0xa206,
- 0x1904, 0x1cdf, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822,
- 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060,
- 0x6034, 0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808,
- 0x783a, 0x680c, 0x783e, 0x00de, 0x04a0, 0xa006, 0x783a, 0x783e,
- 0x0480, 0x8108, 0x2104, 0xa005, 0x1590, 0x8108, 0x2104, 0xa005,
- 0x1570, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160,
- 0xa180, 0x000d, 0x2004, 0xd09c, 0x1170, 0x6008, 0x7822, 0x686e,
- 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006,
- 0x783a, 0x783e, 0x0070, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826,
- 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c,
- 0x783e, 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce,
- 0x00de, 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005,
- 0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908,
- 0xd1ec, 0x1160, 0x080c, 0x1dd7, 0x0148, 0x7803, 0x0009, 0x7904,
- 0xd1fc, 0x0de8, 0x7803, 0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4,
- 0x1150, 0x7007, 0x0000, 0x080c, 0x1dd7, 0x0140, 0x7803, 0x0019,
- 0x7003, 0x0003, 0x0018, 0x00b1, 0xa085, 0x0001, 0x0005, 0x0126,
- 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1150, 0x700c, 0x7110,
- 0xa106, 0x0130, 0x20e1, 0x9028, 0x700f, 0xb003, 0x7013, 0xb003,
- 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1550, 0x2001, 0x0160,
- 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8,
- 0xe000, 0xe000, 0x8211, 0x1de0, 0x080c, 0x1d7e, 0x700c, 0x7110,
- 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060,
- 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210,
- 0x2009, 0xb003, 0x7112, 0x0c50, 0x080c, 0x57d1, 0x00ce, 0x0005,
- 0x04a9, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01d0, 0x2104,
- 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a,
- 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210, 0x2009, 0xb003, 0x7112,
- 0x700c, 0xa106, 0x1d40, 0x080c, 0x2744, 0x2001, 0x0138, 0x2102,
- 0x0c10, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x2001, 0x0160,
- 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x20e1, 0x9028,
- 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x0005, 0x2001, 0x0138,
- 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000,
- 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001,
- 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c,
- 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200,
- 0x7808, 0xa084, 0xf000, 0xa10d, 0x08c9, 0x2019, 0x5000, 0x8319,
- 0x0168, 0x2001, 0xb01e, 0x2004, 0xa086, 0x0000, 0x0138, 0x2001,
- 0x0021, 0xd0fc, 0x0da0, 0x080c, 0x1ff4, 0x0c78, 0x20e1, 0x7000,
- 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f,
- 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001,
- 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x7908,
- 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0218, 0xa085, 0x0001, 0x0088,
- 0x2001, 0x020a, 0x81ff, 0x0130, 0x20e1, 0x6000, 0x200c, 0x200c,
- 0x200c, 0x200c, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000,
- 0xa006, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xaffd,
- 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8,
- 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904,
- 0xa18c, 0x0780, 0x0016, 0x080c, 0x1a6c, 0x001e, 0x81ff, 0x1118,
- 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee,
- 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac,
- 0x0904, 0x1e66, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a,
- 0x0003, 0x0a0c, 0x14f6, 0x080c, 0x20f2, 0x00e6, 0x00f6, 0x2071,
- 0xafec, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800,
- 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838,
- 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079,
- 0x0030, 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x2079, 0x0010, 0x000e,
- 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e,
- 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee,
- 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x080c, 0x6d0d, 0x0005, 0x00e6,
- 0x2071, 0xb01e, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280,
- 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1ee4, 0x6934, 0xa184,
- 0x0007, 0x0002, 0x1e82, 0x1ecf, 0x1e82, 0x1e82, 0x1e82, 0x1eb6,
- 0x1e95, 0x1e84, 0x080c, 0x14f6, 0x684c, 0xd0b4, 0x0904, 0x1fcc,
- 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a,
- 0x6880, 0x680e, 0x6958, 0x0804, 0x1ed7, 0x6834, 0xa084, 0x00ff,
- 0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6860,
- 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880,
- 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
- 0xa080, 0x2186, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff,
- 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6804,
- 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2186,
- 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c,
- 0xd0b4, 0x0904, 0x1a47, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00,
- 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832,
- 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079,
- 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1ff4, 0x00e6, 0x00d6, 0x2071,
- 0xb01e, 0x7000, 0xa005, 0x1904, 0x1f4c, 0x00c6, 0x7206, 0xa280,
- 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6,
- 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079,
- 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de,
- 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034,
- 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a,
- 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120,
- 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10,
- 0x080c, 0x21a6, 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff,
- 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000,
- 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001,
- 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005,
- 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904,
- 0x1fc5, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04,
- 0x1fc4, 0xa705, 0x0904, 0x1fc4, 0xa03e, 0x2730, 0x6850, 0xd0fc,
- 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1fa7, 0x1f8c,
- 0x1f8c, 0x1fa7, 0x1fa7, 0x1fa0, 0x1fa7, 0x1f8c, 0x1fa7, 0x1f91,
- 0x1f91, 0x1fa7, 0x1fa7, 0x1fa7, 0x1f98, 0x1f91, 0xc0fc, 0x6852,
- 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805,
- 0xac68, 0x6f08, 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04,
- 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090,
- 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138,
- 0x00de, 0x080c, 0x2148, 0x1904, 0x1f56, 0xa00e, 0x00f0, 0x00de,
- 0x080c, 0x14f6, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a,
- 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a,
- 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201,
- 0x7012, 0x080c, 0x2148, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e,
- 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x14f6, 0x0026, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596,
- 0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c, 0x20e1,
- 0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c,
- 0x6d0d, 0x002e, 0x0804, 0x20ad, 0x0126, 0x2091, 0x2400, 0x0006,
- 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071,
- 0xb01e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184,
- 0x0700, 0x1920, 0x7000, 0x0002, 0x20ad, 0x2010, 0x2080, 0x20ab,
- 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001,
- 0x080c, 0x1f50, 0x0904, 0x20ad, 0x2009, 0x0001, 0x080c, 0x1f50,
- 0x0804, 0x20ad, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc,
- 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026,
- 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872,
- 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e,
- 0x002e, 0x080c, 0x215e, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826,
- 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x20ad,
- 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100,
- 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019,
- 0x1000, 0x8319, 0x090c, 0x14f6, 0x7820, 0xd0bc, 0x1dd0, 0x003e,
- 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e,
- 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012,
- 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468,
- 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x2004,
- 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x1f50,
- 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6,
- 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c,
- 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804,
- 0x2033, 0x0804, 0x202f, 0x080c, 0x14f6, 0x00ce, 0x00de, 0x00ee,
- 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071,
- 0xb01e, 0x7000, 0xa086, 0x0000, 0x0590, 0x2079, 0x0020, 0x0016,
- 0x2009, 0x0207, 0x210c, 0xd194, 0x0158, 0x2009, 0x020c, 0x210c,
- 0xa184, 0x0003, 0x0128, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102,
- 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110,
- 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0d18, 0x080c, 0x1ff4, 0x7000,
- 0xa086, 0x0000, 0x19e8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac,
- 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee,
- 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071,
- 0xb01e, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004,
- 0x2060, 0x6010, 0x2068, 0x080c, 0x9596, 0x0158, 0x6850, 0xc0b5,
- 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206,
- 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803,
- 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x929c, 0x20e1,
- 0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x00fe,
- 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205,
- 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1e6e, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x2069, 0xafc7, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8,
- 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a,
- 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2186, 0x2045, 0x88ff,
- 0x090c, 0x14f6, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841,
- 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005,
- 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080,
- 0x2196, 0x2045, 0x88ff, 0x090c, 0x14f6, 0x0005, 0x0000, 0x0011,
- 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f,
- 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x217b,
- 0x2177, 0x0000, 0x0000, 0x2185, 0x0000, 0x217b, 0x0000, 0x2182,
- 0x217f, 0x0000, 0x0000, 0x0000, 0x2185, 0x2182, 0x0000, 0x217d,
- 0x217d, 0x0000, 0x0000, 0x2185, 0x0000, 0x217d, 0x0000, 0x2183,
- 0x2183, 0x0000, 0x0000, 0x0000, 0x2185, 0x2183, 0x00a6, 0x0096,
- 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2237, 0x2d60,
- 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2186, 0xa986, 0x0007, 0x0130,
- 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422,
- 0x6060, 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2237,
- 0x6004, 0xa065, 0x0904, 0x2237, 0x0c18, 0x2805, 0xa005, 0x01a8,
- 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020,
- 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150,
- 0x8a51, 0x0904, 0x2237, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904,
- 0x2237, 0x0830, 0x8a51, 0x0904, 0x2237, 0x8840, 0x2805, 0xa005,
- 0x1158, 0x6004, 0xa065, 0x0904, 0x2237, 0x6034, 0xa0cc, 0x000f,
- 0xa9c0, 0x2186, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852,
- 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68,
- 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122,
- 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804,
- 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
- 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
- 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
- 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e,
- 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004,
- 0xa084, 0x0007, 0x0002, 0x224b, 0x224c, 0x224f, 0x2252, 0x2257,
- 0x225a, 0x225f, 0x2264, 0x0005, 0x080c, 0x1ff4, 0x0005, 0x080c,
- 0x1a6c, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4, 0x0005, 0x080c,
- 0x16f8, 0x0005, 0x080c, 0x1ff4, 0x080c, 0x16f8, 0x0005, 0x080c,
- 0x1a6c, 0x080c, 0x16f8, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4,
- 0x080c, 0x16f8, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200,
- 0x2071, 0xb280, 0x2069, 0xad00, 0x2009, 0x0004, 0x7912, 0x7817,
- 0x0004, 0x080c, 0x2651, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x2283, 0x20e1,
- 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126,
- 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2335, 0xa084, 0x0007,
- 0x0002, 0x22b3, 0x22a1, 0x22a4, 0x22a7, 0x22ac, 0x22ae, 0x22b0,
- 0x22b2, 0x080c, 0x5fb7, 0x0078, 0x080c, 0x5ff0, 0x0060, 0x080c,
- 0x5fb7, 0x080c, 0x5ff0, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018,
- 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026,
- 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1, 0x9040, 0x04a0, 0xa184,
- 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c,
- 0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00,
- 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a,
- 0x0010, 0x080c, 0x485e, 0x20e1, 0x9010, 0x00a8, 0xa184, 0x00c0,
- 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c,
- 0x1d22, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300,
- 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005,
- 0x0016, 0x00e6, 0x00f6, 0x2071, 0xad00, 0x7128, 0x2001, 0xaf90,
- 0x2102, 0x2001, 0xaf98, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009,
- 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0,
- 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349,
- 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009,
- 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010,
- 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c,
- 0x2651, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x14f6,
- 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xad00, 0x6024,
- 0x6026, 0x6053, 0x0030, 0x080c, 0x2690, 0x6050, 0xa084, 0xfe7f,
- 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x26a0, 0x60e7,
- 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000,
- 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e,
- 0x600f, 0x00ff, 0x2001, 0xaf8c, 0x2003, 0x00ff, 0x602b, 0x002f,
- 0x012e, 0x0005, 0x2001, 0xad31, 0x2003, 0x0000, 0x2001, 0xad30,
- 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016,
- 0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a,
- 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x23a7, 0x238d, 0x2390,
- 0x2393, 0x2398, 0x239a, 0x239e, 0x23a2, 0x080c, 0x6699, 0x00b8,
- 0x080c, 0x6774, 0x00a0, 0x080c, 0x6774, 0x080c, 0x6699, 0x0078,
- 0x0099, 0x0068, 0x080c, 0x6699, 0x0079, 0x0048, 0x080c, 0x6774,
- 0x0059, 0x0028, 0x080c, 0x6774, 0x080c, 0x6699, 0x0029, 0x002e,
- 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, 0x1904, 0x25bf,
- 0x080c, 0x574f, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024,
- 0xa084, 0x1800, 0x0178, 0x080c, 0x5775, 0x0118, 0x080c, 0x5761,
- 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xaf9d, 0x2003,
- 0xaaaa, 0x0458, 0x080c, 0x5775, 0x15d0, 0x6024, 0xa084, 0x1800,
- 0x1108, 0x04a8, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e,
- 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a,
- 0x0804, 0x25bf, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4,
- 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x7088, 0xa086, 0x0028,
- 0x1110, 0x080c, 0x58da, 0x0804, 0x25bf, 0x2001, 0xaf9e, 0x2003,
- 0x0000, 0x0048, 0x2001, 0xaf9e, 0x2003, 0x0002, 0x0020, 0x080c,
- 0x584d, 0x0804, 0x25bf, 0x080c, 0x597a, 0x0804, 0x25bf, 0xd1ac,
- 0x0904, 0x2507, 0x080c, 0x574f, 0x11d8, 0x6027, 0x0020, 0x0006,
- 0x0026, 0x0036, 0x080c, 0x576b, 0x1170, 0x2001, 0xaf9e, 0x2003,
- 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a, 0x003e,
- 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5726,
- 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061,
- 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ca, 0xa48c,
- 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x7038,
- 0xd084, 0x1148, 0xc085, 0x703a, 0x0036, 0x2418, 0x2011, 0x8016,
- 0x080c, 0x3c5c, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7050, 0xa084,
- 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011,
- 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xad52,
- 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248,
- 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904,
- 0x24d2, 0x7034, 0xd08c, 0x1140, 0x2001, 0xad0c, 0x200c, 0xd1ac,
- 0x1904, 0x24d2, 0xc1ad, 0x2102, 0x0036, 0x73c8, 0x2011, 0x8013,
- 0x080c, 0x3c5c, 0x003e, 0x0804, 0x24d2, 0x7034, 0xd08c, 0x1140,
- 0x2001, 0xad0c, 0x200c, 0xd1ac, 0x1904, 0x24d2, 0xc1ad, 0x2102,
- 0x0036, 0x73c8, 0x2011, 0x8013, 0x080c, 0x3c5c, 0x003e, 0x7130,
- 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x01d0, 0x0016,
- 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019, 0x000e,
- 0x080c, 0xa8eb, 0xa484, 0x00ff, 0xa080, 0x2be6, 0x200d, 0xa18c,
- 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xa96c,
- 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004,
- 0x080c, 0x2aac, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009,
- 0x0000, 0x080c, 0x4cdc, 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04,
- 0x24c9, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x7adf,
- 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581,
- 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3, 0x0000,
- 0x001e, 0x2001, 0xad00, 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c,
- 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xad22,
- 0x2003, 0x0000, 0x6027, 0x0020, 0x080c, 0x5775, 0x1140, 0x0016,
- 0x2009, 0x07d0, 0x2011, 0x567b, 0x080c, 0x6593, 0x001e, 0xd194,
- 0x0904, 0x25bf, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2570, 0x080c,
- 0x6581, 0x080c, 0x7834, 0x6027, 0x0004, 0x00f6, 0x2019, 0xafd0,
- 0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6,
- 0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
- 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0,
- 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a,
- 0x080c, 0x6b73, 0x080c, 0x6c50, 0x7810, 0x2070, 0x7037, 0x0103,
- 0x2f60, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e,
- 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
- 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061,
- 0xafc7, 0x6028, 0xa09a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce,
- 0x080c, 0x7827, 0x0804, 0x25be, 0x2019, 0xafd0, 0x2304, 0xa065,
- 0x0120, 0x2009, 0x0027, 0x080c, 0x80a7, 0x00ce, 0x0804, 0x25be,
- 0xd2bc, 0x0904, 0x25be, 0x080c, 0x658e, 0x6014, 0xa084, 0x0184,
- 0xa085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140,
- 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000,
- 0x00de, 0x00c6, 0x2061, 0xafc7, 0x6044, 0xa09a, 0x00c8, 0x12f0,
- 0x8000, 0x6046, 0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0,
- 0x080c, 0x6586, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138,
- 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114,
- 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019,
- 0x0001, 0x080c, 0x7a64, 0x003e, 0x2019, 0xafd6, 0x2304, 0xa065,
- 0x0120, 0x2009, 0x004f, 0x080c, 0x80a7, 0x00ce, 0x001e, 0xd19c,
- 0x0904, 0x261a, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027,
- 0x0008, 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x25cd, 0x2091,
- 0x6000, 0x1f04, 0x25cd, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400,
- 0x6052, 0x20a9, 0x0366, 0x1d04, 0x25db, 0x2091, 0x6000, 0x6020,
- 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0490,
- 0x080c, 0x2760, 0x1f04, 0x25db, 0x015e, 0x6152, 0x001e, 0x6027,
- 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c,
- 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c,
- 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3,
- 0x0000, 0x080c, 0xac8d, 0x080c, 0xaca8, 0xa085, 0x0001, 0x080c,
- 0x5793, 0x2001, 0xad00, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c,
- 0x12cc, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016,
- 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00,
- 0x71c0, 0x70c2, 0xa116, 0x01f0, 0x81ff, 0x0128, 0x2011, 0x8011,
- 0x080c, 0x3c5c, 0x00b8, 0x2011, 0x8012, 0x080c, 0x3c5c, 0x2001,
- 0xad71, 0x2004, 0xd0fc, 0x1170, 0x0036, 0x00c6, 0x080c, 0x26eb,
- 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2aac,
- 0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e,
- 0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190,
- 0x2664, 0x2205, 0x60f2, 0x2011, 0x2671, 0x2205, 0x60ee, 0x002e,
- 0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580,
- 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8,
- 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c,
- 0x00ff, 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c,
- 0x6278, 0x0038, 0xa080, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f,
- 0xa006, 0x0005, 0xa080, 0x2be6, 0x200d, 0xa18c, 0x00ff, 0x0005,
- 0x00d6, 0x2069, 0x0140, 0x2001, 0xad14, 0x2003, 0x00ef, 0x20a9,
- 0x0010, 0xa006, 0x6852, 0x6856, 0x1f04, 0x269b, 0x00de, 0x0005,
- 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xad14, 0x2102,
- 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000,
- 0xa006, 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xacae, 0x2005,
- 0x6856, 0x8211, 0x1f04, 0x26b0, 0x002e, 0x00de, 0x000e, 0x0005,
- 0x00c6, 0x2061, 0xad00, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c,
- 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006,
- 0x2069, 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212,
- 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404,
- 0x680e, 0x1f04, 0x26e0, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e,
- 0x00de, 0x015e, 0x0005, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150,
- 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c,
- 0xa96c, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140,
- 0x78c4, 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520,
- 0x2011, 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018,
- 0x2300, 0x080c, 0x6665, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085,
- 0x004c, 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009,
- 0x0138, 0x200a, 0x080c, 0x574f, 0x1118, 0x2009, 0xaf8e, 0x200a,
- 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126,
- 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c,
- 0x8000, 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1a6a, 0x002e,
- 0x001e, 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004,
- 0xa082, 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c,
- 0x00ff, 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f,
- 0x0010, 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005,
- 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854,
- 0xd08c, 0x1110, 0x1f04, 0x2767, 0x00fe, 0x015e, 0x000e, 0x0005,
- 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048,
- 0x0006, 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0,
- 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028,
- 0x0006, 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000,
- 0xe000, 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e,
- 0x60e2, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e,
- 0x60ee, 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e,
- 0x60e6, 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c,
- 0x26a0, 0x000e, 0x00ce, 0x001e, 0x0005, 0x2845, 0x2849, 0x284d,
- 0x2853, 0x2859, 0x285f, 0x2865, 0x286d, 0x2875, 0x287b, 0x2881,
- 0x2889, 0x2891, 0x2899, 0x28a1, 0x28ab, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b7, 0x28b7, 0x28bc,
- 0x28bc, 0x28c3, 0x28c3, 0x28ca, 0x28ca, 0x28d3, 0x28d3, 0x28da,
- 0x28da, 0x28e3, 0x28e3, 0x28ec, 0x28ec, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x0106, 0x0006, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x2373, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106,
- 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x223d, 0x080c,
- 0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c,
- 0x223d, 0x080c, 0x228f, 0x0804, 0x28f7, 0xe000, 0x0cf0, 0x0106,
- 0x0006, 0x080c, 0x272f, 0x04d8, 0x0106, 0x0006, 0x080c, 0x272f,
- 0x080c, 0x2373, 0x04a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
- 0x223d, 0x0468, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373,
- 0x080c, 0x223d, 0x0420, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
- 0x228f, 0x00e8, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373,
- 0x080c, 0x228f, 0x00a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
- 0x223d, 0x080c, 0x228f, 0x0058, 0x0106, 0x0006, 0x080c, 0x272f,
- 0x080c, 0x2373, 0x080c, 0x223d, 0x080c, 0x228f, 0x0000, 0x000e,
- 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c,
- 0x502d, 0x1904, 0x29d4, 0x72d0, 0x2001, 0xaf9d, 0x2004, 0xa005,
- 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x29d4,
- 0x080c, 0x29d8, 0x0804, 0x29d4, 0x080c, 0x574f, 0x1120, 0x709b,
- 0xffff, 0x0804, 0x29d4, 0xd294, 0x0120, 0x709b, 0xffff, 0x0804,
- 0x29d4, 0x2001, 0xad14, 0x203c, 0x7284, 0xd284, 0x0904, 0x2976,
- 0xd28c, 0x1904, 0x2976, 0x0036, 0x7398, 0xa38e, 0xffff, 0x1110,
- 0x2019, 0x0001, 0x8314, 0xa2e0, 0xb3c0, 0x2c04, 0xa38c, 0x0001,
- 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e,
- 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230,
- 0xd284, 0x1538, 0x7284, 0xc28d, 0x7286, 0x709b, 0xffff, 0x003e,
- 0x0428, 0x2009, 0x0000, 0x080c, 0x2676, 0x080c, 0x4c80, 0x11b8,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c,
- 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x29eb, 0x0140, 0x0028,
- 0x080c, 0x2b1a, 0x080c, 0x2a19, 0x0110, 0x8318, 0x0818, 0x739a,
- 0x0010, 0x709b, 0xffff, 0x003e, 0x0804, 0x29d4, 0xa780, 0x2be6,
- 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x7098, 0xa096,
- 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220,
- 0x2008, 0xa802, 0x20a8, 0x0020, 0x709b, 0xffff, 0x0804, 0x29d4,
- 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x4cdc,
- 0x0120, 0x080c, 0x4c80, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000,
- 0xd0bc, 0x11d0, 0x7284, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff,
- 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4c9f, 0x0028,
- 0x080c, 0x2b9c, 0x0170, 0x080c, 0x2bc9, 0x0058, 0x080c, 0x2b1a,
- 0x080c, 0x2a19, 0x0170, 0x0028, 0x080c, 0x2b9c, 0x0110, 0x0419,
- 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2990, 0x709b, 0xffff,
- 0x0018, 0x001e, 0x015e, 0x719a, 0x004e, 0x002e, 0x00ce, 0x0005,
- 0x00c6, 0x0016, 0x709b, 0x0000, 0x2009, 0x007e, 0x080c, 0x4c80,
- 0x1138, 0x080c, 0x2b1a, 0x04a9, 0x0118, 0x70d0, 0xc0bd, 0x70d2,
- 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68,
- 0x2001, 0xad56, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807,
- 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2001,
- 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0000, 0x080c, 0x4c30, 0x0126,
- 0x2091, 0x8000, 0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e,
- 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xad56,
- 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807, 0x0550, 0x2d00,
- 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140,
- 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2ad9,
- 0x080c, 0x9956, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e,
- 0x2001, 0x0002, 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x7094,
- 0x8000, 0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085,
- 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026,
- 0x2009, 0x0080, 0x080c, 0x4c80, 0x1120, 0x0031, 0x0110, 0x70d7,
- 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6,
- 0x2c68, 0x080c, 0x8022, 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956,
- 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002,
- 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x70d8, 0x8000, 0x70da,
- 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce,
- 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091,
- 0x8000, 0x2009, 0x007f, 0x080c, 0x4c80, 0x1190, 0x2c68, 0x080c,
- 0x8022, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
- 0x080c, 0x9956, 0x2009, 0x0022, 0x080c, 0x80a7, 0xa085, 0x0001,
- 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036,
- 0x0026, 0x080c, 0x68f3, 0x080c, 0x689d, 0x080c, 0x8a15, 0x2130,
- 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1120, 0x080c,
- 0x4ecf, 0x080c, 0x493a, 0x001e, 0x8108, 0x1f04, 0x2ac3, 0x86ff,
- 0x1110, 0x080c, 0x11d4, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee,
- 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270,
- 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039,
- 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x001e,
- 0x2e60, 0x080c, 0x4ecf, 0x6210, 0x6314, 0x080c, 0x493a, 0x6212,
- 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6,
- 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150,
- 0x2071, 0xad00, 0x7094, 0xa005, 0x0110, 0x8001, 0x7096, 0x000e,
- 0x00ee, 0x0005, 0x2071, 0xad00, 0x70d8, 0xa005, 0x0dc0, 0x8001,
- 0x70da, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6,
- 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118,
- 0x20a9, 0x0001, 0x0098, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150,
- 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c,
- 0xa96c, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e,
- 0x007e, 0x05c8, 0xa28e, 0x007f, 0x05b0, 0xa28e, 0x0080, 0x0598,
- 0xa288, 0xae34, 0x210c, 0x81ff, 0x0570, 0x8fff, 0x05c1, 0x00c6,
- 0x2160, 0x2001, 0x0001, 0x080c, 0x5037, 0x00ce, 0x2019, 0x0029,
- 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x00c6,
- 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118,
- 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206,
- 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xa712, 0x001e, 0x007e,
- 0x2160, 0x080c, 0x4ecf, 0x002e, 0x8210, 0x1f04, 0x2b3e, 0x015e,
- 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046,
- 0x0026, 0x0016, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0148, 0xd0a4,
- 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xa96c,
- 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6,
- 0x7284, 0x82ff, 0x01f8, 0x2011, 0xad52, 0x2214, 0xd2ac, 0x11d0,
- 0x2100, 0x080c, 0x268a, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314,
- 0xa2e0, 0xb3c0, 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007,
- 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110,
- 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e,
- 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0xa180, 0xae34,
- 0x2004, 0xa065, 0x0178, 0x0016, 0x00c6, 0x080c, 0x9807, 0x001e,
- 0x090c, 0x14f6, 0x611a, 0x080c, 0x2ad9, 0x080c, 0x8078, 0x001e,
- 0x080c, 0x4c9f, 0x012e, 0x00ce, 0x001e, 0x0005, 0x7eef, 0x7de8,
- 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6,
- 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc,
- 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc,
- 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1,
- 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6,
- 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797,
- 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c,
- 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071,
- 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66,
- 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454,
- 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a,
- 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039,
- 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d,
- 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123,
- 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f,
- 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700,
- 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000,
- 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000,
- 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700,
- 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100,
- 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00,
- 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400,
- 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00,
- 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800,
- 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400,
- 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xad81,
- 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033,
- 0xad91, 0x7037, 0xad91, 0x7007, 0x0001, 0x2061, 0xadd1, 0x6003,
- 0x0002, 0x0005, 0x1004, 0x2d0c, 0x0e04, 0x2d0c, 0x2071, 0xad81,
- 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069,
- 0x1904, 0x2df1, 0x0804, 0x2d8a, 0x0005, 0x2071, 0xad81, 0x7004,
- 0x0002, 0x2d15, 0x2d16, 0x2d1f, 0x2d30, 0x0005, 0x1004, 0x2d1e,
- 0x0e04, 0x2d1e, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78,
- 0x2061, 0xadd1, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200,
- 0x0904, 0x2deb, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807,
- 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60,
- 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210,
- 0x61c0, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x2de8, 0x61c0,
- 0x0804, 0x2d8a, 0x2dcc, 0x2df7, 0x2dff, 0x2e03, 0x2e0b, 0x2e11,
- 0x2e15, 0x2e21, 0x2e24, 0x2e2e, 0x2e31, 0x2de8, 0x2de8, 0x2de8,
- 0x2e34, 0x2de8, 0x2e43, 0x2e5a, 0x2e71, 0x2ee8, 0x2eed, 0x2f16,
- 0x2f67, 0x2f78, 0x2f96, 0x2fcd, 0x2fd7, 0x2fe4, 0x2ff7, 0x3018,
- 0x3021, 0x3057, 0x305d, 0x2de8, 0x3086, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x308d, 0x3097, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x309f, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x30b1, 0x30b9, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x0002, 0x30cb, 0x311f, 0x317a, 0x318a, 0x2de8,
- 0x31a4, 0x35cb, 0x3fbb, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x2de8, 0x2e2e, 0x2e31, 0x35cd, 0x2de8, 0x35da,
- 0x403c, 0x4097, 0x40fb, 0x2de8, 0x415a, 0x4180, 0x419f, 0x2de8,
- 0x2de8, 0x2de8, 0x2de8, 0x35de, 0x376b, 0x3785, 0x37a3, 0x3804,
- 0x3858, 0x3863, 0x389a, 0x38a9, 0x38b8, 0x38bb, 0x38de, 0x3928,
- 0x398e, 0x399b, 0x3a9c, 0x3bb3, 0x3bdc, 0x3cda, 0x3cfc, 0x3d08,
- 0x3d41, 0x3e05, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x3e6d, 0x3e88,
- 0x3efa, 0x3fac, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x3c39,
- 0x0126, 0x2091, 0x8000, 0x0e04, 0x2dd8, 0x7818, 0xd084, 0x0110,
- 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001,
- 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005,
- 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003,
- 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e,
- 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3c46, 0x7823,
- 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824,
- 0x7930, 0x0804, 0x3c49, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804,
- 0x2dcc, 0x7924, 0x2114, 0x0804, 0x2dcc, 0x2099, 0x0009, 0x20a1,
- 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804,
- 0x2dcc, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0001,
- 0x2019, 0x001b, 0x783b, 0x0017, 0x0804, 0x2dcc, 0x7d38, 0x7c3c,
- 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006,
- 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904,
- 0x2dcc, 0x0804, 0x2dee, 0x2069, 0xad51, 0x7824, 0x7930, 0xa11a,
- 0x1a04, 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684a, 0x6942, 0x782c,
- 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x5a1c,
- 0x0804, 0x2dcc, 0x2069, 0xad51, 0x7824, 0x7934, 0xa11a, 0x1a04,
- 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684e, 0x6946, 0x782c, 0x6862,
- 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x50d9, 0x0804,
- 0x2dcc, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2df1, 0x7924, 0x7b28,
- 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xad88, 0x41a1, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x2009, 0x0020, 0x080c, 0x3c46, 0x701b, 0x2e89,
- 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120,
- 0xa096, 0x0019, 0x1904, 0x2df1, 0x810f, 0xa18c, 0x00ff, 0x0904,
- 0x2df1, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x2009, 0x0020, 0x2061, 0xadd1, 0x6224, 0x6328,
- 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000,
- 0xa5a9, 0x0000, 0x080c, 0x3c46, 0x701b, 0x2eb7, 0x0005, 0x6834,
- 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904,
- 0x2df1, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c,
- 0x4b7c, 0x1128, 0x7007, 0x0003, 0x701b, 0x2ed1, 0x0005, 0x080c,
- 0x51df, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xad88,
- 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3c49,
- 0x61a8, 0x7824, 0x60aa, 0x0804, 0x2dcc, 0x2091, 0x8000, 0x7823,
- 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
- 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
- 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
- 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
- 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904,
- 0x2df1, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x1904,
- 0x2df4, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804,
- 0x2df4, 0x7c28, 0x7d2c, 0x080c, 0x4e96, 0xd28c, 0x1118, 0x080c,
- 0x4e41, 0x0010, 0x080c, 0x4e6f, 0x1518, 0x2061, 0xb400, 0x0126,
- 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d,
- 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e,
- 0xace0, 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1a04, 0x2df1,
- 0x0c30, 0x080c, 0x929c, 0x012e, 0x0904, 0x2df1, 0x0804, 0x2dcc,
- 0xa00e, 0x2001, 0x0005, 0x080c, 0x51df, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x9803, 0x080c, 0x510c, 0x012e, 0x0804, 0x2dcc, 0x81ff,
- 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96,
- 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0904, 0x2df1, 0x0804, 0x2dcc,
- 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c,
- 0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0005, 0x080c, 0x4ebd, 0x0904,
- 0x2df1, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x8003, 0x800b,
- 0x810b, 0xa108, 0x080c, 0x6519, 0x0804, 0x2dcc, 0x0126, 0x2091,
- 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0448, 0x2029, 0x00ff,
- 0x644c, 0x2400, 0xa506, 0x01f0, 0x2508, 0x080c, 0x4cdc, 0x11d0,
- 0x080c, 0x4f0d, 0x1128, 0x2009, 0x0002, 0x62b0, 0x2518, 0x00b8,
- 0x2019, 0x0004, 0x080c, 0x4ebd, 0x1118, 0x2009, 0x0006, 0x0078,
- 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108,
- 0x080c, 0x6519, 0x8529, 0x1ae8, 0x012e, 0x0804, 0x2dcc, 0x012e,
- 0x0804, 0x2df1, 0x012e, 0x0804, 0x2df4, 0x080c, 0x3c1a, 0x0904,
- 0x2df4, 0x080c, 0x4dfc, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff,
- 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4ded,
- 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c,
- 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e71, 0x0904, 0x2df1, 0x080c,
- 0x4bc0, 0x080c, 0x4e3a, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x080c,
- 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x62a0,
- 0x2019, 0x0005, 0x00c6, 0x080c, 0x4ecf, 0x2061, 0x0000, 0x080c,
- 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2009, 0x0000,
- 0x080c, 0xa712, 0x007e, 0x00ce, 0x080c, 0x4e96, 0x0804, 0x2dcc,
- 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e96, 0x2208, 0x0804,
- 0x2dcc, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xae13, 0x6810, 0x6914,
- 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019,
- 0x0000, 0x20a9, 0x007e, 0x2069, 0xae34, 0x2d04, 0xa075, 0x0130,
- 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04,
- 0x3035, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2dcc,
- 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c,
- 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069,
- 0xae13, 0x6910, 0x62ac, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1,
- 0x614c, 0xa190, 0x2be6, 0x2215, 0xa294, 0x00ff, 0x636c, 0x83ff,
- 0x0108, 0x6270, 0x67d0, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090,
- 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031,
- 0x0002, 0x0040, 0x080c, 0x574f, 0x1118, 0x2031, 0x0004, 0x0010,
- 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2dcc, 0x613c, 0x6240,
- 0x2019, 0xafa3, 0x231c, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000,
- 0x6134, 0xa006, 0x2010, 0x2018, 0x012e, 0x0804, 0x2dcc, 0x080c,
- 0x3c2a, 0x0904, 0x2df4, 0x6244, 0x6338, 0x0804, 0x2dcc, 0x613c,
- 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xad51, 0x831f,
- 0xa305, 0x6816, 0x782c, 0x2069, 0xafa3, 0x2d1c, 0x206a, 0x0804,
- 0x2dcc, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x012e, 0x0804,
- 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x7828, 0xa00d, 0x0904,
- 0x2df4, 0x782c, 0xa005, 0x0904, 0x2df4, 0x6244, 0x6146, 0x6338,
- 0x603a, 0x0804, 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003,
- 0x1904, 0x2df1, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
- 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xad14, 0x2004, 0xa085,
- 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2be6, 0x210d,
- 0xa18c, 0x00ff, 0x2001, 0xad14, 0x2004, 0xa116, 0x0550, 0x810f,
- 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x8022, 0x000e,
- 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3c05,
- 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
- 0xc0fd, 0x683a, 0x701b, 0x3173, 0x2d00, 0x6012, 0x2009, 0x0032,
- 0x080c, 0x80a7, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804,
- 0x2df1, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x8078, 0x0cb0, 0x2001,
- 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00c6, 0x2061,
- 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130,
- 0x2001, 0xad14, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f,
- 0x16a0, 0xa188, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xad14,
- 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000,
- 0x0006, 0x080c, 0x8022, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05,
- 0x601f, 0x0001, 0x080c, 0x3c05, 0x01d8, 0x6837, 0x0000, 0x7007,
- 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3173,
- 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x80a7, 0x012e, 0x00ce,
- 0x0005, 0x012e, 0x00ce, 0x0804, 0x2df1, 0x00ce, 0x0804, 0x2df4,
- 0x080c, 0x8078, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1,
- 0x0804, 0x2dcc, 0x2061, 0xb048, 0x0126, 0x2091, 0x8000, 0x6000,
- 0xd084, 0x0128, 0x6104, 0x6208, 0x012e, 0x0804, 0x2dcc, 0x012e,
- 0x0804, 0x2df4, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0904,
- 0x2df1, 0x0126, 0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248,
- 0xa085, 0x0001, 0x080c, 0x26c0, 0x080c, 0x436e, 0x012e, 0x0804,
- 0x2dcc, 0x012e, 0x0804, 0x2df4, 0x0126, 0x2091, 0x8000, 0x7824,
- 0xa084, 0x0007, 0x0002, 0x31b6, 0x31bf, 0x31c6, 0x31b3, 0x31b3,
- 0x31b3, 0x31b3, 0x31b3, 0x012e, 0x0804, 0x2df4, 0x2009, 0x0114,
- 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, 0x332f, 0x0070, 0x2009,
- 0x010b, 0x200b, 0x0010, 0x080c, 0x332f, 0x0038, 0x81ff, 0x0128,
- 0x012e, 0x2021, 0x400b, 0x0804, 0x2dce, 0x0086, 0x0096, 0x00a6,
- 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c,
- 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001,
- 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050,
- 0x2058, 0x080c, 0x3570, 0x080c, 0x34da, 0xa03e, 0x2720, 0x00f6,
- 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xb01e, 0x2079, 0x0020, 0x00d6,
- 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004,
- 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001,
- 0x080c, 0x3486, 0x080c, 0x3486, 0x00ce, 0x00ee, 0x00fe, 0x080c,
- 0x33d5, 0x080c, 0x34ae, 0x080c, 0x342b, 0x080c, 0x3394, 0x080c,
- 0x33c5, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814,
- 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c,
- 0x330d, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079,
- 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032,
- 0x7816, 0x080c, 0x330d, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc,
- 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130,
- 0x8b58, 0x080c, 0x3317, 0x00fe, 0x0804, 0x32d7, 0x00fe, 0x080c,
- 0x330d, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b,
- 0x2502, 0x080c, 0x3317, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201,
- 0x2004, 0xa005, 0x1904, 0x3211, 0x8739, 0x0038, 0x2001, 0xaffd,
- 0x2004, 0xa086, 0x0000, 0x1904, 0x3211, 0x2001, 0x0033, 0x2003,
- 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x32d7,
- 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x32d7,
- 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac,
- 0x1148, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003,
- 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005,
- 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a,
- 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6,
- 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203,
- 0x2004, 0x1f04, 0x32ac, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001,
- 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079,
- 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004,
- 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e,
- 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x31ef, 0x2061,
- 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824,
- 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050,
- 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e,
- 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10,
- 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce,
- 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2dcc,
- 0x012e, 0x2021, 0x400c, 0x0804, 0x2dce, 0xa085, 0x0001, 0x1d04,
- 0x3316, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001,
- 0x0020, 0x2003, 0x0004, 0x2001, 0xaffd, 0x2003, 0x0000, 0x2001,
- 0xb01e, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6,
- 0x2079, 0x0100, 0x2001, 0xad14, 0x200c, 0x7932, 0x7936, 0x080c,
- 0x26a0, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019,
- 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad,
- 0x782e, 0x20a9, 0x0046, 0x1d04, 0x334b, 0x2091, 0x6000, 0x1f04,
- 0x334b, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004,
- 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e,
- 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e,
- 0xe000, 0x1f04, 0x3368, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019,
- 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8,
- 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040,
- 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140,
- 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000,
- 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6,
- 0x00e6, 0x2071, 0xaffd, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004,
- 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc,
- 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe,
- 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a,
- 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108,
- 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200,
- 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001,
- 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100,
- 0x2009, 0xad14, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e,
- 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0xa080,
- 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006,
- 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5,
- 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, 0x7016,
- 0x080c, 0x34ae, 0x080c, 0x330d, 0x1110, 0x8421, 0x0028, 0x7024,
- 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, 0xaffd,
- 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0120,
- 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, 0x080c,
- 0x3486, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ee, 0x00fe, 0x7017,
- 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xaffd, 0x2079,
- 0x0030, 0x7904, 0xd1fc, 0x0904, 0x3483, 0x7803, 0x0002, 0xa026,
- 0xd19c, 0x1904, 0x347f, 0x7000, 0x0002, 0x3483, 0x3441, 0x3465,
- 0x347f, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011,
- 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820,
- 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c,
- 0x81ff, 0x0de8, 0x080c, 0x33b1, 0x2009, 0x0001, 0x7808, 0xd0ec,
- 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184,
- 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1,
- 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000,
- 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803,
- 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005,
- 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832,
- 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804,
- 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802,
- 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a,
- 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6,
- 0x00c6, 0x2071, 0xb01e, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0,
- 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x34d6, 0x34c1,
- 0x34cd, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c,
- 0x3486, 0x0160, 0x080c, 0x3486, 0x0048, 0x8001, 0x7002, 0x7804,
- 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ce, 0x00ee,
- 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b,
- 0x0004, 0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085,
- 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038,
- 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3c05,
- 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220,
- 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080,
- 0x000d, 0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3c05,
- 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001,
- 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061,
- 0x0020, 0x2079, 0x0100, 0x6013, 0x0400, 0x20e1, 0x9040, 0x2001,
- 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001,
- 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006,
- 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071,
- 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336,
- 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122,
- 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003,
- 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6,
- 0x2d60, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x6018, 0x2070, 0x2d00,
- 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005,
- 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001,
- 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3c05, 0x2d60,
- 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220,
- 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080,
- 0x000d, 0x080c, 0x353e, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c,
- 0x3c05, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00,
- 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004,
- 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001,
- 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824,
- 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027,
- 0x0000, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003,
- 0x0009, 0x00ee, 0x0005, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000,
- 0x20a9, 0x0011, 0x2001, 0xad40, 0x20a0, 0xa006, 0x40a4, 0x012e,
- 0x0804, 0x2dcc, 0x7d38, 0x7c3c, 0x0804, 0x2e73, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c, 0x491f, 0x2009,
- 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b,
- 0x35f2, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x2df4,
- 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2df4, 0xd094, 0x00c6,
- 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218,
- 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c,
- 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010,
- 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a,
- 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04,
- 0x2df4, 0xa288, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x6156, 0xd0dc,
- 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2df4, 0x604e, 0x6808,
- 0xa08a, 0x0100, 0x0a04, 0x2df4, 0xa08a, 0x0841, 0x1a04, 0x2df4,
- 0xa084, 0x0007, 0x1904, 0x2df4, 0x680c, 0xa005, 0x0904, 0x2df4,
- 0x6810, 0xa005, 0x0904, 0x2df4, 0x6848, 0x6940, 0xa10a, 0x1a04,
- 0x2df4, 0x8001, 0x0904, 0x2df4, 0x684c, 0x6944, 0xa10a, 0x1a04,
- 0x2df4, 0x8001, 0x0904, 0x2df4, 0x6804, 0xd0fc, 0x0560, 0x080c,
- 0x3c05, 0x0904, 0x2df1, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c,
- 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3c46, 0x701b,
- 0x3672, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069,
- 0xad6d, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xad71,
- 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085,
- 0x0b00, 0x6006, 0x00ce, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xad51,
- 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084,
- 0x00ff, 0x6042, 0x080c, 0x5a1c, 0x080c, 0x5070, 0x080c, 0x50d9,
- 0x6000, 0xa086, 0x0000, 0x1904, 0x3755, 0x6808, 0x602a, 0x080c,
- 0x22f8, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e,
- 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b,
- 0x0000, 0x0036, 0x6b08, 0x080c, 0x26fb, 0x003e, 0x6818, 0x691c,
- 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a,
- 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38,
- 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff,
- 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f,
- 0x20a9, 0x0004, 0x20a1, 0xafad, 0x40a1, 0x080c, 0x659c, 0x6904,
- 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70,
- 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c,
- 0x5fa9, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007,
- 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003,
- 0x0010, 0x6003, 0x0001, 0x1f04, 0x36f3, 0x00ce, 0x2069, 0xad51,
- 0x2001, 0xaf9d, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170,
- 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa,
- 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x0008, 0x2102, 0x00c6,
- 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c,
- 0x574f, 0x0128, 0x080c, 0x3e5f, 0x0110, 0x080c, 0x26c0, 0x60c4,
- 0xa005, 0x01b0, 0x6003, 0x0001, 0x2009, 0x373f, 0x00c0, 0x080c,
- 0x574f, 0x1158, 0x2011, 0x566e, 0x080c, 0x650d, 0x2001, 0xaf9e,
- 0x2003, 0x0000, 0x080c, 0x569a, 0x0040, 0x080c, 0x485e, 0x0028,
- 0x6003, 0x0004, 0x2009, 0x3755, 0x0010, 0x0804, 0x2dcc, 0x2001,
- 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004,
- 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817,
- 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x2df1,
- 0x2069, 0xad51, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc,
- 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c,
- 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0xa006, 0x080c, 0x26c0,
- 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x1178, 0x2001, 0xaf9e,
- 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085, 0x0001,
- 0x080c, 0x5793, 0x080c, 0x569a, 0x0020, 0x080c, 0x491f, 0x080c,
- 0x485e, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f,
- 0x1110, 0x0804, 0x2df1, 0x6184, 0x81ff, 0x0198, 0x703f, 0x0000,
- 0x2001, 0xb3c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x3c49, 0x701b, 0x2dca, 0x012e,
- 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xb3c0, 0x20a9, 0x0040,
- 0x20a1, 0xb3c0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x2be6,
- 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100,
- 0xa506, 0x01a8, 0x080c, 0x4cdc, 0x1190, 0x6014, 0x821c, 0x0238,
- 0xa398, 0xb3c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, 0xa398,
- 0xb3c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108,
- 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105,
- 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb3c0,
- 0x080c, 0x48be, 0x0804, 0x37b0, 0x080c, 0x3c2a, 0x0904, 0x2df4,
- 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0b4, 0x01f0, 0x6000, 0xd08c,
- 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x970b, 0x1120, 0x2009,
- 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3830, 0x0005,
- 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x20a9, 0x002b, 0x2c98, 0xade8,
- 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098,
- 0xad80, 0x0006, 0x20a0, 0x080c, 0x48be, 0x20a9, 0x0004, 0xac80,
- 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x48be, 0x2d00,
- 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49,
- 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c,
- 0x4eab, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x7828, 0xa08a,
- 0x1000, 0x1a04, 0x2df4, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c,
- 0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0004, 0x080c, 0x4ebd, 0x7924,
- 0x810f, 0x7a28, 0x0011, 0x0804, 0x2dcc, 0xa186, 0x00ff, 0x0110,
- 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xad00, 0x644c, 0x2400,
- 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c,
- 0x4cdc, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c,
- 0x6519, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904,
- 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4eb4, 0x0804,
- 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4,
- 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0804, 0x2dcc,
- 0x6100, 0x0804, 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x2001,
- 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00d6, 0xace8,
- 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007,
- 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
- 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2dcc, 0x7824, 0xa09c,
- 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2df1, 0x624c, 0xa294, 0x00ff,
- 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xad40, 0x2009,
- 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x81ff,
- 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05,
- 0x00ce, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
- 0x080c, 0x96b7, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3919,
- 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0xad80, 0x000e,
- 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49,
- 0xa006, 0x080c, 0x26c0, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
- 0x0118, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c,
- 0x491f, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x7924, 0xa18c,
- 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04,
- 0x2df4, 0x2100, 0x080c, 0x268a, 0x0026, 0x00c6, 0x0126, 0x2091,
- 0x8000, 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c,
- 0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00,
- 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a,
- 0x00a0, 0x2061, 0x0100, 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff,
- 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
- 0x002d, 0x2011, 0x4883, 0x080c, 0x6593, 0x7924, 0xa18c, 0xff00,
- 0x810f, 0x080c, 0x574f, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c,
- 0x387d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x2dcc, 0x7924, 0xa18c,
- 0xff00, 0x810f, 0x00c6, 0x080c, 0x4c80, 0x2c08, 0x00ce, 0x1904,
- 0x2df4, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
- 0x2df1, 0x60d0, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005,
- 0x0804, 0x2df1, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46,
- 0x701b, 0x39bb, 0x0005, 0x2009, 0x0080, 0x080c, 0x4cdc, 0x1130,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a,
- 0x0804, 0x2dce, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c,
- 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3a32,
- 0xa0be, 0x0112, 0x0904, 0x3a32, 0xa0be, 0x0113, 0x0904, 0x3a32,
- 0xa0be, 0x0114, 0x0904, 0x3a32, 0xa0be, 0x0117, 0x0904, 0x3a32,
- 0xa0be, 0x011a, 0x0904, 0x3a32, 0xa0be, 0x011c, 0x0904, 0x3a32,
- 0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171,
- 0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830,
- 0x8007, 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213,
- 0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be,
- 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300,
- 0x01c8, 0x00de, 0x0804, 0x2df4, 0xad80, 0x0010, 0x20a9, 0x0007,
- 0x080c, 0x3a78, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3a78,
- 0x0048, 0xad80, 0x000c, 0x080c, 0x3a86, 0x0050, 0xad80, 0x000e,
- 0x080c, 0x3a86, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3a78,
- 0x00c6, 0x080c, 0x3c05, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837,
- 0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b,
- 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996,
- 0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x96d3, 0x1120,
- 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3a6f,
- 0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6820,
- 0xa086, 0x8001, 0x1904, 0x2dcc, 0x2009, 0x0004, 0x0804, 0x2df1,
- 0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108,
- 0x280a, 0x8108, 0x1f04, 0x3a7a, 0x001e, 0x0005, 0x0016, 0x00a6,
- 0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000,
- 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a,
- 0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001,
- 0x0804, 0x2df1, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d0,
- 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182, 0x00ff,
- 0x1a04, 0x2df4, 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x1140, 0x6070,
- 0xa24e, 0x0904, 0x2df4, 0xa9cc, 0xff00, 0x0904, 0x2df4, 0x00c6,
- 0x080c, 0x3b58, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180,
- 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108,
- 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088,
- 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118,
- 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001,
- 0x4006, 0x2020, 0x0804, 0x2dce, 0x2d00, 0x7022, 0x0016, 0x00b6,
- 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x8022, 0x05d8, 0x2d00, 0x601a,
- 0x080c, 0x9956, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3c05,
- 0x00ce, 0x2b70, 0x1150, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00be,
- 0x001e, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6837, 0x0000, 0x683b,
- 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c,
- 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9,
- 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001,
- 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085,
- 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003,
- 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3b3f, 0x0005, 0x6830,
- 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204,
- 0xa294, 0x00ff, 0x0804, 0x2df1, 0x2009, 0x0000, 0x080c, 0x4f6e,
- 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2dcc,
- 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0xad34, 0x2004, 0xd0ac,
- 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34, 0x0030,
- 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xaeb4, 0x2e04, 0xa005,
- 0x1130, 0x2100, 0xa406, 0x1548, 0x2428, 0xc5fd, 0x0430, 0x2068,
- 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, 0xa206, 0x1190,
- 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0540, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x1510, 0x2001, 0x4000, 0x0400, 0x2001,
- 0x4007, 0x00e8, 0x2400, 0xa106, 0x1140, 0x6e14, 0x87ff, 0x1110,
- 0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04,
- 0x3b6e, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001,
- 0x0030, 0x080c, 0x4c80, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005,
- 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824,
- 0xa005, 0x0904, 0x2df4, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004,
- 0x1a04, 0x2df4, 0x2010, 0x2d18, 0x080c, 0x2a8c, 0x0904, 0x2df1,
- 0x7007, 0x0003, 0x701b, 0x3bd5, 0x0005, 0x6830, 0xa086, 0x0100,
- 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x7924, 0xa18c, 0xff00, 0x810f,
- 0x60d0, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182,
- 0x00ff, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x080c, 0x95c6,
- 0x1188, 0xa190, 0xae34, 0x2204, 0xa065, 0x0160, 0x080c, 0x493a,
- 0x2001, 0xad34, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e,
- 0x0804, 0x2dcc, 0x012e, 0x0804, 0x2df1, 0x080c, 0x15d9, 0x0188,
- 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016,
- 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80,
- 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc,
- 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066,
- 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x4cdc,
- 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff,
- 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c,
- 0x15f0, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001,
- 0x0010, 0x2031, 0x0000, 0x2061, 0xadd1, 0x6606, 0x6112, 0x600e,
- 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007,
- 0x0002, 0x701b, 0x2dcc, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000,
- 0x2079, 0x0000, 0x2001, 0xad8f, 0x2004, 0xa005, 0x1168, 0x0e04,
- 0x3c74, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b,
- 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071,
- 0xad81, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078,
- 0x7030, 0xa0e0, 0x0004, 0xac82, 0xadd1, 0x0210, 0x2061, 0xad91,
- 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262,
- 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005,
- 0x00e6, 0x2071, 0xad81, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091,
- 0x8000, 0x0e04, 0x3ccb, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084,
- 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826,
- 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001,
- 0x703a, 0xa005, 0x1130, 0x7033, 0xad91, 0x7037, 0xad91, 0x00ce,
- 0x0048, 0xac80, 0x0004, 0xa0fa, 0xadd1, 0x0210, 0x2001, 0xad91,
- 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001,
- 0xad52, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3c5c,
- 0x002e, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x0126, 0x2091, 0x8000,
- 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x574f, 0x1178,
- 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001,
- 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x0010, 0x080c,
- 0x485e, 0x012e, 0x0804, 0x2dcc, 0x7824, 0x2008, 0xa18c, 0xfffd,
- 0x1128, 0x61dc, 0xa10d, 0x61de, 0x0804, 0x2dcc, 0x0804, 0x2df4,
- 0x81ff, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x1904, 0x2df1,
- 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1904, 0x2df1, 0x080c, 0x3c2a,
- 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120,
- 0x7828, 0xa005, 0x0904, 0x2dcc, 0x00c6, 0x080c, 0x3c05, 0x00ce,
- 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x080c, 0x979c, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b,
- 0x3d3a, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0x0804,
- 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1,
- 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c05, 0x0904,
- 0x2df1, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f,
- 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x4cdc, 0x1904,
- 0x3db4, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4,
- 0xff00, 0xa8c6, 0x0600, 0x1904, 0x3db4, 0x2001, 0xad52, 0x2004,
- 0xd0ac, 0x1128, 0x080c, 0x4f6e, 0x1110, 0xd79c, 0x05e8, 0xd794,
- 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9,
- 0x0004, 0x53a3, 0x080c, 0x3a86, 0xd794, 0x0148, 0xac80, 0x000a,
- 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3a86, 0x21a2,
- 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002,
- 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098,
- 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3a78, 0xac80, 0x0026,
- 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110,
- 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186,
- 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118,
- 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x3d5d,
- 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x702f, 0x0001,
- 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xadd1, 0x6007,
- 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532,
- 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b, 0x3df0, 0x0005,
- 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031,
- 0x0000, 0x2061, 0xadd1, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804,
- 0x3d5d, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x2029, 0x007e, 0x7924,
- 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020,
- 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa184, 0x00ff, 0xa0e2,
- 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa284, 0xff00,
- 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4,
- 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04,
- 0x2df4, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4,
- 0xa502, 0x0a04, 0x2df4, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04,
- 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0xff00, 0x8007, 0xa0e2,
- 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0x00ff,
- 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0x2061,
- 0xafa6, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2dcc, 0x0006,
- 0x2001, 0xad52, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001,
- 0xad71, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6164, 0x7a24, 0x6300,
- 0x82ff, 0x1118, 0x7926, 0x0804, 0x2dcc, 0x83ff, 0x1904, 0x2df4,
- 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2df4, 0x2019, 0xffff, 0x6068,
- 0xa302, 0xa200, 0x0a04, 0x2df4, 0x7926, 0x6266, 0x0804, 0x2dcc,
- 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x7c28,
- 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x2009,
- 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80,
- 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xae34, 0x2c64, 0x8cff, 0x01b8,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084,
- 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010,
- 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108,
- 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff,
- 0x1120, 0x7120, 0x810c, 0x0804, 0x2dcc, 0x702f, 0x0001, 0x711e,
- 0x7020, 0xa300, 0x7022, 0x2061, 0xadd1, 0x6007, 0x0000, 0x6312,
- 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c,
- 0x1624, 0x7007, 0x0002, 0x701b, 0x3ee6, 0x0005, 0x702c, 0xa005,
- 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xadd1,
- 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3ea3, 0x7120, 0x810c,
- 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x60d0, 0xd0ac, 0x1118,
- 0xd09c, 0x0904, 0x2df1, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x7924,
- 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b, 0x3f11,
- 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148,
- 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804,
- 0x2df4, 0x6820, 0x6924, 0x080c, 0x2676, 0x1510, 0x080c, 0x4c80,
- 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3c05,
- 0x01b8, 0x080c, 0x3c05, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000,
- 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c,
- 0x96ef, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3f4b, 0x0005,
- 0x00de, 0x0804, 0x2df1, 0x7120, 0x080c, 0x2bc9, 0x6820, 0xa086,
- 0x8001, 0x0904, 0x2df1, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002,
- 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x48be, 0x000e,
- 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xadd1,
- 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018,
- 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2df4, 0x2009,
- 0x0004, 0x0804, 0x3c49, 0xa7c6, 0x7200, 0x1904, 0x2df4, 0xa6c2,
- 0x0054, 0x0a04, 0x2df4, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a,
- 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b,
- 0x3f92, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004,
- 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c,
- 0x48be, 0x000e, 0x2009, 0x002a, 0x2061, 0xadd1, 0x6224, 0x6328,
- 0x642c, 0x6530, 0x0804, 0x3c49, 0x81ff, 0x1904, 0x2df1, 0x080c,
- 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c,
- 0x4ec6, 0x0804, 0x2dcc, 0x7824, 0xd084, 0x0904, 0x3804, 0x080c,
- 0x3c2a, 0x0904, 0x2df4, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120,
- 0x2009, 0x0002, 0x0804, 0x2df1, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x1508,
- 0x2001, 0xad52, 0x2004, 0xd0b4, 0x0904, 0x3834, 0x6000, 0xd08c,
- 0x1904, 0x3834, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c,
- 0x970b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003,
- 0x701b, 0x3ff3, 0x0005, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x0804,
- 0x3834, 0x2009, 0xad30, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001,
- 0x0804, 0x2df1, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x0120,
- 0x2009, 0x0007, 0x0804, 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0ac,
- 0x0120, 0x2009, 0x0008, 0x0804, 0x2df1, 0x609c, 0xd0a4, 0x1118,
- 0xd0ac, 0x1904, 0x3834, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838,
- 0xc0fd, 0x683a, 0x080c, 0x979c, 0x1120, 0x2009, 0x0003, 0x0804,
- 0x2df1, 0x7007, 0x0003, 0x701b, 0x402e, 0x0005, 0x6830, 0xa086,
- 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2df1, 0x080c, 0x3c2a,
- 0x0904, 0x2df4, 0x0804, 0x3fd8, 0x81ff, 0x2009, 0x0001, 0x1904,
- 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2df1,
- 0x2001, 0xad52, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x2df1,
- 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05,
- 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c,
- 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956,
- 0x0048, 0xa28e, 0x0100, 0x1904, 0x2df4, 0xc0e5, 0x6853, 0x0000,
- 0x6857, 0x0000, 0x683e, 0x080c, 0x9957, 0x2009, 0x0003, 0x0904,
- 0x2df1, 0x7007, 0x0003, 0x701b, 0x408e, 0x0005, 0x6830, 0xa086,
- 0x0100, 0x2009, 0x0004, 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x81ff,
- 0x2009, 0x0001, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009,
- 0x0007, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004,
- 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1,
- 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1,
- 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x080c, 0x3c46, 0x701b, 0x40c5, 0x0005, 0x00d6, 0xade8, 0x000f,
- 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808,
- 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x2df4, 0x00de,
- 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6,
- 0x080c, 0x3c2a, 0x1118, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x99a6,
- 0x2009, 0x0003, 0x00ce, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b,
- 0x40f2, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904,
- 0x2df1, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
- 0x2df1, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804,
- 0x2df1, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c,
- 0x4cdc, 0x1904, 0x2df4, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2df1,
- 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9726,
- 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b,
- 0x413a, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, 0x1120, 0x2009,
- 0x0004, 0x0804, 0x2df1, 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084,
- 0x00ff, 0x808e, 0x6814, 0x8007, 0xa084, 0x00ff, 0x8086, 0xa080,
- 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x0804, 0x3c49, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff,
- 0x0110, 0x0804, 0x2df4, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c,
- 0x7d38, 0x080c, 0x3c46, 0x701b, 0x4176, 0x0005, 0xad80, 0x000d,
- 0x2098, 0x20a9, 0x001a, 0x20a1, 0xafad, 0x53a3, 0x0804, 0x2dcc,
- 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804, 0x2df1, 0x7924,
- 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804,
- 0x2df4, 0x2099, 0xafad, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009,
- 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x7824,
- 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x8003,
- 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xafda, 0x6142, 0x00ce,
- 0x012e, 0x0804, 0x2dcc, 0x00c6, 0x080c, 0x574f, 0x1188, 0x2001,
- 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085,
- 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x080c, 0x14f6, 0x0038,
- 0x2061, 0xad00, 0x6030, 0xc09d, 0x6032, 0x080c, 0x485e, 0x00ce,
- 0x0005, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00,
- 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x4348, 0x0068,
- 0xd08c, 0x0118, 0x080c, 0x4269, 0x0040, 0xd094, 0x0118, 0x080c,
- 0x423a, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e,
- 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e,
- 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0,
- 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294,
- 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240,
- 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7,
- 0x080c, 0x48de, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040,
- 0x6042, 0x6043, 0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b7,
- 0x0000, 0x70d3, 0x0000, 0x2009, 0xb3c0, 0x200b, 0x0000, 0x7087,
- 0x0000, 0x707b, 0x000a, 0x2009, 0x000a, 0x2011, 0x4814, 0x080c,
- 0x6593, 0x0005, 0x0156, 0x2001, 0xad73, 0x2004, 0xd08c, 0x0110,
- 0x704f, 0xffff, 0x7078, 0xa005, 0x1510, 0x2011, 0x4814, 0x080c,
- 0x650d, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9,
- 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4251, 0x6242, 0x708b,
- 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242,
- 0x0030, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e,
- 0x0005, 0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c,
- 0x14f6, 0x0005, 0x4275, 0x42c5, 0x4347, 0x00f6, 0x707f, 0x0001,
- 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x22f8, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x2079, 0xb200, 0x207b, 0x2200, 0x7807,
- 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817,
- 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827,
- 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xb20c, 0x207b,
- 0x1101, 0x7807, 0x0000, 0x2099, 0xad05, 0x20a1, 0xb20e, 0x20a9,
- 0x0004, 0x53a3, 0x2079, 0xb212, 0x207b, 0x0000, 0x7807, 0x0000,
- 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3,
- 0x000c, 0x600f, 0x0000, 0x080c, 0x4845, 0x00fe, 0x7083, 0x0000,
- 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083,
- 0x0000, 0xa025, 0x0904, 0x432f, 0x6020, 0xd0b4, 0x1904, 0x432d,
- 0x7190, 0x81ff, 0x0904, 0x431d, 0xa486, 0x000c, 0x1904, 0x4328,
- 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xb280, 0x2019, 0xb200,
- 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x42e0,
- 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006,
- 0x707f, 0x0002, 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x481b,
- 0x080c, 0x6593, 0x0490, 0x2069, 0xb280, 0x6930, 0xa18e, 0x1101,
- 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118,
- 0x6804, 0xa005, 0x0190, 0x2011, 0xb28e, 0x2019, 0xad05, 0x20a9,
- 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318,
- 0x1f04, 0x4311, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6,
- 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040,
- 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c,
- 0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080,
- 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x0c30, 0x0005,
- 0x7088, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x14f6,
- 0x0005, 0x437b, 0x438a, 0x43b2, 0x43cb, 0x43ef, 0x4417, 0x443b,
- 0x446c, 0x4490, 0x44b8, 0x44ef, 0x4517, 0x4533, 0x4549, 0x4569,
- 0x457c, 0x4584, 0x45b1, 0x45d5, 0x45fd, 0x4621, 0x4652, 0x468f,
- 0x46be, 0x46da, 0x4719, 0x4739, 0x4752, 0x4753, 0x00c6, 0x2061,
- 0xad00, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9,
- 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043,
- 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x481b, 0x080c,
- 0x6593, 0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1508, 0x6043,
- 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128,
- 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x2011, 0x481b, 0x080c,
- 0x650d, 0x708b, 0x0010, 0x080c, 0x4584, 0x0010, 0x080c, 0x485e,
- 0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x481b,
- 0x080c, 0x650d, 0x080c, 0x48c6, 0x20a3, 0x1102, 0x20a3, 0x0000,
- 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x43c2, 0x60c3, 0x0014,
- 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011,
- 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280,
- 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38,
- 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b,
- 0x0004, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b,
- 0x0005, 0x080c, 0x48c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430,
- 0x2011, 0xb28e, 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148,
- 0x714c, 0xa186, 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c,
- 0x48f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6,
- 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086,
- 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1103, 0x1178,
- 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005,
- 0x1110, 0x70b7, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010, 0x080c,
- 0x485e, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x48c6, 0x20a3,
- 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917,
- 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170,
- 0xa180, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df,
- 0x0128, 0x080c, 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008,
- 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0,
- 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079,
- 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160,
- 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001,
- 0x708b, 0x0008, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005,
- 0x708b, 0x0009, 0x080c, 0x48c6, 0x20a3, 0x1105, 0x20a3, 0x0100,
- 0x3430, 0x080c, 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c,
- 0x4754, 0x1170, 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008,
- 0x2099, 0xb28e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x60c3, 0x0014, 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005,
- 0x00f6, 0x7080, 0xa005, 0x0588, 0x2011, 0x481b, 0x080c, 0x650d,
- 0xa086, 0x0014, 0x1540, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1105,
- 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc,
- 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x000a,
- 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b4,
- 0xa005, 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e,
- 0x080c, 0x4569, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b,
- 0x000b, 0x2011, 0xb20e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff,
- 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x48c6,
- 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4917, 0x0118, 0x2013,
- 0x0000, 0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9,
- 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4845, 0x0005, 0x00f6,
- 0x7080, 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086,
- 0x0084, 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138,
- 0x7834, 0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c,
- 0x485e, 0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x48c6, 0x20a3,
- 0x1107, 0x20a3, 0x0000, 0x2099, 0xb28e, 0x20a9, 0x0040, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845,
- 0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c,
- 0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c,
- 0x48b8, 0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
- 0x0005, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f,
- 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011,
- 0x481b, 0x080c, 0x6501, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011,
- 0x481b, 0x080c, 0x650d, 0x0005, 0x708b, 0x0011, 0x080c, 0x4917,
- 0x1188, 0x716c, 0x81ff, 0x0170, 0x2009, 0x0000, 0x7070, 0xa084,
- 0x00ff, 0x080c, 0x2676, 0xa186, 0x0080, 0x0120, 0x2011, 0xb28e,
- 0x080c, 0x47df, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280,
- 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084,
- 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4845,
- 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c,
- 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128,
- 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x0012, 0x0029,
- 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c,
- 0x48d2, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e,
- 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186,
- 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c, 0x48f5, 0x20a9,
- 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005,
- 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8,
- 0x2079, 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005,
- 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7,
- 0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
- 0x0005, 0x708b, 0x0015, 0x080c, 0x48d2, 0x20a3, 0x1104, 0x20a3,
- 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917, 0x11a8, 0x7074,
- 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2be6,
- 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df, 0x0128, 0x080c,
- 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2298, 0x26a0,
- 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
- 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05b8, 0x2011, 0x481b,
- 0x080c, 0x650d, 0xa086, 0x0014, 0x1570, 0x2079, 0xb280, 0x7a30,
- 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148,
- 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001,
- 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005,
- 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0138,
- 0x2001, 0xad73, 0x2004, 0xd0a4, 0x1110, 0x70d3, 0x0008, 0x708b,
- 0x0016, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9,
- 0x000e, 0x53a6, 0x3430, 0x2011, 0xb28e, 0x708b, 0x0017, 0x080c,
- 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c, 0x4754, 0x1170,
- 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2099, 0xb28e,
- 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
- 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005, 0x00f6, 0x7080,
- 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0084,
- 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834,
- 0xa005, 0x1120, 0x708b, 0x0018, 0x0029, 0x0010, 0x080c, 0x485e,
- 0x00fe, 0x0005, 0x708b, 0x0019, 0x080c, 0x48d2, 0x20a3, 0x1106,
- 0x20a3, 0x0000, 0x3430, 0x2099, 0xb28e, 0x2039, 0xb20e, 0x27a0,
- 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4917, 0x11e8, 0x2728, 0x2514,
- 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
- 0xa205, 0x202a, 0x7050, 0x2310, 0x8214, 0xa2a0, 0xb20e, 0x2414,
- 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff,
- 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845,
- 0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c,
- 0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c,
- 0x48b8, 0x708b, 0x001a, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
- 0x0005, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
- 0xb280, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007,
- 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c,
- 0x4845, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xad52,
- 0x252c, 0x20a9, 0x0008, 0x2041, 0xb20e, 0x28a0, 0x2099, 0xb28e,
- 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011,
- 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4,
- 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4769, 0x0804, 0x47d7,
- 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020,
- 0xa1a6, 0x3fff, 0x0904, 0x47d7, 0xa18d, 0xc000, 0x20a9, 0x0010,
- 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4,
- 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319,
- 0x0008, 0x8318, 0x1f04, 0x478f, 0x04d0, 0x23a8, 0x2021, 0x0001,
- 0x8426, 0x8425, 0x1f04, 0x47a1, 0x2328, 0x8529, 0xa2be, 0x0007,
- 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8,
- 0xa5a8, 0x0010, 0x1f04, 0x47b0, 0x754e, 0xa5c8, 0x2be6, 0x292d,
- 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c,
- 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405,
- 0x201a, 0x7077, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006,
- 0x0018, 0xa006, 0x080c, 0x14f6, 0x009e, 0x008e, 0x0005, 0x2118,
- 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420,
- 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421,
- 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8,
- 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x714e, 0xa1a0,
- 0x2be6, 0x242d, 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016,
- 0x2508, 0x080c, 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7077,
- 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x707b,
- 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071,
- 0x0140, 0x080c, 0x7834, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003,
- 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, 0x2071, 0xad22,
- 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c,
- 0x48de, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42,
- 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1,
- 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x2009,
- 0x07d0, 0x2011, 0x481b, 0x080c, 0x6593, 0x0005, 0x0016, 0x0026,
- 0x00c6, 0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x48de,
- 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xad00,
- 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010,
- 0x2009, 0x002d, 0x2011, 0x4883, 0x080c, 0x6501, 0x012e, 0x00ce,
- 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000,
- 0x2071, 0x0100, 0x080c, 0x7834, 0x2071, 0x0140, 0x7004, 0xa084,
- 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x5757,
- 0x01a8, 0x080c, 0x5775, 0x1190, 0x2001, 0xaf9d, 0x2003, 0xaaaa,
- 0x0016, 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x001e, 0x2001,
- 0xaf9e, 0x2003, 0x0000, 0x080c, 0x569a, 0x0030, 0x2001, 0x0001,
- 0x080c, 0x261e, 0x080c, 0x485e, 0x012e, 0x000e, 0x00ee, 0x0005,
- 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb28e, 0x3304, 0x8007,
- 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x48be, 0x0005, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x000c,
- 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280,
- 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006,
- 0x2061, 0x0100, 0x810f, 0x2001, 0xad30, 0x2004, 0xa005, 0x1138,
- 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185,
- 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001,
- 0xad52, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a,
- 0x080c, 0xa96c, 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019,
- 0x002a, 0x2009, 0x0000, 0x080c, 0x2aac, 0x004e, 0x001e, 0x0005,
- 0x080c, 0x485e, 0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006,
- 0x2001, 0xad0c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006,
- 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d,
- 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9,
- 0x00ff, 0x2009, 0xae34, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4934,
- 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069,
- 0xad51, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012,
- 0xa198, 0x2be6, 0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004,
- 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a,
- 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a,
- 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a,
- 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a,
- 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c,
- 0x15f0, 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0,
- 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c,
- 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e,
- 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6944, 0x6e48,
- 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, 0x4a49, 0xa18c, 0xff00,
- 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4a4e, 0x2001, 0xad0c, 0x2004,
- 0xa084, 0x0003, 0x01c0, 0x2001, 0xad0c, 0x2004, 0xd084, 0x1904,
- 0x4a31, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904, 0x4a31, 0x6004,
- 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a31, 0x6000, 0xd0c4,
- 0x0904, 0x4a31, 0x0068, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904,
- 0x4a15, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a1a,
- 0x60a4, 0xa00d, 0x0118, 0x080c, 0x4ef9, 0x05d0, 0x60a8, 0xa00d,
- 0x0188, 0x080c, 0x4f43, 0x1170, 0x694c, 0xd1fc, 0x1118, 0x080c,
- 0x4c11, 0x0448, 0x080c, 0x4bd3, 0x694c, 0xd1ec, 0x1520, 0x080c,
- 0x4ded, 0x0408, 0x694c, 0xa184, 0xa000, 0x0178, 0xd1ec, 0x0140,
- 0xd1fc, 0x0118, 0x080c, 0x4dfc, 0x0028, 0x080c, 0x4dfc, 0x0028,
- 0xd1fc, 0x0118, 0x080c, 0x4bd3, 0x0070, 0x6050, 0xa00d, 0x0130,
- 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0028, 0x2d00, 0x6052,
- 0x604e, 0x6803, 0x0000, 0x080c, 0x67c5, 0xa006, 0x012e, 0x0005,
- 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, 0x2001, 0x0028, 0x2009,
- 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, 0x6100, 0xd1fc, 0x0904,
- 0x49d0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0420, 0x2001, 0x0028,
- 0x00a8, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004,
- 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029,
- 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0060, 0x2009, 0x0000,
- 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029,
- 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091,
- 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff,
- 0x1a04, 0x4aa8, 0xa188, 0xae34, 0x2104, 0xa065, 0x01c0, 0x6004,
- 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, 0x2c70, 0x080c, 0x8022,
- 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f,
- 0x000a, 0x2009, 0x0003, 0x080c, 0x80a7, 0xa006, 0x0460, 0x2001,
- 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8,
- 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090,
- 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050,
- 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010,
- 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c,
- 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0000,
- 0x2079, 0xad00, 0x6944, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
- 0x1a04, 0x4b77, 0x2001, 0xad0c, 0x2004, 0xa084, 0x0003, 0x1904,
- 0x4b65, 0x080c, 0x4cdc, 0x1180, 0x6004, 0xa084, 0x00ff, 0xa082,
- 0x0006, 0x1250, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1904, 0x4b60,
- 0x60a0, 0xd0bc, 0x1904, 0x4b60, 0x6864, 0xa0c6, 0x006f, 0x0118,
- 0x2008, 0x0804, 0x4b28, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f,
- 0x78d0, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff,
- 0x16b8, 0x6a70, 0x6b6c, 0x786c, 0xa306, 0x1160, 0x7870, 0xa24e,
- 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208,
- 0x2310, 0x0430, 0x080c, 0x3b58, 0x2c70, 0x0550, 0x2009, 0x0000,
- 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c,
- 0x4f6e, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e,
- 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008,
- 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010,
- 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0458,
- 0x080c, 0x8022, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011,
- 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0x9956, 0x2d00, 0x6012,
- 0x601f, 0x0001, 0xa006, 0xd88c, 0x0110, 0x2001, 0x4000, 0x683a,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9, 0x012e, 0x2001, 0x0000,
- 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002,
- 0x080c, 0x80a7, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005,
- 0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xad0c, 0x210c,
- 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001,
- 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001,
- 0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff,
- 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
- 0x12e0, 0xa188, 0xae34, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084,
- 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c,
- 0x4dfc, 0x04c9, 0x0030, 0x04b9, 0x684c, 0xd0fc, 0x0110, 0x080c,
- 0x4ded, 0x080c, 0x4e3a, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009,
- 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20,
- 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009,
- 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005,
- 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a,
- 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e,
- 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005,
- 0x0170, 0x00e6, 0x2071, 0xafc7, 0x7004, 0xa086, 0x0002, 0x0168,
- 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00,
- 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80,
- 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e,
- 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800,
- 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c,
- 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05,
- 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a,
- 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6,
- 0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110,
- 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005,
- 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006,
- 0xa086, 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xad52,
- 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007,
- 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206,
- 0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c,
- 0x14f6, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091,
- 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178,
- 0x609c, 0xd0a4, 0x0160, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1138,
- 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e,
- 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005,
- 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190,
- 0xae34, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15c0,
- 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000,
- 0x60ab, 0x0000, 0x080c, 0x493a, 0xa006, 0x002e, 0x0005, 0x0126,
- 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001,
- 0x0480, 0x00d6, 0xa190, 0xae34, 0x2204, 0xa06d, 0x0540, 0x2013,
- 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c,
- 0x15f0, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00ce, 0x00de,
- 0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006,
- 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x1600, 0x080c,
- 0x8078, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x15f0, 0x00de,
- 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218,
- 0xa085, 0x0001, 0x0030, 0xa188, 0xae34, 0x2104, 0xa065, 0x0dc0,
- 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b,
- 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x574f,
- 0x1538, 0x60a0, 0xa086, 0x007e, 0x2069, 0xb290, 0x0130, 0x2001,
- 0xad34, 0x2004, 0xd0ac, 0x11e0, 0x0098, 0x2d04, 0xd0e4, 0x01c0,
- 0x00d6, 0x2069, 0xb28e, 0x00c6, 0x2061, 0xaf9f, 0x6810, 0x2062,
- 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de,
- 0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0xad00, 0x68a2,
- 0x2069, 0xb28e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a,
- 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xb296, 0xac88, 0x000a,
- 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xb29a, 0xac88, 0x0006,
- 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xb2ae, 0x6808, 0x606a,
- 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211,
- 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009,
- 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0,
- 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421,
- 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009,
- 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e,
- 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0xb28d, 0x2e04,
- 0x6896, 0x2071, 0xb28e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00,
- 0x2009, 0xad71, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad,
- 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008,
- 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126,
- 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540,
- 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010,
- 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x4da8, 0x080c,
- 0x14f6, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x15d9, 0x01a8,
- 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010,
- 0x200b, 0xffff, 0x8108, 0x1f04, 0x4dc0, 0x6807, 0x0001, 0x6e12,
- 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126,
- 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800,
- 0xa005, 0x1160, 0x080c, 0x4ef9, 0x1168, 0x200b, 0xffff, 0x6804,
- 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x15f0,
- 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x4f56, 0x0010, 0x080c, 0x4bc0, 0x080c, 0x4e71, 0x1dd8,
- 0x080c, 0x4e3a, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
- 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282,
- 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086,
- 0xffff, 0x0128, 0x8108, 0x1f04, 0x4e0e, 0x080c, 0x14f6, 0x260a,
- 0x8210, 0x6a56, 0x0098, 0x080c, 0x15d9, 0x01d0, 0x2d00, 0x60aa,
- 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff,
- 0x8108, 0x1f04, 0x4e26, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c,
- 0x4c11, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005,
- 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, 0x67c5, 0x012e,
- 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091,
- 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8,
- 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406,
- 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70,
- 0x6a00, 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000,
- 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e,
- 0x0010, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8,
- 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406,
- 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70,
- 0x6a00, 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000,
- 0x2202, 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c,
- 0x4ef3, 0x1110, 0x2011, 0x0001, 0x080c, 0x4f3d, 0x1110, 0xa295,
- 0x0002, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x964b, 0x0010,
- 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x95e4,
- 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c,
- 0x962e, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118,
- 0x080c, 0x9600, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e,
- 0x0118, 0x080c, 0x9667, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126,
- 0x0006, 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800,
- 0x0006, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd,
- 0x0006, 0x6000, 0xd0fc, 0x0110, 0x080c, 0xac03, 0x000e, 0x080c,
- 0x510c, 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de,
- 0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001,
- 0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010,
- 0xae88, 0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4f02,
- 0xa085, 0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091,
- 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x15d9, 0x01a0, 0x2d00,
- 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9,
- 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x4f21, 0xa085, 0x0001,
- 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091,
- 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x15f0,
- 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118,
- 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160,
- 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108,
- 0x1f04, 0x4f4c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091,
- 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068,
- 0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c,
- 0x15f0, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4,
- 0x0005, 0x00f6, 0x080c, 0x574f, 0x01b0, 0x71b4, 0x81ff, 0x1198,
- 0x71d0, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xae34, 0x2004,
- 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118,
- 0x7800, 0xc0ed, 0x7802, 0x2079, 0xad51, 0x7804, 0xd0a4, 0x01e8,
- 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c,
- 0x4cdc, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
- 0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e,
- 0x8108, 0x1f04, 0x4f96, 0x00ce, 0x015e, 0x080c, 0x502d, 0x0120,
- 0x2001, 0xafa2, 0x200c, 0x0038, 0x2079, 0xad51, 0x7804, 0xd0a4,
- 0x0130, 0x2009, 0x07d0, 0x2011, 0x4fc1, 0x080c, 0x6593, 0x00fe,
- 0x0005, 0x2011, 0x4fc1, 0x080c, 0x650d, 0x080c, 0x502d, 0x01f0,
- 0x2001, 0xaeb2, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102,
- 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011,
- 0x4fc1, 0x080c, 0x6593, 0x00e6, 0x2071, 0xad00, 0x706f, 0x0000,
- 0x7073, 0x0000, 0x080c, 0x28fa, 0x00ee, 0x04b0, 0x0156, 0x00c6,
- 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1530,
- 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227,
- 0xa006, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6000, 0xc0e5, 0xc0ec,
- 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019,
- 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d,
- 0x2009, 0x0000, 0x080c, 0xa712, 0x007e, 0x004e, 0x001e, 0x8108,
- 0x1f04, 0x4fec, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060,
- 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac,
- 0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xaeb2,
- 0x2004, 0xa07d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126,
- 0x0026, 0x2091, 0x8000, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008,
- 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, 0x2071, 0xae13, 0x7003,
- 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b,
- 0x0000, 0x701f, 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f,
- 0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071,
- 0xaf7c, 0x7003, 0xae13, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f,
- 0xaf5c, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005,
- 0x0016, 0x00e6, 0x2071, 0xaf34, 0xa00e, 0x7186, 0x718a, 0x7097,
- 0x0001, 0x2001, 0xad52, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xad52,
- 0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x50d6,
- 0x2001, 0xad71, 0x200c, 0xa184, 0x000f, 0x2009, 0xad72, 0x210c,
- 0x0002, 0x507e, 0x50b1, 0x50b8, 0x50c2, 0x50c7, 0x507e, 0x507e,
- 0x507e, 0x50a1, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e,
- 0x507e, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75,
- 0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e,
- 0x0428, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030,
- 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097,
- 0x0001, 0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007,
- 0x0121, 0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184,
- 0xff00, 0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e,
- 0x0005, 0x00e6, 0x2071, 0xae13, 0x684c, 0xa005, 0x1130, 0x7028,
- 0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64,
- 0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c,
- 0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000,
- 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210,
- 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007,
- 0x0001, 0xa006, 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838,
- 0xd0fc, 0x1904, 0x5165, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071,
- 0xad00, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00,
- 0x81ff, 0x1dc8, 0x702e, 0x70b0, 0xa200, 0x70b2, 0x00de, 0x2071,
- 0xae13, 0x701c, 0xa005, 0x1904, 0x5175, 0x20a9, 0x0032, 0x0f04,
- 0x5173, 0x0e04, 0x512f, 0x2071, 0xaf34, 0x7200, 0x82ff, 0x05d8,
- 0x6934, 0xa186, 0x0103, 0x1904, 0x5183, 0x6948, 0x6844, 0xa105,
- 0x1540, 0x2009, 0x8020, 0x2200, 0x0002, 0x5173, 0x514a, 0x519b,
- 0x51a7, 0x5173, 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5173,
- 0x7018, 0xd084, 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a,
- 0x701b, 0x0001, 0x2091, 0x4080, 0x2071, 0xad00, 0x702c, 0x206a,
- 0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x002e, 0x00ee, 0x015e,
- 0x0005, 0x6844, 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118,
- 0x2009, 0x8020, 0x0880, 0x2071, 0xae13, 0x2d08, 0x206b, 0x0000,
- 0x7010, 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902,
- 0x0008, 0x711e, 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130,
- 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc,
- 0x0d10, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009,
- 0x8021, 0x0804, 0x5143, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98,
- 0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084,
- 0x8008, 0xa092, 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003,
- 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a,
- 0x0a04, 0x515c, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x515c, 0x2071,
- 0x0000, 0x7018, 0xd084, 0x1904, 0x515c, 0x2071, 0xaf34, 0x7000,
- 0xa086, 0x0002, 0x1150, 0x080c, 0x5426, 0x2071, 0x0000, 0x701b,
- 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x080c, 0x5450, 0x2071,
- 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x0006,
- 0x684c, 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011,
- 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e,
- 0x000e, 0x684a, 0x6952, 0x0005, 0x2071, 0xae13, 0x7004, 0x0002,
- 0x5202, 0x5213, 0x5411, 0x5412, 0x541f, 0x5425, 0x5203, 0x5402,
- 0x5398, 0x53ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5212,
- 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001,
- 0x700b, 0x0000, 0x012e, 0x2069, 0xafda, 0x683c, 0xa005, 0x03f8,
- 0x11f0, 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001,
- 0xae1f, 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5236, 0x2069, 0x0000,
- 0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001,
- 0x2091, 0x4080, 0x2069, 0xafda, 0x683f, 0xffff, 0x012e, 0x2069,
- 0xad00, 0x6844, 0x6964, 0xa102, 0x2069, 0xaf34, 0x688a, 0x6984,
- 0x701c, 0xa06d, 0x0120, 0x81ff, 0x0904, 0x528c, 0x00a0, 0x81ff,
- 0x0904, 0x5352, 0x2071, 0xaf34, 0x7184, 0x7088, 0xa10a, 0x1258,
- 0x7190, 0x2071, 0xafda, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5352,
- 0x713a, 0x0804, 0x5352, 0x2071, 0xaf34, 0x718c, 0x0126, 0x2091,
- 0x8000, 0x7084, 0xa10a, 0x0a04, 0x536d, 0x0e04, 0x530e, 0x2071,
- 0x0000, 0x7018, 0xd084, 0x1904, 0x530e, 0x2001, 0xffff, 0x2071,
- 0xafda, 0x703a, 0x2071, 0xaf34, 0x7000, 0xa086, 0x0002, 0x1150,
- 0x080c, 0x5426, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
- 0x0804, 0x530e, 0x080c, 0x5450, 0x2071, 0x0000, 0x701b, 0x0001,
- 0x2091, 0x4080, 0x0804, 0x530e, 0x2071, 0xaf34, 0x7000, 0xa005,
- 0x0904, 0x5334, 0x6934, 0xa186, 0x0103, 0x1904, 0x5311, 0x684c,
- 0xd0bc, 0x1904, 0x5334, 0x6948, 0x6844, 0xa105, 0x1904, 0x5329,
- 0x2009, 0x8020, 0x2071, 0xaf34, 0x7000, 0x0002, 0x5334, 0x52f4,
- 0x52cc, 0x52de, 0x52ab, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75,
- 0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e,
- 0x2071, 0xaf7c, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007,
- 0x0002, 0x700b, 0x0000, 0x2e10, 0x080c, 0x1624, 0x2071, 0xae13,
- 0x7007, 0x0009, 0x0804, 0x5352, 0x7084, 0x8008, 0xa092, 0x001e,
- 0x1a04, 0x5352, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186,
- 0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x7084, 0x8008,
- 0xa092, 0x000f, 0x1a04, 0x5352, 0xae90, 0x0003, 0x8003, 0xa210,
- 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xae13,
- 0x080c, 0x54a7, 0x0804, 0x5352, 0x0126, 0x2091, 0x8000, 0x0e04,
- 0x530e, 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c,
- 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e,
- 0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x012e, 0x0804,
- 0x5352, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e,
- 0x0118, 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850,
- 0xa084, 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804,
- 0x52a2, 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120,
- 0x2009, 0x8020, 0x0804, 0x52a2, 0x2071, 0xae13, 0x080c, 0x54b9,
- 0x01c8, 0x2071, 0xae13, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff,
- 0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108,
- 0x710e, 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100,
- 0x0904, 0x5412, 0x0126, 0x2091, 0x8000, 0x2071, 0xae13, 0x7008,
- 0xa086, 0x0001, 0x1180, 0x0e04, 0x536b, 0x2009, 0x000d, 0x7030,
- 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006,
- 0x1110, 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xae13, 0x080c,
- 0x54b9, 0x0518, 0x2071, 0xaf34, 0x7084, 0x700a, 0x20a9, 0x0020,
- 0x2099, 0xaf35, 0x20a1, 0xaf5c, 0x53a3, 0x7087, 0x0000, 0x2071,
- 0xae13, 0x2069, 0xaf7c, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074,
- 0x682e, 0x7078, 0x6832, 0x2d10, 0x080c, 0x1624, 0x7007, 0x0008,
- 0x2001, 0xffff, 0x2071, 0xafda, 0x703a, 0x012e, 0x0804, 0x5352,
- 0x2069, 0xaf7c, 0x6808, 0xa08e, 0x0000, 0x0904, 0x53ed, 0xa08e,
- 0x0200, 0x0904, 0x53eb, 0xa08e, 0x0100, 0x1904, 0x53ed, 0x0126,
- 0x2091, 0x8000, 0x0e04, 0x53e9, 0x2069, 0x0000, 0x6818, 0xd084,
- 0x15c0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
- 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e,
- 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b,
- 0x0000, 0x2001, 0xaf59, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069,
- 0xaf34, 0x689c, 0x699e, 0x2069, 0xafda, 0xa102, 0x1118, 0x683c,
- 0xa005, 0x1368, 0x2001, 0xaf5a, 0x200c, 0x810d, 0x693e, 0x0038,
- 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007,
- 0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xaf7e,
- 0x2004, 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x54a7,
- 0x0005, 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007,
- 0x0005, 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x54b9, 0x0140,
- 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100, 0x0110,
- 0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004,
- 0x0030, 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c,
- 0x5475, 0x7006, 0x080c, 0x54a7, 0x0005, 0x0005, 0x00e6, 0x0156,
- 0x2071, 0xaf34, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80,
- 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04,
- 0x544a, 0x2014, 0x722a, 0x8000, 0x0f04, 0x544a, 0x2014, 0x722e,
- 0x8000, 0x0f04, 0x544a, 0x2014, 0x723a, 0x8000, 0x0f04, 0x544a,
- 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005,
- 0x00e6, 0x0156, 0x2071, 0xaf34, 0x7184, 0x81ff, 0x01d8, 0xa006,
- 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226,
- 0x8000, 0x2014, 0x722a, 0x8000, 0x0f04, 0x546c, 0x2014, 0x723a,
- 0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001,
- 0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108,
- 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048,
- 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000,
- 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091,
- 0x8000, 0x0e04, 0x54a1, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080,
- 0x2001, 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007,
- 0x0005, 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c,
- 0xa06d, 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012,
- 0x2d04, 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x15f0,
- 0x0005, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304,
- 0x230c, 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130,
- 0xa102, 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008,
- 0x8002, 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053,
- 0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc08d,
- 0x200a, 0x012e, 0x080c, 0x163c, 0x0005, 0x7088, 0xa08a, 0x0029,
- 0x1220, 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x14f6, 0x6027,
- 0x1e00, 0x0005, 0x55c1, 0x555b, 0x5571, 0x5595, 0x55b4, 0x55e6,
- 0x55f8, 0x5571, 0x55d2, 0x54ff, 0x552d, 0x54fe, 0x0005, 0x00d6,
- 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518,
- 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x584d,
- 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069,
- 0xafac, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6,
- 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e,
- 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200,
- 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708b, 0x0028,
- 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x58da, 0x6028, 0xa085,
- 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04,
- 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046,
- 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e, 0x004e, 0x003e,
- 0x00ee, 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1180,
- 0x080c, 0x5663, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140,
- 0x708b, 0x0020, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f,
- 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x11c8, 0xd1dc, 0x11a0,
- 0xd1e4, 0x1178, 0xa184, 0x1e00, 0x11b8, 0x60e3, 0x0001, 0x600c,
- 0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x708b, 0x0028,
- 0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b,
- 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c,
- 0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x6124, 0xd1d4,
- 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, 0x1e00, 0x1158,
- 0x708b, 0x0028, 0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d,
- 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1dc,
- 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d,
- 0x0005, 0x080c, 0x568d, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x5663,
- 0xd1d4, 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b,
- 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, 0x1160, 0xd1cc,
- 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028,
- 0x708b, 0x001d, 0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x568d,
- 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b,
- 0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005,
- 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc,
- 0x1128, 0xd1e4, 0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d,
- 0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x0016,
- 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140,
- 0x2071, 0xad00, 0x2091, 0x8000, 0x080c, 0x574f, 0x11e8, 0x2001,
- 0xad0c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, 0x6027, 0x0200,
- 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, 0x00a0, 0x2001,
- 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0428,
- 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x576b, 0x0150, 0x080c,
- 0x5761, 0x1138, 0x2001, 0x0001, 0x080c, 0x261e, 0x080c, 0x5726,
- 0x00a0, 0x080c, 0x568a, 0x0178, 0x2001, 0x0001, 0x080c, 0x261e,
- 0x7088, 0xa086, 0x001e, 0x0120, 0x7088, 0xa086, 0x0022, 0x1118,
- 0x708b, 0x0025, 0x0010, 0x708b, 0x0021, 0x012e, 0x00ee, 0x00de,
- 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011,
- 0x566e, 0x080c, 0x6501, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6,
- 0x0016, 0x080c, 0x7834, 0x2071, 0xad00, 0x080c, 0x560f, 0x001e,
- 0x00fe, 0x00ee, 0x0005, 0x2001, 0xad00, 0x2004, 0xa086, 0x0004,
- 0x0140, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003,
- 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6803, 0x00c0, 0x0156,
- 0x20a9, 0x002d, 0x1d04, 0x5692, 0x2091, 0x6000, 0x1f04, 0x5692,
- 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069,
- 0x0140, 0x2071, 0xad00, 0x2001, 0xaf9e, 0x200c, 0xa186, 0x0000,
- 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186,
- 0x0003, 0x0158, 0x0804, 0x5714, 0x708b, 0x0022, 0x0040, 0x708b,
- 0x0021, 0x0028, 0x708b, 0x0023, 0x0020, 0x708b, 0x0024, 0x6043,
- 0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c,
- 0x26cb, 0x0026, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002,
- 0x080c, 0x7ae9, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b,
- 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000,
- 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0118, 0x012e, 0x015e, 0x04d0,
- 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130,
- 0x6803, 0x0100, 0x1f04, 0x56e2, 0x080c, 0x57a0, 0x012e, 0x015e,
- 0x080c, 0x5761, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006,
- 0xa085, 0x0020, 0x6052, 0x080c, 0x57a0, 0xa006, 0x8001, 0x1df0,
- 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x57a0,
- 0x2001, 0xaf9e, 0x2003, 0x0004, 0x080c, 0x54e5, 0x080c, 0x5761,
- 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0xaf9e,
- 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6,
- 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x2001,
- 0xaf9d, 0x2003, 0x0000, 0x2001, 0xaf8e, 0x2003, 0x0000, 0x708b,
- 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c,
- 0x26cb, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027,
- 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006,
- 0x2001, 0xaf9d, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006,
- 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e,
- 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086,
- 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084,
- 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71,
- 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001,
- 0xad0c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x26eb, 0x0036, 0x0016,
- 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2aac, 0x001e, 0x003e,
- 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xad0c, 0x2e04, 0x0118,
- 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005,
- 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006,
- 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000,
- 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006,
- 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, 0x0000,
- 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x26cb, 0x6800, 0xa084,
- 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, 0x6050,
- 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6,
- 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x6020, 0xa084,
- 0x0080, 0x0138, 0x2001, 0xad0c, 0x200c, 0xc1bd, 0x2102, 0x0804,
- 0x5845, 0x2001, 0xad0c, 0x200c, 0xc1bc, 0x2102, 0x6028, 0xa084,
- 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, 0x0384,
- 0x6024, 0xd0cc, 0x1518, 0x1d04, 0x57f8, 0x2091, 0x6000, 0x1f04,
- 0x57f8, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
- 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
- 0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001,
- 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x0438, 0x60e3, 0x0000,
- 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x6803, 0x0080,
- 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024,
- 0xa10c, 0x0138, 0x1d04, 0x582a, 0x2091, 0x6000, 0x1f04, 0x582a,
- 0x0840, 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a0, 0xa005, 0x1118,
- 0x6887, 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce,
- 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026,
- 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00,
- 0x2069, 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005,
- 0x1904, 0x58a1, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000,
- 0x2001, 0x0000, 0x080c, 0x26cb, 0x2069, 0x0200, 0x6804, 0xa005,
- 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a,
- 0x6027, 0x0400, 0x2069, 0xafac, 0x7000, 0x206a, 0x708b, 0x0026,
- 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5884, 0x2091, 0x6000,
- 0x1f04, 0x5884, 0x0804, 0x58d2, 0x2069, 0x0140, 0x20a9, 0x0384,
- 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0530,
- 0xa084, 0x1a00, 0x1518, 0x1d04, 0x5890, 0x2091, 0x6000, 0x1f04,
- 0x5890, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
- 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
- 0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001,
- 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x00a0, 0x6803, 0x0080,
- 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a0, 0xa005, 0x1118, 0x6887,
- 0x0001, 0x0008, 0x6886, 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb,
- 0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
- 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6,
- 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x6020, 0xa084, 0x00c0,
- 0x01f0, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
- 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
- 0x7a64, 0x2069, 0x0140, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003,
- 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0804, 0x5972, 0x2001,
- 0xad0c, 0x200c, 0xd1b4, 0x1150, 0xc1b5, 0x2102, 0x080c, 0x5663,
- 0x2069, 0x0140, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200,
- 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01b8, 0x6028, 0xa084,
- 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0xafac, 0x7000, 0x206a,
- 0x708b, 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x592e,
- 0x2091, 0x6000, 0x1f04, 0x592e, 0x04e8, 0x6027, 0x1e00, 0x2009,
- 0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0,
- 0x1d04, 0x5935, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c,
- 0x64a2, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071,
- 0xafda, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x01e0, 0x0026, 0x2011,
- 0x566e, 0x080c, 0x650d, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000,
- 0x70a0, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001,
- 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x2001, 0xad0c, 0x200c,
- 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
- 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6,
- 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x7130, 0xd184, 0x1180,
- 0x2011, 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011,
- 0xad52, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x59df,
- 0x7130, 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x0530,
- 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019,
- 0x000e, 0x080c, 0xa8eb, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000,
- 0xa186, 0x007e, 0x0170, 0xa186, 0x0080, 0x0158, 0x080c, 0x4cdc,
- 0x1140, 0x8127, 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xa96c,
- 0x001e, 0x8108, 0x1f04, 0x59b0, 0x015e, 0x001e, 0xd1ac, 0x1148,
- 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2aac, 0x001e,
- 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4cdc,
- 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04, 0x59d6, 0x015e, 0x2011,
- 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c,
- 0x79e1, 0x080c, 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64,
- 0x003e, 0x60e3, 0x0000, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c,
- 0x569a, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e,
- 0x0005, 0x2071, 0xade1, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f,
- 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f,
- 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, 0x708f,
- 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, 0xade1, 0x6848,
- 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0428,
- 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c,
- 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c,
- 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0,
- 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a,
- 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78,
- 0x2071, 0xade1, 0x7004, 0x0043, 0x700c, 0x0002, 0x5a5b, 0x5a52,
- 0x5a52, 0x5a52, 0x5a52, 0x0005, 0x5ab1, 0x5ab2, 0x5ae4, 0x5ae5,
- 0x5aaf, 0x5b33, 0x5b38, 0x5b69, 0x5b6a, 0x5b85, 0x5b86, 0x5b87,
- 0x5b88, 0x5b89, 0x5b8a, 0x5c40, 0x5c67, 0x700c, 0x0002, 0x5a74,
- 0x5aaf, 0x5aaf, 0x5ab0, 0x5ab0, 0x7830, 0x7930, 0xa106, 0x0120,
- 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210,
- 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x15c0, 0x01b0,
- 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000,
- 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc085,
- 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x163c, 0x0005, 0x080c,
- 0x15c0, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15c0, 0x1108, 0x0c10,
- 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8, 0x0005,
- 0x0005, 0x0005, 0x700c, 0x0002, 0x5ab9, 0x5abc, 0x5aca, 0x5ae3,
- 0x5ae3, 0x080c, 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058,
- 0x0006, 0x080c, 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d,
- 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058,
- 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834,
- 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, 0x012e, 0x0005,
- 0x012e, 0x080c, 0x5b8b, 0x0005, 0x0005, 0x0005, 0x00e6, 0x2071,
- 0xade1, 0x700c, 0x0002, 0x5af0, 0x5af0, 0x5af0, 0x5af2, 0x5af5,
- 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002, 0x00ee,
- 0x0005, 0x5b8b, 0x5b8b, 0x5ba7, 0x5b8b, 0x5d22, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x5d64, 0x5da7, 0x5df0, 0x5e04,
- 0x5b8b, 0x5b8b, 0x5bc3, 0x5ba7, 0x5b8b, 0x5b8b, 0x5c1d, 0x5ead,
- 0x5ec8, 0x5b8b, 0x5bc3, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5c13,
- 0x5ec8, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5bd7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5bec, 0x7020, 0x2068, 0x080c, 0x15f0, 0x0005,
- 0x700c, 0x0002, 0x5b3f, 0x5b42, 0x5b50, 0x5b68, 0x5b68, 0x080c,
- 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c,
- 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d, 0x00de, 0x0048,
- 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058, 0x2068, 0x7084,
- 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
- 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419,
- 0x0005, 0x0005, 0x0005, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5ba7,
- 0x5b8b, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5ba7, 0x5ba7,
- 0x5ba7, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5b8b,
- 0x5ba7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x0005, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff,
- 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e,
- 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007,
- 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838,
- 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c,
- 0x510c, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988,
- 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x5cd0, 0x7007, 0x0006,
- 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5cd0, 0x0005, 0x6834,
- 0x8007, 0xa084, 0x00ff, 0x0904, 0x5b99, 0x8001, 0x1120, 0x7007,
- 0x0001, 0x0804, 0x5ced, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016,
- 0x701a, 0x704b, 0x5ced, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff,
- 0xa086, 0x0001, 0x1904, 0x5b99, 0x7007, 0x0001, 0x2009, 0xad30,
- 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853,
- 0x0000, 0x080c, 0x4ab1, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x510c, 0x012e, 0x0ca0,
- 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, 0x00c0,
- 0x1120, 0x7007, 0x0001, 0x0804, 0x5ee0, 0x2d00, 0x7016, 0x701a,
- 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xae0c, 0x53a3,
- 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5bb5, 0x6a84, 0xa28a,
- 0x0002, 0x1a04, 0x5bb5, 0x82ff, 0x1138, 0x6888, 0x698c, 0xa105,
- 0x0118, 0x2001, 0x5ca3, 0x0018, 0xa280, 0x5c99, 0x2005, 0x70c6,
- 0x7010, 0xa015, 0x0904, 0x5c85, 0x080c, 0x15c0, 0x1118, 0x7007,
- 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836,
- 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200,
- 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, 0xa108,
- 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x1624, 0x7090,
- 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, 0x0010,
- 0x0005, 0x7020, 0x2068, 0x080c, 0x15f0, 0x7014, 0x2068, 0x0804,
- 0x5bb5, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08,
- 0x2068, 0x6906, 0x711a, 0x0804, 0x5c40, 0x7014, 0x2068, 0x7007,
- 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, 0x0108,
- 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, 0x5ee0,
- 0x04b8, 0x5c9b, 0x5c9f, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a,
- 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x00f6,
- 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, 0x2060,
- 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816,
- 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a,
- 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, 0x6004,
- 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
- 0x2009, 0xad30, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, 0x00ff,
- 0x683a, 0x080c, 0x4993, 0x1108, 0x0005, 0x080c, 0x51df, 0x0126,
- 0x2091, 0x8000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x012e, 0x0ca0,
- 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xad30, 0x210c,
- 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01b0, 0x6838, 0xa084, 0x00ff,
- 0x683a, 0x6853, 0x0000, 0x080c, 0x4a55, 0x1108, 0x0005, 0x0126,
- 0x2091, 0x8000, 0x080c, 0x51df, 0x080c, 0x510c, 0x012e, 0x0cb0,
- 0x2001, 0x0028, 0x0ca0, 0x2001, 0x0000, 0x0c88, 0x7018, 0x6802,
- 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118,
- 0x7007, 0x0006, 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048,
- 0x080f, 0x0005, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff,
- 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0,
- 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005,
- 0x11f0, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x11b8,
- 0x0066, 0x6e50, 0x080c, 0x4dcf, 0x006e, 0x0088, 0x0046, 0x2011,
- 0xad0c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4cdc,
- 0x1110, 0x080c, 0x4f2d, 0x8108, 0x1f04, 0x5d4e, 0x00ce, 0x684c,
- 0xd084, 0x1118, 0x080c, 0x15f0, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x510c, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007,
- 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0580, 0x2061, 0xb048,
- 0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000,
- 0xd084, 0x0520, 0x6004, 0xa005, 0x1538, 0x6003, 0x0000, 0x600b,
- 0x0000, 0x00c8, 0x2011, 0x0001, 0x6860, 0xa005, 0x1110, 0x2001,
- 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006,
- 0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000,
- 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x5f7f, 0x012e, 0x0804,
- 0x5f79, 0x012e, 0x0804, 0x5f73, 0x012e, 0x0804, 0x5f76, 0x0126,
- 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4,
- 0x05e0, 0x2061, 0xb048, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308,
- 0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c,
- 0x00ff, 0x8001, 0x1120, 0x2100, 0xa210, 0x0620, 0x0028, 0x8001,
- 0x1508, 0x2100, 0xa212, 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958,
- 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120, 0x2100, 0xa318,
- 0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250,
- 0x6860, 0xa005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e,
- 0x0804, 0x5f7f, 0x012e, 0x0804, 0x5f7c, 0x012e, 0x0804, 0x5f79,
- 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xb048, 0x6300,
- 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804,
- 0x5f8d, 0x012e, 0x0804, 0x5f7c, 0x0126, 0x00c6, 0x2091, 0x8000,
- 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb048,
- 0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005,
- 0x05d0, 0x685c, 0xa065, 0x0598, 0x2001, 0xad30, 0x2004, 0xa005,
- 0x0118, 0x080c, 0x974e, 0x0068, 0x6013, 0x0400, 0x6057, 0x0000,
- 0x694c, 0xd1a4, 0x0110, 0x6950, 0x6156, 0x2009, 0x0041, 0x080c,
- 0x80a7, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x1140, 0x0026,
- 0x2009, 0x0000, 0x2011, 0xfdff, 0x080c, 0x663f, 0x002e, 0x684c,
- 0xd0c4, 0x0148, 0x2061, 0xb048, 0x6000, 0xd08c, 0x1120, 0x6008,
- 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5f7f, 0x00ce,
- 0x012e, 0x0804, 0x5f79, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186,
- 0x002d, 0x0d28, 0xa186, 0x0045, 0x0510, 0xa186, 0x002a, 0x1130,
- 0x2001, 0xad0c, 0x200c, 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020,
- 0x0170, 0xa186, 0x0029, 0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f,
- 0x080c, 0x4cdc, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c,
- 0xa065, 0x09a8, 0x2001, 0xafa3, 0x2004, 0x6016, 0x0800, 0x685c,
- 0xa065, 0x0968, 0x00e6, 0x6860, 0xa075, 0x2001, 0xad30, 0x2004,
- 0xa005, 0x0150, 0x080c, 0x974e, 0x8eff, 0x0118, 0x2e60, 0x080c,
- 0x974e, 0x00ee, 0x0804, 0x5e3f, 0x6020, 0xc0dc, 0xc0d5, 0x6022,
- 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b,
- 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x00ee, 0x0804, 0x5e3f, 0x2061, 0xb048, 0x6000,
- 0xd084, 0x0190, 0xd08c, 0x1904, 0x5f8d, 0x0126, 0x2091, 0x8000,
- 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x5f8d, 0x012e,
- 0x6853, 0x0016, 0x0804, 0x5f86, 0x6853, 0x0007, 0x0804, 0x5f86,
- 0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5b99, 0x0078,
- 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007,
- 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5ee0, 0x0005,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x2009, 0xad30, 0x210c, 0x81ff,
- 0x1904, 0x5f5b, 0x2009, 0xad0c, 0x210c, 0xd194, 0x1904, 0x5f63,
- 0x6848, 0x2070, 0xae82, 0xb400, 0x0a04, 0x5f4f, 0x2001, 0xad16,
- 0x2004, 0xae02, 0x1a04, 0x5f4f, 0x2061, 0xb048, 0x6100, 0xa184,
- 0x0301, 0xa086, 0x0001, 0x15a8, 0x711c, 0xa186, 0x0006, 0x15b0,
- 0x7018, 0xa005, 0x0904, 0x5f5b, 0x2004, 0xd0e4, 0x1904, 0x5f5e,
- 0x7020, 0xd0dc, 0x1904, 0x5f66, 0x6853, 0x0000, 0x6803, 0x0000,
- 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, 0x1904,
- 0x5f69, 0x2e60, 0x080c, 0x65aa, 0x012e, 0x00ee, 0x0005, 0x2068,
- 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x15c8,
- 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, 0x0006, 0x0804,
- 0x5f86, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6944, 0xa18c,
- 0xff00, 0x810f, 0x080c, 0x4cdc, 0x11c8, 0x6000, 0xd0e4, 0x11b0,
- 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853,
- 0x0008, 0x0070, 0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040,
- 0x6853, 0x0035, 0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029,
- 0x012e, 0x00ee, 0x0418, 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045,
- 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x080c, 0xa566,
- 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004,
- 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009,
- 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x080c, 0x15f0, 0x0005,
- 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072,
- 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072, 0x1230,
- 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132,
- 0x0005, 0x00d6, 0x080c, 0x65a1, 0x00de, 0x0005, 0x00d6, 0x2011,
- 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1,
- 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118,
- 0xa086, 0x1000, 0x1540, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00,
- 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1118, 0x080c, 0x61c6,
- 0x00b0, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84,
- 0x0007, 0x1188, 0xac82, 0xb400, 0x0270, 0x6858, 0xac02, 0x1258,
- 0x6120, 0xd1f4, 0x1160, 0x2009, 0x0047, 0x080c, 0x80a7, 0x7a1c,
- 0xd284, 0x1968, 0x0005, 0xa016, 0x080c, 0x1824, 0x0cc0, 0x0cd8,
- 0x781c, 0xd08c, 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000,
- 0x3d20, 0x3e28, 0xa584, 0x0076, 0x1530, 0xa484, 0x7000, 0xa086,
- 0x1000, 0x11a8, 0x080c, 0x604e, 0x01f0, 0x20e1, 0x3000, 0x7828,
- 0x7828, 0x080c, 0x606a, 0x014e, 0x013e, 0x015e, 0x2009, 0xafcf,
- 0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6c50, 0x0ce0, 0xa484,
- 0x7000, 0x1518, 0x0499, 0x01b8, 0x7000, 0xa084, 0xff00, 0xa086,
- 0x8100, 0x0d18, 0x0080, 0xd5a4, 0x0158, 0x080c, 0x1d86, 0x20e1,
- 0x9010, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0048,
- 0x00e9, 0x6883, 0x0000, 0x080c, 0xac59, 0x20e1, 0x3000, 0x7828,
- 0x7828, 0x014e, 0x013e, 0x015e, 0x08b0, 0x0081, 0x1130, 0x7000,
- 0xa084, 0xff00, 0xa086, 0x8100, 0x1d70, 0x080c, 0xac59, 0x20e1,
- 0x3000, 0x7828, 0x7828, 0x080c, 0x642d, 0x0c58, 0xa484, 0x01ff,
- 0x6882, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac,
- 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9,
- 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085,
- 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007,
- 0xa196, 0x0000, 0x1118, 0x0804, 0x62cf, 0x0005, 0xa196, 0x2000,
- 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x41d1, 0x0ca8,
- 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x6372, 0x0c68,
- 0x00c6, 0x6a80, 0x82ff, 0x0904, 0x61c0, 0x7110, 0xa18c, 0xff00,
- 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, 0x61c0,
- 0xa08e, 0x0023, 0x1570, 0x080c, 0x6408, 0x0904, 0x61c0, 0x7124,
- 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, 0x1904,
- 0x61c0, 0x2009, 0x0015, 0x080c, 0x80a7, 0x0804, 0x61c0, 0xa08e,
- 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c,
- 0x80a7, 0x0804, 0x61c0, 0xa08e, 0x0100, 0x1904, 0x61c0, 0x7034,
- 0xa005, 0x1904, 0x61c0, 0x2009, 0x0016, 0x080c, 0x80a7, 0x0804,
- 0x61c0, 0xa08e, 0x0022, 0x1904, 0x61c0, 0x7030, 0xa08e, 0x0300,
- 0x1580, 0x68d0, 0xd0a4, 0x0528, 0xc0b5, 0x68d2, 0x7100, 0xa18c,
- 0x00ff, 0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6,
- 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26a0,
- 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2676, 0x694e,
- 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xad00, 0x70a2,
- 0x00ee, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0017, 0x0804,
- 0x6193, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, 0x61c0,
- 0x68d0, 0xc0a5, 0x68d2, 0x2009, 0x0030, 0x0804, 0x6193, 0xa08e,
- 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0018,
- 0x0804, 0x6193, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804,
- 0x6193, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x6193,
- 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009,
- 0x001b, 0x0804, 0x6193, 0xa08e, 0x5000, 0x1140, 0x7034, 0xa005,
- 0x1904, 0x61c0, 0x2009, 0x001c, 0x0804, 0x6193, 0xa08e, 0x1300,
- 0x1120, 0x2009, 0x0034, 0x0804, 0x6193, 0xa08e, 0x1200, 0x1140,
- 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0024, 0x0804, 0x6193,
- 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, 0x04d8,
- 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, 0x0498,
- 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, 0x5300,
- 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xb28d, 0x8208,
- 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015,
- 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3c5c, 0x004e, 0x8108,
- 0x1f04, 0x6176, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, 0x1118,
- 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045,
- 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xb283, 0x2204, 0x8211,
- 0x220c, 0x080c, 0x2676, 0x1530, 0x080c, 0x4c80, 0x1518, 0x6612,
- 0x6516, 0x86ff, 0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158,
- 0x686c, 0xa606, 0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118,
- 0x6000, 0xc0f5, 0x6002, 0x00c6, 0x080c, 0x8022, 0x0168, 0x001e,
- 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x80a7,
- 0x00ce, 0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046,
- 0x080c, 0x6221, 0x1904, 0x621e, 0xa184, 0xff00, 0x8007, 0xa086,
- 0x0008, 0x1904, 0x621e, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6408,
- 0x0904, 0x621e, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140,
- 0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x80a7, 0x04b0,
- 0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016,
- 0x080c, 0x80a7, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e,
- 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xb283, 0x2204,
- 0x8211, 0x220c, 0x080c, 0x2676, 0x11c0, 0x080c, 0x4c80, 0x11a8,
- 0x6612, 0x6516, 0x00c6, 0x080c, 0x8022, 0x0170, 0x001e, 0x611a,
- 0x080c, 0x9956, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c,
- 0x80a7, 0x080c, 0x6c50, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce,
- 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156,
- 0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1df2,
- 0x1590, 0x080c, 0x1ce2, 0x05c8, 0x04d9, 0x1130, 0x7908, 0xa18c,
- 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000,
- 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a,
- 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0401,
- 0x1120, 0xa08a, 0x0140, 0x1a0c, 0x14f6, 0x80ac, 0x20e1, 0x6000,
- 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803,
- 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e,
- 0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa085, 0x0001, 0x0c98,
- 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005,
- 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198,
- 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x62ca, 0xa596,
- 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118,
- 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xad34, 0x231c,
- 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34,
- 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0xaeb5, 0x2e1c,
- 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368,
- 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346,
- 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420,
- 0x8e70, 0x1f04, 0x62a7, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018,
- 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084,
- 0x0007, 0x000a, 0x0005, 0x62db, 0x62db, 0x62db, 0x641a, 0x62db,
- 0x62dc, 0x62f1, 0x635d, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120,
- 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xb400, 0x0248, 0x6858,
- 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x80a7,
- 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x6344, 0x2011, 0xb283,
- 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1904, 0x6344, 0x080c,
- 0x4c80, 0x1904, 0x6344, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15e0,
- 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c,
- 0x574f, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0,
- 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0530,
- 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009,
- 0x0044, 0x080c, 0x80a7, 0x00c0, 0x00c6, 0x080c, 0x8022, 0x001e,
- 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
- 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00ce, 0x0005, 0x00c6, 0x080c,
- 0x9807, 0x001e, 0x0dc8, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a,
- 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c38, 0x7110, 0xd1bc, 0x0188,
- 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xb400, 0x0248,
- 0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c,
- 0x80a7, 0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000,
- 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005,
- 0x6386, 0x6387, 0x6386, 0x6386, 0x63f0, 0x63fc, 0x0005, 0x7110,
- 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x63ef, 0x700c, 0x7108,
- 0x080c, 0x2676, 0x1904, 0x63ef, 0x080c, 0x4c80, 0x1904, 0x63ef,
- 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff,
- 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c,
- 0x6408, 0x00ce, 0x0904, 0x63ef, 0x00c6, 0x080c, 0x8022, 0x001e,
- 0x05f0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0002, 0x7120, 0x610a,
- 0x2009, 0x0088, 0x080c, 0x80a7, 0x0490, 0xa28c, 0x00ff, 0xa186,
- 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217,
- 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c,
- 0x8022, 0x001e, 0x01e0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0005,
- 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x80a7, 0x0080, 0x00c6,
- 0x080c, 0x8022, 0x001e, 0x0158, 0x611a, 0x080c, 0x9956, 0x601f,
- 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x80a7, 0x0005,
- 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009,
- 0x0089, 0x080c, 0x80a7, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041,
- 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x80a7, 0x0005,
- 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xb400, 0x0240,
- 0x2001, 0xad16, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005,
- 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84,
- 0x0007, 0x1150, 0xac82, 0xb400, 0x0238, 0x6858, 0xac02, 0x1220,
- 0x2009, 0x0051, 0x080c, 0x80a7, 0x0005, 0x2031, 0x0105, 0x0069,
- 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029,
- 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6,
- 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x8022,
- 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xb283, 0x2204, 0x8211,
- 0x220c, 0x080c, 0x2676, 0x1580, 0x080c, 0x4c80, 0x1568, 0x6612,
- 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0x9956, 0x080c,
- 0x15d9, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000,
- 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3,
- 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00fe, 0x00de, 0x00ce, 0x0005,
- 0x080c, 0x8078, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x2071,
- 0xafda, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
- 0x7017, 0xb400, 0x7007, 0x0000, 0x7026, 0x702b, 0x7841, 0x7032,
- 0x7037, 0x789d, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047,
- 0x41b3, 0x0005, 0x2071, 0xafda, 0x1d04, 0x64fc, 0x2091, 0x6000,
- 0x700c, 0x8001, 0x700e, 0x1180, 0x700f, 0x0361, 0x7007, 0x0001,
- 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0148, 0x8109, 0x7142,
- 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024,
- 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009,
- 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff,
- 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, 0x0158, 0x702c, 0x8001,
- 0x702e, 0x1138, 0x702f, 0x0009, 0x8109, 0x7132, 0x1110, 0x7034,
- 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c,
- 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x7018, 0xa00d, 0x0158,
- 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a,
- 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6522, 0x6523,
- 0x653b, 0x00e6, 0x2071, 0xafda, 0x7018, 0xa005, 0x1120, 0x711a,
- 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071,
- 0xafda, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee,
- 0x0005, 0x00e6, 0x2071, 0xafda, 0x6088, 0xa102, 0x0208, 0x618a,
- 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x4cdc, 0x1158, 0x6088,
- 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c,
- 0x6c50, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007,
- 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000,
- 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0x9846,
- 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186,
- 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854,
- 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a,
- 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
- 0x0010, 0x080c, 0x9350, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001,
- 0xe400, 0xa102, 0x0220, 0x7017, 0xb400, 0x7007, 0x0000, 0x0005,
- 0x00e6, 0x2071, 0xafda, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee,
- 0x0005, 0x2001, 0xafe3, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071,
- 0xafda, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xafe6,
- 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xafda, 0x711a, 0x721e,
- 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb048, 0x00ce,
- 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb048,
- 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
- 0xa005, 0x1150, 0x00c6, 0x2061, 0xb048, 0x6014, 0x00ce, 0xa005,
- 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006,
- 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0,
- 0xa18e, 0x00c0, 0x05b0, 0xd0b4, 0x1138, 0xd0bc, 0x1528, 0x2009,
- 0x0006, 0x080c, 0x661a, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003,
- 0x0118, 0xa086, 0x0003, 0x15c0, 0x6020, 0xd0d4, 0x0130, 0xc0d4,
- 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xad73, 0x2104,
- 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x80a7, 0x0005, 0x2009,
- 0x0043, 0x080c, 0x80a7, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003,
- 0x0118, 0xa086, 0x0003, 0x11c0, 0x2009, 0x0042, 0x080c, 0x80a7,
- 0x0005, 0xd0fc, 0x0150, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0138,
- 0x2009, 0x0041, 0x080c, 0x80a7, 0x0005, 0x0051, 0x0ce8, 0x2009,
- 0x0043, 0x080c, 0x80a7, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005,
- 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068,
- 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c,
- 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb048, 0x6200,
- 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c,
- 0x510c, 0x6010, 0xa06d, 0x190c, 0x65aa, 0x00de, 0x0005, 0x0156,
- 0x00c6, 0x2061, 0xb048, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008,
- 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138,
- 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005,
- 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200,
- 0x1f04, 0x665c, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010,
- 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a,
- 0x1220, 0x1f04, 0x666c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04,
- 0x666c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e,
- 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091,
- 0x2800, 0x2079, 0xafc7, 0x012e, 0x00d6, 0x2069, 0xafc7, 0x6803,
- 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de,
- 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002,
- 0x66aa, 0x66cb, 0x671e, 0x66b0, 0x66cb, 0x66aa, 0x66a8, 0x66a8,
- 0x080c, 0x14f6, 0x080c, 0x6581, 0x080c, 0x6c50, 0x00ce, 0x0005,
- 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x481b, 0x080c,
- 0x650d, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c,
- 0x4855, 0x0c88, 0x080c, 0x481b, 0x7807, 0x0003, 0x7827, 0x0000,
- 0x782b, 0x0000, 0x0c40, 0x080c, 0x6581, 0x3c00, 0x0006, 0x2011,
- 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178,
- 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c,
- 0x14f6, 0x2009, 0x0013, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x3900,
- 0xa082, 0xb0e8, 0x1210, 0x080c, 0x7d8d, 0x00c6, 0x7824, 0xa065,
- 0x090c, 0x14f6, 0x7804, 0xa086, 0x0004, 0x0904, 0x675e, 0x7828,
- 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x7827,
- 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xad00,
- 0x70dc, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100,
- 0x2071, 0xad00, 0x080c, 0x485e, 0x00ee, 0x00ce, 0x080c, 0xaca2,
- 0x2009, 0x0014, 0x080c, 0x80a7, 0x00ce, 0x0838, 0x2001, 0xafe3,
- 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824,
- 0xa065, 0x090c, 0x14f6, 0x2009, 0x0013, 0x080c, 0x80fb, 0x00ce,
- 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xb0e8, 0x1210, 0x080c,
- 0x7d8d, 0x7824, 0xa005, 0x090c, 0x14f6, 0x781c, 0xa06d, 0x090c,
- 0x14f6, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x8078,
- 0x693c, 0x81ff, 0x090c, 0x14f6, 0x8109, 0x693e, 0x6854, 0xa015,
- 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827,
- 0x0000, 0x00de, 0x00ce, 0x080c, 0x6c50, 0x0888, 0x6104, 0xa186,
- 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, 0x66f7, 0x7808,
- 0xac06, 0x0904, 0x66f7, 0x080c, 0x6b73, 0x080c, 0x67ee, 0x00ce,
- 0x080c, 0x6c50, 0x0804, 0x66e5, 0x00c6, 0x6027, 0x0002, 0x62c8,
- 0x60c4, 0xa205, 0x1178, 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009,
- 0x0049, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x2011, 0xafe6, 0x2013,
- 0x0000, 0x0cc8, 0x3908, 0xa192, 0xb0e8, 0x1210, 0x080c, 0x7d8d,
- 0x793c, 0x81ff, 0x0d90, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e,
- 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016,
- 0x0c10, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, 0x08d8,
- 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000,
- 0x2c08, 0x2061, 0xafc7, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
- 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e,
- 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xafc7,
- 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
- 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x6c56,
- 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000,
- 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xafc7, 0x0c18,
- 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016,
- 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
- 0xafc7, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080,
- 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005,
- 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061,
- 0xafc7, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136,
- 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6,
- 0x00c6, 0x0076, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071,
- 0xafc7, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904,
- 0x6889, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6884,
- 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6884, 0x703c, 0xac06,
- 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x7033, 0x0000,
- 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x003e, 0x7038,
- 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00,
- 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c,
- 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f,
- 0x0000, 0x080c, 0x9596, 0x0198, 0x6010, 0x2068, 0x601c, 0xa086,
- 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
- 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c, 0x9742, 0x080c,
- 0x974e, 0x00ce, 0x0804, 0x682e, 0x2c78, 0x600c, 0x2060, 0x0804,
- 0x682e, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e, 0x007e, 0x00ce,
- 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19d0,
- 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x0006, 0x0066, 0x00c6,
- 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079,
- 0xafc7, 0x7838, 0xa065, 0x0558, 0x600c, 0x0006, 0x600f, 0x0000,
- 0x783c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64,
- 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000,
- 0x003e, 0x080c, 0x9596, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086,
- 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
- 0x510c, 0x080c, 0x9742, 0x080c, 0x974e, 0x000e, 0x0898, 0x7e3a,
- 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005,
- 0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c60, 0x0016,
- 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x69a9, 0x008e,
- 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xafc7, 0x2091,
- 0x8000, 0x080c, 0x6a36, 0x080c, 0x6aa8, 0x012e, 0x00fe, 0x0005,
- 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126,
- 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x8cff,
- 0x0904, 0x6985, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904,
- 0x6980, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6980, 0x7024,
- 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c,
- 0x6581, 0x080c, 0x7834, 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7027,
- 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
- 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
- 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a,
- 0x04b8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36,
- 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013,
- 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
- 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9596, 0x0188,
- 0x601c, 0xa086, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847,
- 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c,
- 0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804, 0x690f,
- 0x2c78, 0x600c, 0x2060, 0x0804, 0x690f, 0x012e, 0x000e, 0x001e,
- 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086,
- 0x0006, 0x1128, 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x601c,
- 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0968, 0x08c8,
- 0x601c, 0xa086, 0x0005, 0x19a8, 0x6004, 0xa086, 0x0085, 0x0d50,
- 0x0880, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xae34,
- 0x2004, 0xa065, 0x0904, 0x6a32, 0x00f6, 0x00e6, 0x00d6, 0x0066,
- 0x2071, 0xafc7, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c,
- 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e,
- 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00,
- 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc,
- 0x6002, 0x080c, 0x4c07, 0x0904, 0x6a2e, 0x7624, 0x86ff, 0x05e8,
- 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834, 0x68c3,
- 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
- 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
- 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
- 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660,
- 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003,
- 0x0009, 0x630a, 0x00ce, 0x0804, 0x69d9, 0x8dff, 0x0158, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa,
- 0x080c, 0x510c, 0x080c, 0x7b88, 0x0804, 0x69d9, 0x006e, 0x00de,
- 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066,
- 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x6a88,
- 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069,
- 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6581, 0x080c, 0x7834,
- 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
- 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
- 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8,
- 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c,
- 0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x000e, 0x0804, 0x6a3d,
- 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c,
- 0xa086, 0x0006, 0x1118, 0x080c, 0xa91f, 0x0c58, 0x601c, 0xa086,
- 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c,
- 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8,
- 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6b0e,
- 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4,
- 0xc0dc, 0x6002, 0x080c, 0x4c07, 0x0904, 0x6b0b, 0x7e24, 0x86ff,
- 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069,
- 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834,
- 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
- 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
- 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e,
- 0x2660, 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660,
- 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6aba, 0x8dff, 0x0138,
- 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c,
- 0x7b88, 0x0804, 0x6aba, 0x000e, 0x0804, 0x6aad, 0x781e, 0x781a,
- 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066,
- 0x6000, 0xd0dc, 0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606,
- 0x1158, 0x2071, 0xafc7, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004,
- 0x2004, 0xad06, 0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005,
- 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660,
- 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7834, 0x78c3,
- 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140,
- 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000,
- 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c,
- 0x7ca8, 0x003e, 0x080c, 0x4c07, 0x00c6, 0x603c, 0xa005, 0x0110,
- 0x8001, 0x603e, 0x2660, 0x080c, 0x8078, 0x00ce, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x080c,
- 0x7b88, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xafc7, 0x7004,
- 0xa084, 0x0007, 0x0002, 0x6b85, 0x6b88, 0x6b9e, 0x6bb7, 0x6bf0,
- 0x6b85, 0x6b83, 0x6b83, 0x080c, 0x14f6, 0x00ce, 0x00ee, 0x0005,
- 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
- 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000,
- 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060,
- 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022,
- 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027,
- 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024,
- 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c,
- 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a,
- 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c, 0xa015,
- 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098,
- 0x6018, 0x2060, 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x080c,
- 0x7b88, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e,
- 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005,
- 0x7024, 0xa065, 0x0140, 0x080c, 0x7b88, 0x600c, 0xa015, 0x0150,
- 0x720e, 0x600f, 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x00ce,
- 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0xafc7,
- 0x6830, 0xa084, 0x0003, 0x0002, 0x6c12, 0x6c14, 0x6c38, 0x6c10,
- 0x080c, 0x14f6, 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001,
- 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, 0x0170, 0x6a3a,
- 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0xafe6,
- 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90,
- 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, 0x0003, 0x0c50,
- 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0168,
- 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
- 0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005,
- 0x00d6, 0x2069, 0xafc7, 0x6804, 0xa084, 0x0007, 0x0002, 0x6c61,
- 0x6cfd, 0x6cfd, 0x6cfd, 0x6cfd, 0x6cff, 0x6c5f, 0x6c5f, 0x080c,
- 0x14f6, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c,
- 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c,
- 0x6d49, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, 0x6807,
- 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x6d49, 0x00ce, 0x00de,
- 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x6cf9,
- 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075,
- 0x0120, 0xa20e, 0x0904, 0x6cf9, 0x0028, 0x6818, 0xa20e, 0x0904,
- 0x6cf9, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70,
- 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, 0x804f,
- 0x0904, 0x6cf9, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180,
- 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003,
- 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001,
- 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6,
- 0x2c78, 0x71a0, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd1bc,
- 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040,
- 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c, 0x00ff,
- 0x2061, 0x0100, 0x619a, 0x080c, 0x736f, 0x7300, 0xc3dd, 0x7302,
- 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003,
- 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de,
- 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6,
- 0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
- 0x080c, 0x6d49, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069,
- 0xafc7, 0x6830, 0xa086, 0x0000, 0x11c0, 0x2001, 0xad0c, 0x200c,
- 0xd1bc, 0x1550, 0x6838, 0xa07d, 0x0180, 0x6833, 0x0001, 0x683e,
- 0x6847, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c,
- 0x1ee6, 0x1130, 0x012e, 0x080c, 0x76a5, 0x00de, 0x00fe, 0x0005,
- 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015,
- 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000,
- 0x0c60, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x080c, 0x57d1,
- 0x0888, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x6d57, 0x6d5c,
- 0x7210, 0x732c, 0x6d5c, 0x7210, 0x732c, 0x6d57, 0x6d5c, 0x080c,
- 0x6b73, 0x080c, 0x6c50, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6,
- 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x6118, 0x2178,
- 0x79a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150,
- 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009,
- 0x0000, 0x0028, 0xa1f8, 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78,
- 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x6dd0, 0x0033,
- 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x6e7c, 0x6ec7,
- 0x6ef4, 0x6fc1, 0x6fef, 0x6ff7, 0x701d, 0x702e, 0x703f, 0x7047,
- 0x705d, 0x7047, 0x70b7, 0x702e, 0x70d8, 0x70e0, 0x703f, 0x70e0,
- 0x70f1, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce,
- 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x790d, 0x7932, 0x7947, 0x796a,
- 0x798b, 0x701d, 0x6dce, 0x701d, 0x7047, 0x6dce, 0x6ef4, 0x6fc1,
- 0x6dce, 0x7daa, 0x7047, 0x6dce, 0x7dca, 0x7047, 0x6dce, 0x703f,
- 0x6e75, 0x6de0, 0x6dce, 0x7def, 0x7e64, 0x7f3b, 0x6dce, 0x7f4c,
- 0x7018, 0x7f68, 0x6dce, 0x79a0, 0x7fc3, 0x6dce, 0x080c, 0x14f6,
- 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005,
- 0x6dde, 0x6dde, 0x6dde, 0x6e14, 0x6e32, 0x6e48, 0x080c, 0x14f6,
- 0x00d6, 0x20a1, 0x020b, 0x080c, 0x710e, 0x7810, 0x2068, 0x20a3,
- 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850,
- 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0018, 0x080c, 0x7821, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068,
- 0x68a0, 0x2069, 0xad00, 0x6ad0, 0xd2ac, 0x1110, 0xd0bc, 0x0110,
- 0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c,
- 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f,
- 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2,
- 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7821,
- 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3,
- 0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
- 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200,
- 0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xad05,
- 0x20a9, 0x0004, 0x53a6, 0x2099, 0xad01, 0x20a9, 0x0004, 0x53a6,
- 0x2099, 0xafad, 0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398,
- 0x1f04, 0x6e64, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c,
- 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x2001, 0xad14, 0x2004,
- 0x609a, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0xad51, 0x6804,
- 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x268a,
- 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004,
- 0x2099, 0xad01, 0x53a6, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1138,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001,
- 0xad1b, 0x20a6, 0x2001, 0xad1c, 0x20a6, 0x0040, 0x20a3, 0x0000,
- 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001,
- 0xad34, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004,
- 0xa082, 0x007f, 0x0238, 0x2001, 0xad1b, 0x20a6, 0x2001, 0xad1c,
- 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xad14, 0x2004, 0xa084,
- 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x60c3,
- 0x0010, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, 0x5037, 0x00ce,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3,
- 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3,
- 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904,
- 0x6f83, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xaf8d,
- 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000,
- 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001,
- 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099,
- 0xaf8d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x574f,
- 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398,
- 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004,
- 0x2099, 0xad01, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04,
- 0x6f5d, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6f63, 0x2099,
- 0xaf95, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xad71, 0x2004, 0xd0e4,
- 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398,
- 0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000,
- 0x1f04, 0x6f7e, 0x0468, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x0140,
- 0x2001, 0xaf8e, 0x2004, 0x60e3, 0x0000, 0x080c, 0x26cb, 0x60e2,
- 0x2099, 0xaf8d, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099,
- 0xad05, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xad01, 0x53a6, 0x20a9,
- 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fa1, 0x20a9, 0x0008, 0x20a3,
- 0x0000, 0x1f04, 0x6fa7, 0x2099, 0xaf95, 0x20a9, 0x0008, 0x53a6,
- 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fb2, 0x20a9, 0x000a,
- 0x20a3, 0x0000, 0x1f04, 0x6fb8, 0x60c3, 0x0074, 0x080c, 0x7821,
- 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x2010, 0x20a3,
- 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2,
- 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51, 0x7904, 0x00fe,
- 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010,
- 0xa085, 0x0002, 0x00d6, 0x0804, 0x7099, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x710e, 0x20a3, 0x5000, 0x0804, 0x6f0f, 0x20a1,
- 0x020b, 0x080c, 0x710e, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x080c, 0x71a2, 0x0020, 0x20a1, 0x020b, 0x080c,
- 0x71aa, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b,
- 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
- 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6f0f, 0x20a1,
- 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828,
- 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2,
- 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x00d6, 0x20a1, 0x020b,
- 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
- 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1178, 0x6998, 0xa184,
- 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0040, 0x20a3,
- 0x0100, 0x0028, 0x20a3, 0x0400, 0x0010, 0x20a3, 0x0700, 0xa006,
- 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51,
- 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110,
- 0xa085, 0x0010, 0x2009, 0xad73, 0x210c, 0xd184, 0x1110, 0xa085,
- 0x0002, 0x0026, 0x2009, 0xad71, 0x210c, 0xd1e4, 0x0130, 0xc0c5,
- 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094,
- 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2,
- 0x20a2, 0x60c3, 0x0014, 0x080c, 0x7821, 0x00de, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6e82,
- 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821,
- 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c,
- 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3,
- 0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x0026, 0x0036,
- 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036,
- 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0,
- 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011,
- 0xad14, 0x2214, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x0118, 0x2011,
- 0xad1c, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6,
- 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xad34,
- 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6,
- 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8,
- 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069,
- 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8,
- 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de,
- 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0029,
- 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2,
- 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000,
- 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xad1b,
- 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000,
- 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3,
- 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021,
- 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021,
- 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
- 0x02d8, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2,
- 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, 0x1128,
- 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0xad1b, 0x2da6,
- 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, 0xae34, 0x2d6c,
- 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000,
- 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3,
- 0x0000, 0x004e, 0x003e, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000,
- 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
- 0x0005, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
- 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
- 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a,
- 0x008c, 0x1a0c, 0x14f6, 0x6118, 0x2178, 0x79a0, 0x2011, 0xad34,
- 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120,
- 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8,
- 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a,
- 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7247, 0x7251,
- 0x726c, 0x7245, 0x7245, 0x7245, 0x7247, 0x080c, 0x14f6, 0x0146,
- 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x7821, 0x014e,
- 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x72b8, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
- 0x080c, 0x7821, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c,
- 0x72f2, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x014e, 0x0005, 0x0026,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
- 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, 0x7175,
- 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
- 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8400,
- 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6,
- 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085,
- 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011,
- 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000,
- 0x0804, 0x7201, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118,
- 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810,
- 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6,
- 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c,
- 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3,
- 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2,
- 0x20a3, 0x0000, 0x0804, 0x7201, 0x00c6, 0x00f6, 0x2c78, 0x7804,
- 0xa08a, 0x0040, 0x0a0c, 0x14f6, 0xa08a, 0x0053, 0x1a0c, 0x14f6,
- 0x7918, 0x2160, 0x61a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110,
- 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff,
- 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c,
- 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe,
- 0x00ce, 0x0005, 0x736f, 0x747b, 0x7418, 0x761a, 0x736d, 0x736d,
- 0x736d, 0x736d, 0x736d, 0x736d, 0x736d, 0x7b41, 0x7b51, 0x7b61,
- 0x7b71, 0x736d, 0x7f79, 0x736d, 0x7b30, 0x080c, 0x14f6, 0x00d6,
- 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, 0x080c, 0x73cf,
- 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2,
- 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040,
- 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, 0x8004,
- 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e,
- 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118,
- 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80,
- 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1,
- 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3,
- 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009,
- 0x6016, 0x2001, 0xafe3, 0x2003, 0x07d0, 0x2001, 0xafe2, 0x2003,
- 0x0009, 0x080c, 0x17bf, 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210,
- 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004,
- 0x2019, 0xad34, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
- 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814,
- 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2,
- 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0xad14, 0x210c,
- 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000,
- 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005,
- 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810,
- 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c,
- 0x080c, 0x7821, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
- 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
- 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814,
- 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
- 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214,
- 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2,
- 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810,
- 0xa06d, 0x080c, 0x5025, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086,
- 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c,
- 0x75d0, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
- 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043,
- 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005,
- 0x74b2, 0x7547, 0x7550, 0x7579, 0x758c, 0x75a7, 0x75b0, 0x74b0,
- 0x080c, 0x14f6, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118,
- 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5,
- 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804,
- 0x7583, 0xa186, 0x0001, 0x190c, 0x14f6, 0x6b78, 0x7820, 0xd0cc,
- 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
- 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
- 0x0300, 0x0904, 0x7541, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc,
- 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020,
- 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x74f0, 0x015e, 0x22a2,
- 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7541, 0x20a1, 0x020b,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889,
- 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7810, 0x22a2, 0x20a3,
- 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7821, 0x0005, 0x2011,
- 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488,
- 0x2011, 0x0302, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016,
- 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008,
- 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500,
- 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2,
- 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7821,
- 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2,
- 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
- 0x0018, 0x080c, 0x7821, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc,
- 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
- 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2,
- 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7821, 0x0005, 0x2011,
- 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888,
- 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001,
- 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808,
- 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108,
- 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7583,
- 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010,
- 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2, 0x20a3,
- 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036,
- 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e,
- 0x013e, 0x015e, 0x00de, 0x0005, 0x7634, 0x7634, 0x7636, 0x7634,
- 0x7634, 0x7634, 0x7658, 0x7634, 0x080c, 0x14f6, 0x7910, 0xa18c,
- 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
- 0x00f9, 0x00d6, 0x2069, 0xad51, 0x6804, 0xd0bc, 0x0130, 0x682c,
- 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de,
- 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80,
- 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c,
- 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6,
- 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xad00, 0x7150,
- 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d0, 0xd6ac, 0x1130, 0xd0bc,
- 0x1120, 0x6910, 0x6a14, 0x7450, 0x0020, 0x6910, 0x6a14, 0x736c,
- 0x7470, 0x781c, 0xa0be, 0x0006, 0x0904, 0x775b, 0xa0be, 0x000a,
- 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073,
- 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
- 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
- 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
- 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0x609f, 0x0000, 0x080c, 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084,
- 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e,
- 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d0, 0xd0ac,
- 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
- 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
- 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
- 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082,
- 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e,
- 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5,
- 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120,
- 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c,
- 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110,
- 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e, 0x004e, 0x005e, 0x00ce,
- 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003,
- 0xa086, 0x0002, 0x0904, 0x77b1, 0x2001, 0xad34, 0x2004, 0xd0ac,
- 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
- 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
- 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
- 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086,
- 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6,
- 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928,
- 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294,
- 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8011, 0x0804,
- 0x7749, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138,
- 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185,
- 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5025,
- 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020,
- 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889,
- 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084,
- 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086,
- 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
- 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294,
- 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120,
- 0x080c, 0x8014, 0x0804, 0x7749, 0x080c, 0x8011, 0x0804, 0x7749,
- 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
- 0x8217, 0x0005, 0x00d6, 0x2069, 0xafc7, 0x6843, 0x0001, 0x00de,
- 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019,
- 0x080c, 0x6578, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085,
- 0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100,
- 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016, 0x00ce, 0x000e,
- 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069,
- 0x0140, 0x080c, 0x574f, 0x1178, 0x2001, 0xafe3, 0x2004, 0xa005,
- 0x1598, 0x080c, 0x57d1, 0x1118, 0x080c, 0x6578, 0x0468, 0x00c6,
- 0x2061, 0xafc7, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x08a1,
- 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xafc7, 0x6128,
- 0xa192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff,
- 0x0198, 0x080c, 0x6578, 0x080c, 0x782b, 0x0070, 0x6124, 0xa1e5,
- 0x0000, 0x0140, 0x080c, 0xaca2, 0x2009, 0x0014, 0x080c, 0x80a7,
- 0x080c, 0x6581, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce,
- 0x0005, 0x2001, 0xafe3, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061,
- 0xafc7, 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce,
- 0x080c, 0x6578, 0x080c, 0x485e, 0x0c38, 0x00c6, 0x00d6, 0x00e6,
- 0x0016, 0x0026, 0x080c, 0x658e, 0x2071, 0xafc7, 0x713c, 0x81ff,
- 0x0570, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x574f, 0x1188,
- 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c, 0x2160,
- 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x080c, 0x57d1,
- 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, 0x6803,
- 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c,
- 0x2160, 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x002e,
- 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x00e6, 0x00d6,
- 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000,
- 0x6018, 0x2068, 0x6ca0, 0x2071, 0xafc7, 0x7018, 0x2068, 0x8dff,
- 0x0198, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010,
- 0x2060, 0x643c, 0x6540, 0x6e48, 0x2d60, 0x080c, 0x4e41, 0x0120,
- 0x080c, 0x7b88, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e,
- 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c,
- 0x710e, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c,
- 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xad14, 0x2004,
- 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006,
- 0x20a2, 0x1f04, 0x7928, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c,
- 0x7821, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
- 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x0156,
- 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x20a3,
- 0x0000, 0x20a9, 0x0006, 0x2011, 0xad40, 0x2019, 0xad41, 0x23a6,
- 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7957, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x014e,
- 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b,
- 0x080c, 0x7183, 0x080c, 0x7199, 0x7810, 0xa080, 0x0000, 0x2004,
- 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
- 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7821, 0x002e, 0x001e,
- 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c,
- 0x710e, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
- 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
- 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808,
- 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7821,
- 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006,
- 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x700c, 0x2060, 0x8cff,
- 0x0178, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x600c, 0x0006,
- 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x7b88, 0x00ce, 0x0c78,
- 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee,
- 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026,
- 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140,
- 0x2071, 0xafc7, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7834,
- 0x68c3, 0x0000, 0x080c, 0x6581, 0x2009, 0x0013, 0x080c, 0x80a7,
- 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804,
- 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
- 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x7a02, 0x7804,
- 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
- 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e,
- 0x012e, 0x0005, 0x2001, 0xad00, 0x2004, 0xa096, 0x0001, 0x0550,
- 0xa096, 0x0004, 0x0538, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011,
- 0x481b, 0x080c, 0x650d, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158,
- 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000,
- 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010,
- 0x1f04, 0x7a3d, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100,
- 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee,
- 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6,
- 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069,
- 0x0100, 0x2079, 0x0140, 0x2071, 0xafc7, 0x703c, 0x2060, 0x8cff,
- 0x0904, 0x7ad5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0,
- 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x658e, 0x080c, 0x20b5,
- 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404,
- 0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7, 0x0000, 0x68cb,
- 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, 0xb01e, 0x6814,
- 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003,
- 0x0000, 0x00fe, 0x00ee, 0x200b, 0x0000, 0x004e, 0xa39d, 0x0000,
- 0x1120, 0x2009, 0x0049, 0x080c, 0x80a7, 0x20a9, 0x03e8, 0x6824,
- 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0,
- 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827,
- 0x0002, 0x0010, 0x1f04, 0x7ab7, 0x7804, 0xa084, 0x1000, 0x0120,
- 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e,
- 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6,
- 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a06, 0x012e, 0x00de,
- 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a32,
- 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006,
- 0x0126, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000,
- 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110,
- 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
- 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00,
- 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
- 0x974e, 0x080c, 0x7b88, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060,
- 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
- 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, 0x20a2,
- 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804,
- 0x7b80, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000,
- 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000,
- 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400,
- 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
- 0x0089, 0x60c3, 0x0020, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
- 0x00e6, 0x2071, 0xafc7, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022,
- 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7b94, 0x20a2,
- 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066,
- 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660,
- 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x7c24, 0x8cff, 0x0904,
- 0x7c24, 0x601c, 0xa086, 0x0006, 0x1904, 0x7c1f, 0x88ff, 0x0138,
- 0x2800, 0xac06, 0x1904, 0x7c1f, 0x2039, 0x0000, 0x0050, 0x6018,
- 0xa206, 0x1904, 0x7c1f, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904,
- 0x7c1f, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005,
- 0x01f0, 0x080c, 0x6581, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c,
- 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384,
- 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
- 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003,
- 0x0009, 0x630a, 0x0460, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616,
- 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012,
- 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
- 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e,
- 0x080c, 0x7b88, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x7bab, 0x2c78,
- 0x600c, 0x2060, 0x0804, 0x7bab, 0xa006, 0x012e, 0x000e, 0x006e,
- 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000,
- 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
- 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7,
- 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x7c98, 0x601c, 0xa086,
- 0x0006, 0x1904, 0x7c93, 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904,
- 0x7c93, 0x0040, 0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6050,
- 0xa106, 0x15c8, 0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001,
- 0x080c, 0x7a64, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
- 0x7047, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a,
- 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036,
- 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
- 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c,
- 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e, 0x87ff, 0x1190,
- 0x00ce, 0x0804, 0x7c43, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7c43,
- 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee,
- 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88,
- 0x00e6, 0x2071, 0xafc7, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002,
- 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005,
- 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091,
- 0x8000, 0x2071, 0xafc7, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff,
- 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c,
- 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00,
- 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110,
- 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020,
- 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e,
- 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
- 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x760c,
- 0x2660, 0x2678, 0x8cff, 0x0904, 0x7d7e, 0x6018, 0xa080, 0x0028,
- 0x2004, 0xa206, 0x1904, 0x7d79, 0x7024, 0xac06, 0x1508, 0x2069,
- 0x0100, 0x68c0, 0xa005, 0x0904, 0x7d55, 0x080c, 0x7834, 0x68c3,
- 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
- 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
- 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
- 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140,
- 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000,
- 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678,
- 0x600f, 0x0000, 0x080c, 0x9778, 0x1158, 0x080c, 0x2aff, 0x080c,
- 0x9789, 0x11f0, 0x080c, 0x85f3, 0x00d8, 0x080c, 0x7ca8, 0x08c0,
- 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0090, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742,
- 0x080c, 0x994e, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804,
- 0x7d02, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7d02, 0x012e, 0x000e,
- 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086,
- 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c18, 0x0036, 0x0156, 0x0136,
- 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x28f9,
- 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020,
- 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e,
- 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3,
- 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x2099, 0xafa6, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004,
- 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7821,
- 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0214,
- 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7821, 0x0005, 0x00d6,
- 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0x9a34, 0x1904, 0x7e5d,
- 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x1300, 0x20a3, 0x0000,
- 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080,
- 0x0028, 0x2014, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x11d0, 0xa286,
- 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286,
- 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc,
- 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc,
- 0x0428, 0xa2e8, 0xae34, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2,
- 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xad34,
- 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082,
- 0x007e, 0x0240, 0x00d6, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6,
- 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2,
- 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
- 0x080c, 0x7821, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803,
- 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168,
- 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x7ed3,
- 0xa186, 0x0005, 0x0904, 0x7ebc, 0xa186, 0x0004, 0x05b8, 0xa186,
- 0x0008, 0x0904, 0x7ec4, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c,
- 0x7f3b, 0x002e, 0x00de, 0x0005, 0x080c, 0x7ef7, 0x2009, 0x4000,
- 0x6800, 0x0002, 0x7e9d, 0x7ea8, 0x7e9f, 0x7ea8, 0x7ea4, 0x7e9d,
- 0x7e9d, 0x7ea8, 0x7ea8, 0x7ea8, 0x7ea8, 0x7e9d, 0x7e9d, 0x7e9d,
- 0x7e9d, 0x7e9d, 0x7ea8, 0x7e9d, 0x7ea8, 0x080c, 0x14f6, 0x6820,
- 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000,
- 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x7eed, 0x080c, 0x7ef7,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286,
- 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002,
- 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810,
- 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180,
- 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118,
- 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000,
- 0x60c3, 0x0018, 0x080c, 0x7821, 0x002e, 0x00de, 0x0005, 0x0036,
- 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x71aa, 0xa006,
- 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818,
- 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118,
- 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xad1b, 0x2d2c, 0x8d68,
- 0x2d34, 0xa0e8, 0xae34, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030,
- 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080,
- 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2,
- 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e,
- 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3,
- 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3,
- 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7106,
- 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2,
- 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007,
- 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x080c, 0x71a2, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821,
- 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c,
- 0x7821, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110,
- 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085,
- 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68,
- 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810,
- 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000,
- 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7810,
- 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2,
- 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575,
- 0x080c, 0x782b, 0x080c, 0x6578, 0x0005, 0x0156, 0x0136, 0x0036,
- 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068,
- 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212,
- 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308,
- 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215,
- 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98,
- 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000,
- 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e,
- 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036,
- 0x6116, 0x0005, 0x2061, 0xb400, 0x2a70, 0x7064, 0x7046, 0x704b,
- 0xb400, 0x0005, 0x00e6, 0x0126, 0x2071, 0xad00, 0x2091, 0x8000,
- 0x7544, 0xa582, 0x0010, 0x0608, 0x7048, 0x2060, 0x6000, 0xa086,
- 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0,
- 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8,
- 0x0018, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085, 0x0001, 0x012e,
- 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6,
- 0x2071, 0xad00, 0x7544, 0xa582, 0x0010, 0x0600, 0x7048, 0x2060,
- 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02,
- 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529,
- 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502, 0x1228, 0x754a, 0xa085,
- 0x0001, 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc8, 0xa006, 0x0cc8,
- 0xac82, 0xb400, 0x0a0c, 0x14f6, 0x2001, 0xad16, 0x2004, 0xac02,
- 0x1a0c, 0x14f6, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016,
- 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022,
- 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061,
- 0xad00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108, 0x0005,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0cc0, 0x601c,
- 0xa084, 0x000f, 0x0002, 0x80b6, 0x80c5, 0x80e0, 0x80fb, 0x9a61,
- 0x9a7c, 0x9a97, 0x80b6, 0x80c5, 0x80b6, 0x8116, 0xa186, 0x0013,
- 0x1128, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x0005, 0xa18e, 0x0047,
- 0x1118, 0xa016, 0x080c, 0x1824, 0x0005, 0x0066, 0x6000, 0xa0b2,
- 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x80de, 0x8478,
- 0x862d, 0x80de, 0x86a2, 0x81cf, 0x80de, 0x80de, 0x840a, 0x8a91,
- 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x080c, 0x14f6,
- 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e,
- 0x0005, 0x80f9, 0x909a, 0x80f9, 0x80f9, 0x80f9, 0x80f9, 0x80f9,
- 0x80f9, 0x9045, 0x9200, 0x80f9, 0x90c7, 0x913e, 0x90c7, 0x913e,
- 0x80f9, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
- 0x14f6, 0x0013, 0x006e, 0x0005, 0x8114, 0x8ad2, 0x8b98, 0x8cb8,
- 0x8e12, 0x8114, 0x8114, 0x8114, 0x8aac, 0x8ff5, 0x8ff8, 0x8114,
- 0x8114, 0x8114, 0x8114, 0x9022, 0x080c, 0x14f6, 0x0066, 0x6000,
- 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x812f,
- 0x812f, 0x812f, 0x8152, 0x81a5, 0x812f, 0x812f, 0x812f, 0x8131,
- 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x080c,
- 0x14f6, 0xa186, 0x0003, 0x190c, 0x14f6, 0x00d6, 0x6003, 0x0003,
- 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880,
- 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x00de, 0x2c10, 0x080c,
- 0x1e6e, 0x080c, 0x680b, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d0d,
- 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x815e, 0x815e, 0x8160,
- 0x817f, 0x815e, 0x815e, 0x815e, 0x815e, 0x8191, 0x080c, 0x14f6,
- 0x00d6, 0x0016, 0x080c, 0x6c05, 0x080c, 0x6d0d, 0x6003, 0x0004,
- 0x6110, 0x2168, 0x6854, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
- 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882,
- 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c,
- 0x6c05, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0120, 0x684b,
- 0x0006, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c, 0x6d0d,
- 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110, 0x2168,
- 0x080c, 0x9596, 0x0120, 0x684b, 0x0029, 0x080c, 0x510c, 0x00de,
- 0x080c, 0x8078, 0x080c, 0x6d0d, 0x0005, 0xa182, 0x0047, 0x0002,
- 0x81b3, 0x81c2, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1,
- 0x81b1, 0x080c, 0x14f6, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4,
- 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c,
- 0x1824, 0x0005, 0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853,
- 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x0005, 0xa1b6,
- 0x0015, 0x1118, 0x080c, 0x8078, 0x0030, 0xa1b6, 0x0016, 0x190c,
- 0x14f6, 0x080c, 0x8078, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010,
- 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0,
- 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002,
- 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x81ea, 0x00e6, 0x080c,
- 0x9596, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
- 0x00ee, 0x080c, 0x8078, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386,
- 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd,
- 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103,
- 0x6b32, 0x080c, 0x8078, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9,
- 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0,
- 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080,
- 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037,
- 0x0103, 0x00ee, 0x080c, 0x8078, 0x001e, 0x0005, 0x0016, 0x2009,
- 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff,
- 0x808e, 0x703c, 0xa084, 0x00ff, 0x8086, 0xa080, 0x0004, 0xa108,
- 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0,
- 0x080c, 0x48be, 0x00e6, 0x080c, 0x9596, 0x0140, 0x6010, 0x2070,
- 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c,
- 0x8078, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68,
- 0x0016, 0x2009, 0x0035, 0x080c, 0x9a34, 0x001e, 0x1168, 0x0026,
- 0x6228, 0x2268, 0x002e, 0x2071, 0xb28c, 0x6b1c, 0xa386, 0x0003,
- 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x8078, 0x0020, 0x0031,
- 0x0010, 0x080c, 0x8323, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810,
- 0x2078, 0xa186, 0x0015, 0x0904, 0x830c, 0xa18e, 0x0016, 0x1904,
- 0x8321, 0x700c, 0xa084, 0xff00, 0xa086, 0x1700, 0x1904, 0x82eb,
- 0x8fff, 0x0904, 0x831f, 0x6808, 0xa086, 0xffff, 0x1904, 0x830e,
- 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810,
- 0xa106, 0x1904, 0x830e, 0x7980, 0x7814, 0xa106, 0x1904, 0x830e,
- 0x080c, 0x9742, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4,
- 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6665,
- 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138,
- 0x00c6, 0x2d60, 0x080c, 0x9374, 0x00ce, 0x0804, 0x831f, 0x00c6,
- 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4993, 0x0010,
- 0x080c, 0x4b7c, 0x00de, 0x00ce, 0x1548, 0x00c6, 0x2d60, 0x080c,
- 0x8078, 0x00ce, 0x04a0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018,
- 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007,
- 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c,
- 0x6c50, 0x00ce, 0x00e0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001,
- 0xafa5, 0x2004, 0x683e, 0x0098, 0x0471, 0x0098, 0x8fff, 0x090c,
- 0x14f6, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x684b, 0x0003, 0x080c,
- 0x926f, 0x080c, 0x9742, 0x080c, 0x974e, 0x00de, 0x00ce, 0x080c,
- 0x8078, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xafa5,
- 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00,
- 0x2060, 0x080c, 0xabb4, 0x080c, 0x6618, 0x080c, 0x8078, 0x00ce,
- 0x080c, 0x8078, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80,
- 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xafa5, 0x2004, 0x683e, 0x0804,
- 0x839d, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x6804, 0xa086,
- 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007,
- 0x0050, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x04f0, 0x6800,
- 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x14f6, 0x6820, 0xd0dc,
- 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180,
- 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852,
- 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0,
- 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0,
- 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406,
- 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e,
- 0x080c, 0x9894, 0x080c, 0x6c50, 0x0010, 0x080c, 0x8078, 0x004e,
- 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068,
- 0x6a1c, 0xa286, 0x0007, 0x0904, 0x83ee, 0xa286, 0x0002, 0x05f0,
- 0xa286, 0x0000, 0x05d8, 0x6808, 0x6338, 0xa306, 0x15b8, 0x2071,
- 0xb28c, 0xa186, 0x0015, 0x0560, 0xa18e, 0x0016, 0x1190, 0x6030,
- 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00,
- 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102,
- 0x00b8, 0x00c6, 0x6034, 0x2060, 0x6010, 0x2068, 0x080c, 0x9596,
- 0x090c, 0x14f6, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b,
- 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x0030,
- 0x6034, 0x2070, 0x2001, 0xafa5, 0x2004, 0x703e, 0x080c, 0x8078,
- 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98,
- 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1148, 0x6018, 0x2068,
- 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de,
- 0x0804, 0x81f6, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b2,
- 0x0040, 0x1a04, 0x846e, 0x0002, 0x8462, 0x8456, 0x8462, 0x8462,
- 0x8462, 0x8462, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8462, 0x8462, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8462,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8462, 0x8454, 0x8454, 0x080c, 0x14f6, 0x6003, 0x0001,
- 0x6106, 0x080c, 0x67ee, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50,
- 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x67ee, 0x0126,
- 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x2600, 0x0002,
- 0x8462, 0x8476, 0x8476, 0x8462, 0x8462, 0x8476, 0x080c, 0x14f6,
- 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x0904,
- 0x8518, 0xa1b6, 0x0027, 0x1904, 0x84de, 0x080c, 0x6b73, 0x6004,
- 0x080c, 0x9778, 0x0188, 0x080c, 0x9789, 0x0904, 0x84d8, 0xa08e,
- 0x0021, 0x0904, 0x84db, 0xa08e, 0x0022, 0x0904, 0x84d8, 0xa08e,
- 0x003d, 0x0904, 0x84db, 0x04a8, 0x080c, 0x2aff, 0x2001, 0x0007,
- 0x080c, 0x4c30, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3,
- 0xa186, 0x007e, 0x1148, 0x2001, 0xad34, 0x2014, 0xc285, 0x080c,
- 0x574f, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110,
- 0x2019, 0x0028, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c,
- 0x681d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x4ecf, 0x00ce,
- 0x2c08, 0x080c, 0xa712, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c,
- 0x4c9f, 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005,
- 0x080c, 0x85f3, 0x0cb0, 0x080c, 0x8621, 0x0c98, 0xa186, 0x0014,
- 0x1db0, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x080c, 0x9778, 0x1188,
- 0x080c, 0x2aff, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3,
- 0xa186, 0x007e, 0x1128, 0x2001, 0xad34, 0x200c, 0xc185, 0x2102,
- 0x08c0, 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0890, 0x6004,
- 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079,
- 0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e,
- 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x85f3, 0x0804, 0x84d1,
- 0xa0b2, 0x0040, 0x1a04, 0x85db, 0x2008, 0x0002, 0x8560, 0x8561,
- 0x8564, 0x8567, 0x856a, 0x856d, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x8570, 0x857f, 0x855e, 0x8581,
- 0x857f, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x857f, 0x857f,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x85bb, 0x857f, 0x855e, 0x857b, 0x855e, 0x855e, 0x855e, 0x857c,
- 0x855e, 0x855e, 0x855e, 0x857f, 0x85b2, 0x855e, 0x080c, 0x14f6,
- 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001,
- 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400,
- 0x080c, 0x6b73, 0x6003, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e,
- 0x080c, 0x6c50, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4c30, 0x0804,
- 0x85cc, 0x080c, 0x6b73, 0x2001, 0xafa3, 0x2004, 0x6016, 0x2001,
- 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x6c50, 0x0005,
- 0x080c, 0x4c30, 0x080c, 0x6b73, 0x6003, 0x0002, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x0036, 0x2019, 0xad5c, 0x2304, 0xa084, 0xff00,
- 0x1120, 0x2001, 0xafa3, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004,
- 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c,
- 0x6c50, 0x08e8, 0x080c, 0x6b73, 0x080c, 0x994e, 0x080c, 0x8078,
- 0x080c, 0x6c50, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079,
- 0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x080c, 0x6b73, 0x080c,
- 0x8078, 0x080c, 0x6c50, 0x0818, 0x080c, 0x6b73, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xafa3, 0x2004, 0x6016,
- 0x080c, 0x6c50, 0x0005, 0x2600, 0x2008, 0x0002, 0x85e6, 0x85e4,
- 0x85e4, 0x85cc, 0x85cc, 0x85e4, 0x080c, 0x14f6, 0x080c, 0x6b73,
- 0x00d6, 0x6010, 0x2068, 0x080c, 0x15f0, 0x00de, 0x080c, 0x8078,
- 0x080c, 0x6c50, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0x9596,
- 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001,
- 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0x9a05, 0x0090,
- 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e,
- 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103,
- 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009,
- 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037,
- 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668,
- 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x14f6,
- 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0x99c1, 0x0804, 0x8692,
- 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0x9971, 0x0804, 0x8692,
- 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x97b9, 0x0804, 0x8692,
- 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x97d0, 0x04d8, 0x6604,
- 0xa6b6, 0x001f, 0x1118, 0x080c, 0x81dc, 0x04a0, 0x6604, 0xa6b6,
- 0x0000, 0x1118, 0x080c, 0x83f4, 0x0468, 0x6604, 0xa6b6, 0x0022,
- 0x1118, 0x080c, 0x8204, 0x0430, 0x6604, 0xa6b6, 0x0035, 0x1118,
- 0x080c, 0x826b, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c,
- 0x83a3, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x821e,
- 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x823e, 0x0050,
- 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118,
- 0x0804, 0x883f, 0x0005, 0x080c, 0x80be, 0x0ce0, 0x86b9, 0x86bc,
- 0x86b9, 0x86fe, 0x86b9, 0x87cc, 0x884d, 0x86b9, 0x86b9, 0x881b,
- 0x86b9, 0x882f, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18,
- 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x00e6, 0xacf0, 0x0004,
- 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8078,
- 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x7080,
- 0xa086, 0x0074, 0x1530, 0x080c, 0xa6e9, 0x11b0, 0x00d6, 0x6018,
- 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5,
- 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c,
- 0x2aff, 0x080c, 0x8078, 0x0078, 0x2001, 0x000a, 0x080c, 0x4c30,
- 0x080c, 0x2aff, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee,
- 0x0010, 0x080c, 0x87bd, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168,
- 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2069, 0xad51, 0x6804, 0xd0a4,
- 0x0120, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x0005, 0x00d6, 0x2011,
- 0xad20, 0x2204, 0xa086, 0x0074, 0x1904, 0x87ba, 0x6018, 0x2068,
- 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x894d, 0x0804, 0x875e,
- 0x080c, 0x8943, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286,
- 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
- 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200,
- 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078,
- 0x0804, 0x87bb, 0x00e6, 0x2071, 0xad34, 0x2e04, 0xd09c, 0x0188,
- 0x2071, 0xb280, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284,
- 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112,
- 0x7216, 0x00ee, 0x6010, 0xa005, 0x0128, 0x2068, 0x6838, 0xd0f4,
- 0x0108, 0x0880, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001,
- 0x6007, 0x0003, 0x080c, 0x67ee, 0x0804, 0x87bb, 0x685c, 0xd0e4,
- 0x01d0, 0x080c, 0x9903, 0x080c, 0x574f, 0x0110, 0xd0dc, 0x1900,
- 0x2011, 0xad34, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xaf8e, 0x2004,
- 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x26cb, 0x78e2,
- 0x00fe, 0x0804, 0x8728, 0x080c, 0x9937, 0x2011, 0xad34, 0x2204,
- 0xc0a5, 0x2012, 0x0006, 0x080c, 0xa801, 0x000e, 0x1904, 0x8728,
- 0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x00c6, 0x2009,
- 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe,
- 0x080c, 0x26a0, 0x00f6, 0x2079, 0xad00, 0x7972, 0x2100, 0x2009,
- 0x0000, 0x080c, 0x2676, 0x794e, 0x00fe, 0x8108, 0x080c, 0x4c80,
- 0x2c00, 0x00ce, 0x1904, 0x8728, 0x601a, 0x2001, 0x0002, 0x080c,
- 0x4c30, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
- 0x67ee, 0x0008, 0x0011, 0x00de, 0x0005, 0x2001, 0xad00, 0x2004,
- 0xa086, 0x0003, 0x0120, 0x2001, 0x0007, 0x080c, 0x4c30, 0x080c,
- 0x2aff, 0x080c, 0x8078, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071,
- 0xad00, 0x7080, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003,
- 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3cce, 0x00d6, 0x6018,
- 0x2068, 0x080c, 0x4d72, 0x080c, 0x86ed, 0x00de, 0x080c, 0x89f7,
- 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518,
- 0x2001, 0x0006, 0x080c, 0x4c30, 0x00e6, 0x6010, 0xa075, 0x01a8,
- 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000,
- 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0x9a05, 0x0030, 0x7007,
- 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2aff,
- 0x080c, 0x8078, 0x0020, 0x080c, 0x85f3, 0x080c, 0x87bd, 0x001e,
- 0x002e, 0x00ee, 0x0005, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014,
- 0x1158, 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007,
- 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c, 0x87bd, 0x0005, 0x2011,
- 0xad20, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c,
- 0x4c30, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x000b,
- 0x0005, 0x86b9, 0x8854, 0x86b9, 0x888a, 0x86b9, 0x88ff, 0x884d,
- 0x86b9, 0x86b9, 0x8912, 0x86b9, 0x8922, 0x6604, 0xa6b6, 0x001e,
- 0x1110, 0x080c, 0x8078, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x8932,
- 0x1178, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c,
- 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x00f8,
- 0x2009, 0xb28e, 0x2104, 0xa086, 0x0009, 0x1160, 0x6018, 0x2068,
- 0x6840, 0xa084, 0x00ff, 0xa005, 0x0180, 0x8001, 0x6842, 0x6017,
- 0x000a, 0x0068, 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086,
- 0x1900, 0x1118, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x00ce,
- 0x00de, 0x0005, 0x080c, 0x8940, 0x00d6, 0x2069, 0xaf9d, 0x2d04,
- 0xa005, 0x0168, 0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138,
- 0x2069, 0xad1c, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de,
- 0x0078, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c,
- 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x0428,
- 0x080c, 0x85f3, 0x2009, 0xb28e, 0x2134, 0xa6b4, 0x00ff, 0xa686,
- 0x0005, 0x01e0, 0xa686, 0x000b, 0x01b0, 0x2009, 0xb28f, 0x2104,
- 0xa084, 0xff00, 0x1118, 0xa686, 0x0009, 0x0180, 0xa086, 0x1900,
- 0x1150, 0xa686, 0x0009, 0x0150, 0x2001, 0x0004, 0x080c, 0x4c30,
- 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x00d6, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de,
- 0x0c90, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140,
- 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28,
- 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xad00, 0x080c,
- 0x48f5, 0x00ee, 0x0010, 0x080c, 0x2ad9, 0x00de, 0x08a0, 0x080c,
- 0x8940, 0x1158, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001,
- 0x6007, 0x0003, 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c,
- 0x87bd, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, 0x4c30,
- 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x67ee, 0x0010, 0x080c,
- 0x87bd, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, 0x4c30,
- 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c,
- 0x87bd, 0x0005, 0x2009, 0xb28e, 0x2104, 0xa086, 0x0003, 0x1138,
- 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005,
- 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164,
- 0x080c, 0x4ceb, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6,
- 0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xad34, 0x2e04, 0xa085,
- 0x0003, 0x2072, 0x080c, 0x89cc, 0x0538, 0x2001, 0xad52, 0x2004,
- 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xa96c,
- 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009,
- 0x0001, 0x080c, 0x2aac, 0x2071, 0xad00, 0x080c, 0x28fa, 0x00c6,
- 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, 0x2bc9, 0x8108,
- 0x1f04, 0x897d, 0x015e, 0x00ce, 0x080c, 0x8943, 0x6813, 0x00ff,
- 0x6817, 0xfffe, 0x2071, 0xb280, 0x2079, 0x0100, 0x2e04, 0xa084,
- 0x00ff, 0x2069, 0xad1b, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04,
- 0x2069, 0xad1c, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084,
- 0xff00, 0x001e, 0xa105, 0x2009, 0xad27, 0x200a, 0x2200, 0xa084,
- 0x00ff, 0x2008, 0x080c, 0x26a0, 0x080c, 0x574f, 0x0170, 0x2069,
- 0xb28e, 0x2071, 0xaf9f, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818,
- 0x700a, 0x681c, 0x700e, 0x080c, 0x9903, 0x0040, 0x2001, 0x0006,
- 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078, 0x001e, 0x003e,
- 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156,
- 0x2019, 0xad27, 0x231c, 0x83ff, 0x01e8, 0x2071, 0xb280, 0x2e14,
- 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190,
- 0x2011, 0xb296, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c,
- 0x1148, 0x2011, 0xb29a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c,
- 0x8a7c, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6,
- 0x2071, 0xb28c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086,
- 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086,
- 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006,
- 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6,
- 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000,
- 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400,
- 0x2071, 0xad00, 0x7244, 0x7064, 0xa202, 0x16f0, 0x080c, 0xa990,
- 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568,
- 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000,
- 0xa086, 0x0004, 0x1110, 0x080c, 0x190b, 0xa786, 0x0008, 0x1148,
- 0x080c, 0x9789, 0x1130, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x974e,
- 0x00a0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0160, 0xa786, 0x0003,
- 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c,
- 0x080c, 0x9742, 0x080c, 0x974e, 0x00ce, 0xace0, 0x0018, 0x7058,
- 0xac02, 0x1210, 0x0804, 0x8a2a, 0x012e, 0x000e, 0x002e, 0x004e,
- 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006,
- 0x1d00, 0x080c, 0xa91f, 0x0c30, 0x220c, 0x2304, 0xa106, 0x1130,
- 0x8210, 0x8318, 0x1f04, 0x8a7c, 0xa006, 0x0005, 0x2304, 0xa102,
- 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001,
- 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x080c, 0x9778,
- 0x0120, 0x080c, 0x9789, 0x0168, 0x0028, 0x080c, 0x2aff, 0x080c,
- 0x9789, 0x0138, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50,
- 0x0005, 0x080c, 0x85f3, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x8ac2,
- 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2,
- 0x8ac2, 0x8ac2, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac2, 0x8ac2,
- 0x8ac2, 0x8ac4, 0x080c, 0x14f6, 0x600b, 0xffff, 0x6003, 0x0001,
- 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50,
- 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040,
- 0x0804, 0x8b5e, 0xa186, 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c,
- 0x2ad9, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0168, 0x6837,
- 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e,
- 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x080c,
- 0x6c50, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040,
- 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186,
- 0x0047, 0x190c, 0x14f6, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198,
- 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699,
- 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002,
- 0x1110, 0x0804, 0x8b98, 0x080c, 0x80be, 0x0005, 0x0002, 0x8b3c,
- 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a,
- 0x8b3a, 0x8b3a, 0x8b57, 0x8b57, 0x8b57, 0x8b57, 0x8b3a, 0x8b57,
- 0x8b3a, 0x8b57, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x00d6, 0x6110,
- 0x2168, 0x080c, 0x9596, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006,
- 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, 0x510c, 0x080c,
- 0x9742, 0x00de, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c,
- 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x0002, 0x8b74,
- 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72,
- 0x8b72, 0x8b72, 0x8b86, 0x8b86, 0x8b86, 0x8b86, 0x8b72, 0x8b91,
- 0x8b72, 0x8b86, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c50, 0x6010, 0xa088,
- 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x6b73,
- 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x6c50,
- 0x0005, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005,
- 0xa182, 0x0040, 0x0002, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae,
- 0x8bb0, 0x8c88, 0x8ca9, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae,
- 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x080c, 0x14f6,
- 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xb280, 0x7124, 0x610a,
- 0x2071, 0xb28c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff,
- 0x0904, 0x8c54, 0xa68c, 0x0c00, 0x01e8, 0x00f6, 0x2c78, 0x080c,
- 0x5029, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, 0x6020, 0xd0dc,
- 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, 0xa306, 0x1904,
- 0x8c66, 0x731c, 0x6810, 0xa306, 0x1904, 0x8c66, 0x7318, 0x6b62,
- 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186,
- 0x0028, 0x1128, 0x080c, 0x9767, 0x684b, 0x001c, 0x00e8, 0xd6dc,
- 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10,
- 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206,
- 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b,
- 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e,
- 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xb299, 0x2004,
- 0xa005, 0x1118, 0xc6c4, 0x0804, 0x8bbf, 0x7328, 0x732c, 0x6b56,
- 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036,
- 0x2308, 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e,
- 0xd6cc, 0x0904, 0x8c79, 0x7124, 0x695a, 0x81ff, 0x0904, 0x8c79,
- 0xa192, 0x0021, 0x1250, 0x2071, 0xb298, 0x831c, 0x2300, 0xae18,
- 0xad90, 0x001d, 0x080c, 0x927f, 0x04a0, 0x6838, 0xd0fc, 0x0120,
- 0x2009, 0x0020, 0x695a, 0x0c78, 0x00f6, 0x2d78, 0x080c, 0x9224,
- 0x00fe, 0x080c, 0x926f, 0x0438, 0x00f6, 0x2c78, 0x080c, 0x5029,
- 0x00fe, 0x0188, 0x684c, 0xd0ac, 0x0170, 0x6020, 0xd0dc, 0x1158,
- 0x6850, 0xd0bc, 0x1140, 0x684c, 0xd0f4, 0x1128, 0x080c, 0x9866,
- 0x00de, 0x00ee, 0x00e0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46,
- 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c,
- 0x8e04, 0x080c, 0x510c, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
- 0x080c, 0x9834, 0x00de, 0x00ee, 0x1110, 0x080c, 0x8078, 0x0005,
- 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00, 0x7e0c,
- 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120, 0x6003, 0x0002,
- 0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f,
- 0x0000, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b, 0x080c, 0x6d0d,
- 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110,
- 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005,
- 0xa182, 0x0040, 0x0002, 0x8cce, 0x8cce, 0x8cce, 0x8cce, 0x8cce,
- 0x8cd0, 0x8d61, 0x8cce, 0x8cce, 0x8d77, 0x8ddb, 0x8cce, 0x8cce,
- 0x8cce, 0x8cce, 0x8dea, 0x8cce, 0x8cce, 0x8cce, 0x080c, 0x14f6,
- 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c, 0x6110, 0x2178,
- 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218,
- 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x8d5c, 0xa694,
- 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e,
- 0xa284, 0x0300, 0x0904, 0x8d5c, 0x080c, 0x15d9, 0x090c, 0x14f6,
- 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838,
- 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
- 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
- 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060,
- 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
- 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
- 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff,
- 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308,
- 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc,
- 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250,
- 0x2071, 0xb298, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c,
- 0x927f, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a,
- 0x0c78, 0x2d78, 0x080c, 0x9224, 0x00de, 0x00ee, 0x00fe, 0x007e,
- 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00,
- 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
- 0x00fe, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x781a, 0x0005, 0x00d6,
- 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c05, 0x080c, 0x6d0d,
- 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x8dd9, 0xd1cc, 0x0540,
- 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850,
- 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156,
- 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x8da1, 0x015e,
- 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600,
- 0x0418, 0x0016, 0x080c, 0x1600, 0x00de, 0x080c, 0x926f, 0x00e0,
- 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180,
- 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118,
- 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010,
- 0x684b, 0x0000, 0x080c, 0x510c, 0x080c, 0x9834, 0x1110, 0x080c,
- 0x8078, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7a64, 0x6003,
- 0x0002, 0x2001, 0xafa5, 0x2004, 0x603e, 0x080c, 0x6c05, 0x080c,
- 0x6d0d, 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110,
- 0x2168, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029,
- 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c,
- 0x8078, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138,
- 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962,
- 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x8e28, 0x8e28, 0x8e28,
- 0x8e28, 0x8e28, 0x8e2a, 0x8e28, 0x8ee3, 0x8eef, 0x8e28, 0x8e28,
- 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28,
- 0x080c, 0x14f6, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c,
- 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c,
- 0x5029, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4,
- 0x0120, 0x080c, 0x9866, 0x0804, 0x8ede, 0x7e46, 0x7f4c, 0xc7e5,
- 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904,
- 0x8ed4, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862,
- 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x8ed2, 0xa686, 0x0100,
- 0x1140, 0x2001, 0xb299, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46,
- 0x0c28, 0x080c, 0x15d9, 0x090c, 0x14f6, 0x2d00, 0x784a, 0x7f4c,
- 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c,
- 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318,
- 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180,
- 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118,
- 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010,
- 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e,
- 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a,
- 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xb298,
- 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc, 0x01d8, 0x7124,
- 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xb298,
- 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x927f, 0x0050,
- 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78,
- 0x080c, 0x9224, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, 0x0001,
- 0x2071, 0xb28c, 0x7218, 0x731c, 0x080c, 0x186f, 0x00de, 0x00ee,
- 0x00fe, 0x007e, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x20e1,
- 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x2001,
- 0xafa5, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168,
- 0x694c, 0xd1e4, 0x0904, 0x8ff3, 0x603f, 0x0000, 0x00f6, 0x2c78,
- 0x080c, 0x5029, 0x00fe, 0x0548, 0x6814, 0x6910, 0xa115, 0x0528,
- 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x01f8, 0x684c, 0xc0e4,
- 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, 0x697c,
- 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020,
- 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
- 0x00de, 0x080c, 0x9866, 0x0804, 0x8ff3, 0x694c, 0xd1cc, 0x0904,
- 0x8fc3, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x8f88, 0x0016, 0x684c,
- 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c,
- 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b,
- 0x0015, 0x080c, 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080,
- 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c,
- 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04,
- 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d,
- 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012,
- 0x8318, 0x8210, 0x1f04, 0x8f76, 0x015e, 0x00fe, 0x000e, 0x6852,
- 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600, 0x0804, 0x8fee,
- 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002,
- 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c,
- 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c,
- 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128,
- 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130,
- 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04, 0x6860, 0x7862,
- 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x1600, 0x00de,
- 0x080c, 0x926f, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c,
- 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0x99ee, 0x0118,
- 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007,
- 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914,
- 0xa115, 0x0110, 0x080c, 0x8e04, 0x080c, 0x510c, 0x080c, 0x9834,
- 0x1110, 0x080c, 0x8078, 0x00de, 0x0005, 0x080c, 0x6b73, 0x0010,
- 0x080c, 0x6c05, 0x080c, 0x9596, 0x01c0, 0x00d6, 0x6110, 0x2168,
- 0x6837, 0x0103, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x11c0, 0xd184,
- 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xabfa,
- 0x6847, 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c,
- 0x6c50, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b,
- 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x9038, 0x9038, 0x9038,
- 0x9038, 0x9038, 0x903a, 0x9038, 0x903d, 0x9038, 0x9038, 0x9038,
- 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038,
- 0x080c, 0x14f6, 0x080c, 0x8078, 0x0005, 0x0006, 0x0026, 0xa016,
- 0x080c, 0x1824, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002,
- 0x9051, 0x904f, 0x904f, 0x905d, 0x904f, 0x904f, 0x904f, 0x080c,
- 0x14f6, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6,
- 0x00e6, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0x9586,
- 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18,
- 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x0128,
- 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003,
- 0x0001, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00f6, 0x2278, 0x080c,
- 0x5029, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260,
- 0x603f, 0x0000, 0x080c, 0x9866, 0x00ce, 0x00ee, 0x00de, 0x005e,
- 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085,
- 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c, 0x14f6, 0xa082, 0x0085,
- 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x14f6,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x90be,
- 0x90c0, 0x90c0, 0x90be, 0x90be, 0x90be, 0x90be, 0x080c, 0x14f6,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa186,
- 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186,
- 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x00d6, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000,
- 0x684b, 0x0029, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c,
- 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c, 0x80be, 0x0ce0, 0xa186,
- 0x0014, 0x1dd0, 0x080c, 0x6b73, 0x00d6, 0x6010, 0x2068, 0x080c,
- 0x9596, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006,
- 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x910e, 0x910c, 0x910c,
- 0x910c, 0x910c, 0x910c, 0x9126, 0x080c, 0x14f6, 0x080c, 0x6b73,
- 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
- 0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004,
- 0x6016, 0x6003, 0x000c, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73,
- 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
- 0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004,
- 0x6016, 0x6003, 0x000e, 0x080c, 0x6c50, 0x0005, 0xa182, 0x008c,
- 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x80be, 0x0005,
- 0x914f, 0x914f, 0x914f, 0x914f, 0x9151, 0x91a4, 0x914f, 0x080c,
- 0x14f6, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0168,
- 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
- 0x0035, 0x1118, 0x00de, 0x0804, 0x91b7, 0x080c, 0x9742, 0x080c,
- 0x9596, 0x01c8, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4,
- 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118,
- 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847,
- 0x0000, 0x080c, 0x510c, 0x2c68, 0x080c, 0x8022, 0x01c0, 0x6003,
- 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xb28e, 0x210c,
- 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c,
- 0x9956, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x67a8, 0x2d60,
- 0x080c, 0x8078, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029,
- 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035,
- 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6,
- 0x2c68, 0x080c, 0x9a34, 0x1904, 0x91fc, 0x080c, 0x8022, 0x01d8,
- 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928,
- 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934,
- 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0x9956, 0x080c,
- 0x67a8, 0x080c, 0x6c50, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128,
- 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b,
- 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847, 0x0000,
- 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x0005,
- 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0140, 0x6837,
- 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x510c, 0x00de,
- 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186,
- 0x0027, 0x0118, 0x080c, 0x80be, 0x0030, 0x080c, 0x6b73, 0x080c,
- 0x974e, 0x080c, 0x6c50, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6,
- 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100,
- 0x2130, 0x2069, 0xb298, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020,
- 0xaf90, 0x001d, 0x080c, 0x927f, 0xa6b2, 0x0020, 0x7804, 0xa06d,
- 0x0110, 0x080c, 0x1600, 0x080c, 0x15d9, 0x0500, 0x8528, 0x6837,
- 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228,
- 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009,
- 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f,
- 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f,
- 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6,
- 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c,
- 0x510c, 0x2f68, 0x0cb8, 0x080c, 0x510c, 0x00fe, 0x0005, 0x0156,
- 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007,
- 0x2012, 0x8318, 0x8210, 0x1f04, 0x9286, 0x015e, 0x0005, 0x0066,
- 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f,
- 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066,
- 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e,
- 0x0005, 0x92c3, 0x92c3, 0x92be, 0x92e5, 0x92b1, 0x92be, 0x92e5,
- 0x92be, 0x080c, 0x14f6, 0x0036, 0x2019, 0x0010, 0x080c, 0xa566,
- 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, 0x0005,
- 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, 0x684b,
- 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c,
- 0x51df, 0x080c, 0x9803, 0x080c, 0x510c, 0x080c, 0x8078, 0xa085,
- 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010,
- 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x92fc, 0x9319, 0x92fe, 0x9338,
- 0x9316, 0x92fc, 0x92be, 0x92c3, 0x92c3, 0x92be, 0x92be, 0x92be,
- 0x92be, 0x92be, 0x92be, 0x92be, 0x080c, 0x14f6, 0x86ff, 0x1198,
- 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x9803,
- 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c,
- 0x67a8, 0x080c, 0x6c50, 0xa085, 0x0001, 0x0005, 0x080c, 0x190b,
- 0x0c28, 0x00e6, 0x2071, 0xafc7, 0x7024, 0xac06, 0x1110, 0x080c,
- 0x79e1, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086,
- 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x7b9a, 0x009e, 0x008e,
- 0x0010, 0x080c, 0x78de, 0x00ee, 0x1948, 0x080c, 0x92be, 0x0005,
- 0x0036, 0x00e6, 0x2071, 0xafc7, 0x703c, 0xac06, 0x1140, 0x2019,
- 0x0000, 0x080c, 0x7a64, 0x00ee, 0x003e, 0x0804, 0x92fe, 0x080c,
- 0x7cb8, 0x00ee, 0x003e, 0x1904, 0x92fe, 0x080c, 0x92be, 0x0005,
- 0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9369,
- 0x93d3, 0x9501, 0x9374, 0x974e, 0x9369, 0xa558, 0x8078, 0x93d3,
- 0x9362, 0x955f, 0x080c, 0x14f6, 0x080c, 0x9789, 0x1110, 0x080c,
- 0x85f3, 0x0005, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x080c, 0x8078,
- 0x0005, 0x6017, 0x0001, 0x0005, 0x6010, 0xa080, 0x0019, 0x2c02,
- 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x938f,
- 0x9391, 0x93b1, 0x93c3, 0x93d0, 0x938f, 0x9369, 0x9369, 0x9369,
- 0x93c3, 0x93c3, 0x938f, 0x938f, 0x938f, 0x938f, 0x93cd, 0x080c,
- 0x14f6, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071,
- 0xafc7, 0x7024, 0xac06, 0x0190, 0x080c, 0x78de, 0x6007, 0x0085,
- 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xafa4, 0x2004, 0x6016,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x6017, 0x0001,
- 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de,
- 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068,
- 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005,
- 0x080c, 0x190b, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6,
- 0x000b, 0x0005, 0x93ea, 0x9371, 0x93ec, 0x93ea, 0x93ec, 0x93ec,
- 0x936a, 0x93ea, 0x9364, 0x9364, 0x93ea, 0x93ea, 0x93ea, 0x93ea,
- 0x93ea, 0x93ea, 0x080c, 0x14f6, 0x00d6, 0x6018, 0x2068, 0x6804,
- 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x14f6, 0x000b,
- 0x0005, 0x9405, 0x94a7, 0x9407, 0x9441, 0x9407, 0x9441, 0x9407,
- 0x9411, 0x9405, 0x9441, 0x9405, 0x942d, 0x080c, 0x14f6, 0x6004,
- 0xa08e, 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, 0x0002,
- 0x0558, 0x6004, 0x080c, 0x9789, 0x0904, 0x94c0, 0xa08e, 0x0021,
- 0x0904, 0x94c4, 0xa08e, 0x0022, 0x0904, 0x94c0, 0xa08e, 0x003d,
- 0x0904, 0x94c4, 0xa08e, 0x0039, 0x0904, 0x94c8, 0xa08e, 0x0035,
- 0x0904, 0x94c8, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150,
- 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086,
- 0x0006, 0x0110, 0x080c, 0x2ad9, 0x080c, 0x85f3, 0x080c, 0x974e,
- 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9498,
- 0xa186, 0x0002, 0x1518, 0x6018, 0x2068, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x1904, 0x94ea, 0x68a0, 0xd0bc, 0x1904, 0x94ea, 0x6840,
- 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000,
- 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x8022,
- 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce,
- 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004,
- 0xa086, 0x007e, 0x1170, 0x2009, 0xad34, 0x2104, 0xc085, 0x200a,
- 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x00ee, 0x080c, 0x85f3,
- 0x0020, 0x080c, 0x85f3, 0x080c, 0x2ad9, 0x00e6, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x2aff, 0x012e, 0x00ee, 0x080c, 0x974e, 0x0005,
- 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002,
- 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x0c80, 0x00c6,
- 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, 0x6840,
- 0xa084, 0x00ff, 0xa005, 0x0904, 0x946e, 0x8001, 0x6842, 0x6003,
- 0x0001, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x08b8,
- 0x080c, 0x85f3, 0x0804, 0x943e, 0x080c, 0x8621, 0x0804, 0x943e,
- 0x00d6, 0x2c68, 0x6104, 0x080c, 0x9a34, 0x00de, 0x0118, 0x080c,
- 0x8078, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105,
- 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038,
- 0x600a, 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c,
- 0x6c50, 0x0005, 0x00de, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x2ad9,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2aff, 0x6013, 0x0000,
- 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee,
- 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005,
- 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518,
- 0x9518, 0x9369, 0x9518, 0x9371, 0x951a, 0x9371, 0x9527, 0x9518,
- 0x080c, 0x14f6, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b,
- 0x6003, 0x000d, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0005, 0x080c,
- 0x9742, 0x080c, 0x9596, 0x0580, 0x080c, 0x2ad9, 0x00d6, 0x080c,
- 0x9596, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
- 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x510c, 0x2c68,
- 0x080c, 0x8022, 0x0150, 0x6818, 0x601a, 0x080c, 0x9956, 0x00c6,
- 0x2d60, 0x080c, 0x974e, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013,
- 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
- 0x67ee, 0x080c, 0x6c50, 0x0010, 0x080c, 0x974e, 0x0005, 0x6000,
- 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x9576, 0x9576,
- 0x9576, 0x9578, 0x9579, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576,
- 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x080c, 0x14f6,
- 0x0005, 0x080c, 0x7cb8, 0x190c, 0x14f6, 0x6110, 0x2168, 0x684b,
- 0x0006, 0x080c, 0x510c, 0x080c, 0x8078, 0x0005, 0xa284, 0x0007,
- 0x1158, 0xa282, 0xb400, 0x0240, 0x2001, 0xad16, 0x2004, 0xa202,
- 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210,
- 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006,
- 0x0126, 0x2091, 0x8000, 0x2061, 0xb400, 0x2071, 0xad00, 0x7344,
- 0x7064, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0x98e3,
- 0x0148, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x00c6, 0x080c,
- 0x8078, 0x00ce, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0c38,
- 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6,
- 0x0016, 0xa188, 0xae34, 0x210c, 0x81ff, 0x0170, 0x2061, 0xb400,
- 0x2071, 0xad00, 0x0016, 0x080c, 0x8022, 0x001e, 0x0138, 0x611a,
- 0x080c, 0x2ad9, 0x080c, 0x8078, 0xa006, 0x0010, 0xa085, 0x0001,
- 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091,
- 0x8000, 0x00c6, 0x080c, 0x8022, 0x005e, 0x0180, 0x6612, 0x651a,
- 0x080c, 0x9956, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x80a7,
- 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0,
- 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c,
- 0x8022, 0x005e, 0x0508, 0x6013, 0x0000, 0x651a, 0x080c, 0x9956,
- 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x4ecf, 0x00ce, 0x080c,
- 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c,
- 0xa712, 0x007e, 0x2009, 0x004c, 0x080c, 0x80a7, 0xa085, 0x0001,
- 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6,
- 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0180, 0x7e12,
- 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9683,
- 0x2f60, 0x2009, 0x004d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e,
- 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c,
- 0x8022, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f,
- 0x0003, 0x2021, 0x0005, 0x0439, 0x2f60, 0x2009, 0x004e, 0x080c,
- 0x80a7, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6,
- 0x00c6, 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0178,
- 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x0059,
- 0x2f60, 0x2009, 0x0052, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e,
- 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x4e71, 0x0118, 0x2001, 0x9688, 0x0028, 0x080c, 0x4e43,
- 0x0158, 0x2001, 0x968e, 0x0006, 0xa00e, 0x2400, 0x080c, 0x51df,
- 0x080c, 0x510c, 0x000e, 0x0807, 0x2418, 0x080c, 0x6b15, 0x62a0,
- 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6900,
- 0x008e, 0x080c, 0x681d, 0x2f08, 0x2648, 0x080c, 0xa712, 0x613c,
- 0x81ff, 0x090c, 0x69a9, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6,
- 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188,
- 0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012,
- 0x2009, 0x001f, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce,
- 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
- 0x080c, 0x8022, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0x9956,
- 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x80a7,
- 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6,
- 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188,
- 0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012,
- 0x2009, 0x003d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce,
- 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
- 0x080c, 0x9807, 0x001e, 0x0180, 0x611a, 0x080c, 0x9956, 0x601f,
- 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x80a7, 0xa085,
- 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
- 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188, 0x660a,
- 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009,
- 0x0044, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
- 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff,
- 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000,
- 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001,
- 0xafa3, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004,
- 0x6016, 0x080c, 0xabb4, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066,
- 0x00c6, 0x00d6, 0x2031, 0xad52, 0x2634, 0xd6e4, 0x0128, 0x6618,
- 0x2660, 0x6e48, 0x080c, 0x4dfc, 0x00de, 0x00ce, 0x006e, 0x0005,
- 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003,
- 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e,
- 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086,
- 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085,
- 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000,
- 0x00c6, 0x080c, 0x8022, 0x001e, 0x0190, 0x611a, 0x080c, 0x9956,
- 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2ad9, 0x2009, 0x0028,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
- 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xad20, 0x2204, 0xa086,
- 0x0074, 0x1148, 0x080c, 0x8943, 0x6003, 0x0001, 0x6007, 0x0029,
- 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005,
- 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4c30, 0x00e8,
- 0xa186, 0x0015, 0x11e8, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014,
- 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x4d72, 0x00de, 0x080c,
- 0x89f7, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005,
- 0x0138, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x81f6, 0x0020,
- 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005, 0x6848, 0xa086, 0x0005,
- 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6,
- 0x0126, 0x2071, 0xad00, 0x2091, 0x8000, 0x7544, 0xa582, 0x0001,
- 0x0608, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0,
- 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98,
- 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502,
- 0x1230, 0x754a, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704b,
- 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb28c, 0x7014,
- 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x00c6, 0x00f6,
- 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f,
- 0x0013, 0x00ce, 0x0005, 0x9369, 0x985e, 0x9861, 0x9864, 0xa9a7,
- 0xa9c2, 0xa9c5, 0x9369, 0x9369, 0x080c, 0x14f6, 0xe000, 0xe000,
- 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78,
- 0x080c, 0x5029, 0x0538, 0x080c, 0x8022, 0x1128, 0x2001, 0xafa5,
- 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0x9956, 0x781c,
- 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020,
- 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007,
- 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x67a8, 0x080c,
- 0x6c50, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032,
- 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a,
- 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078,
- 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834,
- 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036,
- 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001,
- 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x67a8, 0x6803, 0x0002,
- 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x1118,
- 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022,
- 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x190b,
- 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034,
- 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e,
- 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140,
- 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001,
- 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6,
- 0x2001, 0xaf9f, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c,
- 0x6665, 0x2001, 0xafa3, 0x82ff, 0x1110, 0x2011, 0x0002, 0x2202,
- 0x2001, 0xafa1, 0x200c, 0x8000, 0x2014, 0x2071, 0xaf8d, 0x711a,
- 0x721e, 0x2001, 0x0064, 0x080c, 0x6665, 0x2001, 0xafa4, 0x82ff,
- 0x1110, 0x2011, 0x0002, 0x2202, 0x2009, 0xafa5, 0xa280, 0x000a,
- 0x200a, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006,
- 0x00e6, 0x2001, 0xafa3, 0x2003, 0x0028, 0x2001, 0xafa4, 0x2003,
- 0x0014, 0x2071, 0xaf8d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001,
- 0xafa5, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054,
- 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00de, 0x0005, 0x0005, 0x00c6,
- 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0178,
- 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
- 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015,
- 0x1500, 0x7080, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c,
- 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x6e05, 0x01d8, 0x706c, 0x6a50,
- 0xa206, 0x1160, 0x7070, 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290,
- 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2b1e, 0x080c, 0x81f6,
- 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de,
- 0x0005, 0x7050, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126,
- 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0180, 0x611a,
- 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
- 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015,
- 0x11c0, 0x7080, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f,
- 0x2c78, 0x080c, 0x6e05, 0x01a8, 0x706c, 0x6a08, 0xa206, 0x1130,
- 0x7070, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2ad9, 0x080c, 0x81f6,
- 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de,
- 0x0005, 0x7050, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026,
- 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150,
- 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e,
- 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310,
- 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x1188, 0x00c6, 0x6318,
- 0x2360, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108, 0xc185, 0x6000,
- 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66,
- 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6,
- 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c,
- 0x510c, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186,
- 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9586, 0x01f0,
- 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190,
- 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834,
- 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018,
- 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001,
- 0x0cc8, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013,
- 0x006e, 0x0005, 0x9a7a, 0x9eff, 0xa027, 0x9a7a, 0x9a7a, 0x9a7a,
- 0x9a7a, 0x9a7a, 0x9ab2, 0xa0a3, 0x9a7a, 0x9a7a, 0x9a7a, 0x9a7a,
- 0x9a7a, 0x9a7a, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010,
- 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x9a95, 0xa4fd, 0x9a95,
- 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0xa4c1, 0xa545, 0x9a95,
- 0xaaea, 0xab1a, 0xaaea, 0xab1a, 0x9a95, 0x080c, 0x14f6, 0x0066,
- 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005,
- 0x9ab0, 0xa1d8, 0xa295, 0xa2c2, 0xa346, 0x9ab0, 0xa433, 0xa3de,
- 0xa0af, 0xa497, 0xa4ac, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0,
- 0x080c, 0x14f6, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0x2100, 0xa1b2,
- 0x0040, 0x1a04, 0x9e79, 0x0002, 0x9afc, 0x9cab, 0x9afc, 0x9afc,
- 0x9afc, 0x9cb2, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc,
- 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc,
- 0x9afc, 0x9afc, 0x9afc, 0x9afe, 0x9b5a, 0x9b65, 0x9ba6, 0x9bc0,
- 0x9c3e, 0x9c9c, 0x9afc, 0x9afc, 0x9cb5, 0x9afc, 0x9afc, 0x9cc4,
- 0x9ccb, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9d42, 0x9afc,
- 0x9afc, 0x9d4d, 0x9afc, 0x9afc, 0x9d18, 0x9afc, 0x9afc, 0x9afc,
- 0x9d61, 0x9afc, 0x9afc, 0x9afc, 0x9dd5, 0x9afc, 0x9afc, 0x9afc,
- 0x9afc, 0x9afc, 0x9afc, 0x9e40, 0x080c, 0x14f6, 0x080c, 0x502d,
- 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
- 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804,
- 0x9ca6, 0x080c, 0x501d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016,
- 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7,
- 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712,
- 0x007e, 0x001e, 0x2e60, 0x080c, 0x4ecf, 0x001e, 0x002e, 0x003e,
- 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4ceb, 0x00ce,
- 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278,
- 0x080c, 0xa656, 0x1904, 0x9ba0, 0x080c, 0xa5f6, 0x1120, 0x6007,
- 0x0008, 0x0804, 0x9ca6, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c,
- 0xa801, 0x0128, 0x080c, 0xa656, 0x0d78, 0x0804, 0x9ba0, 0x6013,
- 0x1900, 0x0c88, 0x6106, 0x080c, 0xa5a6, 0x6007, 0x0006, 0x0804,
- 0x9ca6, 0x6007, 0x0007, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904,
- 0x9e76, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637,
- 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4,
- 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686,
- 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xa6b4, 0x11a0, 0xa686,
- 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
- 0x0000, 0x080c, 0x2b1e, 0x002e, 0x080c, 0x4d72, 0x6007, 0x000a,
- 0x00de, 0x0804, 0x9ca6, 0x6007, 0x000b, 0x00de, 0x0804, 0x9ca6,
- 0x080c, 0x2ad9, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x080c, 0xab4e,
- 0x1904, 0x9e76, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686,
- 0x0707, 0x0d70, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
- 0x0000, 0x080c, 0x2b1e, 0x002e, 0x6007, 0x000c, 0x0804, 0x9ca6,
- 0x080c, 0x502d, 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009,
- 0xa086, 0x0008, 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618,
- 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8,
- 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x002e, 0x0050,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006,
- 0x1904, 0x9ba0, 0x080c, 0xa6c1, 0x1120, 0x6007, 0x000e, 0x0804,
- 0x9ca6, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff,
- 0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009,
- 0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c,
- 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e,
- 0x004e, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x2001, 0x0001, 0x080c,
- 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
- 0xad05, 0x2011, 0xb290, 0x080c, 0x8a7c, 0x003e, 0x002e, 0x001e,
- 0x015e, 0xa005, 0x0168, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004,
- 0x0a04, 0x9ba0, 0xa682, 0x0007, 0x0a04, 0x9bea, 0x0804, 0x9ba0,
- 0x6013, 0x1900, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c, 0x502d,
- 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
- 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618, 0xa6b0, 0x0001,
- 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06b0, 0xa6b4, 0xff00,
- 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x9ba0,
- 0x080c, 0xa6e9, 0x1130, 0x080c, 0xa5f6, 0x1118, 0x6007, 0x0010,
- 0x04e8, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff,
- 0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009,
- 0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c,
- 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e,
- 0x004e, 0x6007, 0x0001, 0x00d0, 0x080c, 0xa801, 0x0140, 0xa6b4,
- 0xff00, 0x8637, 0xa686, 0x0006, 0x0958, 0x0804, 0x9ba0, 0x6013,
- 0x1900, 0x6007, 0x0009, 0x0050, 0x080c, 0xab4e, 0x1904, 0x9e76,
- 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0012, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
- 0x67ee, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xab4e, 0x1904,
- 0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0020, 0x6003,
- 0x0001, 0x080c, 0x67ee, 0x0005, 0x6007, 0x0023, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x0005, 0x080c, 0xab4e, 0x1904, 0x9e76, 0x080c,
- 0x9e98, 0x1904, 0x9ba0, 0x0016, 0x0026, 0x2011, 0xb291, 0x2214,
- 0xa286, 0xffff, 0x0190, 0x2c08, 0x080c, 0x9586, 0x01d8, 0x2260,
- 0x2011, 0xb290, 0x2214, 0x6008, 0xa206, 0x11a0, 0x6018, 0xa190,
- 0x0006, 0x2214, 0xa206, 0x01e0, 0x0068, 0x2011, 0xb290, 0x2214,
- 0x2c08, 0x080c, 0xa940, 0x11a0, 0x2011, 0xb291, 0x2214, 0xa286,
- 0xffff, 0x01a0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011,
- 0xb289, 0x2214, 0xa296, 0xffff, 0x1160, 0x6007, 0x0025, 0x0048,
- 0x601c, 0xa086, 0x0007, 0x1d70, 0x080c, 0x8078, 0x2160, 0x6007,
- 0x0025, 0x6003, 0x0001, 0x080c, 0x67ee, 0x002e, 0x001e, 0x0005,
- 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036,
- 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c, 0x8a7c,
- 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804,
- 0x9ca6, 0x080c, 0x87bd, 0x080c, 0x574f, 0x1158, 0x0006, 0x0026,
- 0x0036, 0x080c, 0x576b, 0x0110, 0x080c, 0x5726, 0x003e, 0x002e,
- 0x000e, 0x0005, 0x6106, 0x080c, 0x9eb4, 0x6007, 0x002b, 0x0804,
- 0x9ca6, 0x6007, 0x002c, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904,
- 0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6106, 0x080c, 0x9eb8,
- 0x1120, 0x6007, 0x002e, 0x0804, 0x9ca6, 0x6007, 0x002f, 0x0804,
- 0x9ca6, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c,
- 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007,
- 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0x9cab,
- 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904, 0x9dd2, 0x2071, 0xb28c,
- 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xad52,
- 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118,
- 0x6814, 0xa206, 0x01f8, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1580,
- 0x2069, 0xad00, 0x6870, 0xa206, 0x1558, 0x686c, 0xa106, 0x1540,
- 0x7210, 0x080c, 0x9586, 0x0548, 0x080c, 0xa9d4, 0x0530, 0x622a,
- 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x67a8, 0x00ce, 0x00de,
- 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0x9586,
- 0x01a0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1170, 0x0c08,
- 0x7210, 0x2c08, 0x080c, 0xa940, 0x2c10, 0x2160, 0x0130, 0x08c8,
- 0x6007, 0x0037, 0x6013, 0x1500, 0x08e8, 0x6007, 0x0037, 0x6013,
- 0x1700, 0x08c0, 0x6007, 0x0012, 0x08a8, 0x6018, 0xa080, 0x0001,
- 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0x9cab,
- 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904,
- 0x9e38, 0x2069, 0xad00, 0x2071, 0xb28c, 0x7008, 0x6036, 0x720c,
- 0x623a, 0xa286, 0xffff, 0x1140, 0x7208, 0x00c6, 0x2c08, 0x080c,
- 0xa940, 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9586, 0x0570, 0x00c6,
- 0x0026, 0x2260, 0x080c, 0x928f, 0x002e, 0x00ce, 0x7118, 0xa18c,
- 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118,
- 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150,
- 0x0056, 0x7510, 0x7614, 0x080c, 0xa9eb, 0x005e, 0x00ce, 0x00de,
- 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00,
- 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c88, 0x6007, 0x003b, 0x602b,
- 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c30,
- 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0x9daa,
- 0x00e6, 0x0026, 0x080c, 0x502d, 0x0558, 0x080c, 0x501d, 0x080c,
- 0xabc5, 0x1520, 0x2071, 0xad00, 0x70d0, 0xc085, 0x70d2, 0x00f6,
- 0x2079, 0x0100, 0x729c, 0xa284, 0x00ff, 0x706e, 0x78e6, 0xa284,
- 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, 0x00fe, 0x70db, 0x0000,
- 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xafe0, 0x2013,
- 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x28fa, 0x0010, 0x080c, 0xabf1,
- 0x002e, 0x00ee, 0x080c, 0x8078, 0x0804, 0x9caa, 0x080c, 0x8078,
- 0x0005, 0x2600, 0x0002, 0x9e81, 0x9e81, 0x9e81, 0x9e81, 0x9e81,
- 0x9e83, 0x080c, 0x14f6, 0x080c, 0xab4e, 0x1d80, 0x0089, 0x1138,
- 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005, 0x080c,
- 0x2ad9, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005,
- 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637,
- 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4,
- 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085,
- 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005,
- 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084,
- 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009,
- 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824,
- 0x080c, 0x2676, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2b1e,
- 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069,
- 0xb28d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085,
- 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xb28c,
- 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084,
- 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004,
- 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x1130, 0x2008,
- 0xa1b2, 0x0040, 0x1a04, 0x9ffb, 0x0092, 0xa1b6, 0x0027, 0x0120,
- 0xa1b6, 0x0014, 0x190c, 0x14f6, 0x2001, 0x0007, 0x080c, 0x4c5d,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x9f5f,
- 0x9f61, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f6f, 0x9ff4, 0x9fbf,
- 0x9ff4, 0x9fd0, 0x9ff4, 0x9f6f, 0x9ff4, 0x9fec, 0x9ff4, 0x9fec,
- 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f,
- 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f5f, 0x9ff4,
- 0x9f5f, 0x9f5f, 0x9ff4, 0x9f5f, 0x9ff1, 0x9ff4, 0x9f5f, 0x9f5f,
- 0x9f5f, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f,
- 0x9f69, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9ff0, 0x9ff4, 0x9f5f,
- 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x080c,
- 0x14f6, 0x080c, 0x6b73, 0x6003, 0x0002, 0x080c, 0x6c50, 0x0804,
- 0x9ffa, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x0804, 0x9ff4, 0x00f6,
- 0x2079, 0xad51, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0x9ff4, 0x2001,
- 0x0000, 0x080c, 0x4c1e, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086,
- 0x00ff, 0x1140, 0x00f6, 0x2079, 0xad00, 0x7894, 0x8000, 0x7896,
- 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140,
- 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, 0x3cce, 0x0804, 0x9ff4,
- 0x00ce, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6,
- 0x2079, 0xad00, 0x7894, 0x8000, 0x7896, 0x00fe, 0x2001, 0x0002,
- 0x080c, 0x4c30, 0x080c, 0x6b73, 0x601f, 0x0001, 0x6003, 0x0001,
- 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00c6, 0x6118,
- 0x2160, 0x2009, 0x0001, 0x080c, 0x6519, 0x00ce, 0x04d8, 0x6618,
- 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0006, 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410,
- 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3cce,
- 0x2001, 0x0006, 0x0489, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006,
- 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x00e9, 0x0020,
- 0x0018, 0x0010, 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x8078,
- 0x080c, 0x6c50, 0x0005, 0x2600, 0x0002, 0xa003, 0xa003, 0xa003,
- 0xa003, 0xa003, 0xa005, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x080c,
- 0x8078, 0x080c, 0x6c50, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168,
- 0x6900, 0xd184, 0x0188, 0x6104, 0xa18e, 0x000a, 0x1128, 0x699c,
- 0xd1a4, 0x1110, 0x2001, 0x0007, 0x080c, 0x4c30, 0x2001, 0x0000,
- 0x080c, 0x4c1e, 0x080c, 0x2aff, 0x00de, 0x001e, 0x0005, 0x00d6,
- 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2,
- 0x000c, 0x1a0c, 0x14f6, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028,
- 0xa1b6, 0x0016, 0x190c, 0x14f6, 0x006b, 0x0005, 0x86b9, 0x86b9,
- 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0xa08f, 0xa056, 0x86b9, 0x86b9,
- 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9,
- 0xa08f, 0xa096, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x00f6, 0x2079,
- 0xad51, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800,
- 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c,
- 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x601f, 0x0001, 0x6003,
- 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00a8,
- 0x2011, 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1168,
- 0x00c6, 0x080c, 0x4cdc, 0x0120, 0x00ce, 0x080c, 0x8078, 0x0028,
- 0x080c, 0x493a, 0x00ce, 0x080c, 0x8078, 0x00fe, 0x0005, 0x6604,
- 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8078, 0x0005, 0x080c, 0x8940,
- 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010,
- 0x080c, 0x8078, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa182,
- 0x0040, 0x0002, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c7, 0xa0c5,
- 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5,
- 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0x080c, 0x14f6, 0x00d6,
- 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002b,
- 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xab96, 0x6106,
- 0x2071, 0xb280, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa129, 0xa486,
- 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x663f,
- 0x080c, 0x15d9, 0x090c, 0x14f6, 0x6003, 0x0007, 0x2d00, 0x6837,
- 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e,
- 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a,
- 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036,
- 0x080c, 0x510c, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, 0x0017,
- 0x080c, 0xa8eb, 0x0804, 0xa186, 0xa486, 0x0400, 0x1130, 0x2019,
- 0x0002, 0x080c, 0xa89d, 0x0804, 0xa186, 0xa486, 0x0200, 0x1110,
- 0x080c, 0xa882, 0xa486, 0x1000, 0x1110, 0x080c, 0xa8d0, 0x0804,
- 0xa186, 0x2069, 0xb048, 0x6a00, 0xd284, 0x0904, 0xa1d5, 0xa284,
- 0x0300, 0x1904, 0xa1cf, 0x6804, 0xa005, 0x0904, 0xa1c0, 0x2d78,
- 0x6003, 0x0007, 0x080c, 0x15c0, 0x0904, 0xa18d, 0x7800, 0xd08c,
- 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000,
- 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a,
- 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x7928,
- 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, 0x6853,
- 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, 0x684f,
- 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, 0x0010,
- 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xb290, 0xad90, 0x0015,
- 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xa178, 0x200c,
- 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x510c, 0x002e, 0x004e,
- 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100, 0x6003,
- 0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c70,
- 0x2069, 0xb292, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8,
- 0x2069, 0xb280, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c,
- 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0888, 0x6013, 0x0200, 0x6003,
- 0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0830,
- 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007,
- 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0804, 0xa186, 0x6013,
- 0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200, 0x0800,
- 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x14f6,
- 0xa08a, 0x0053, 0x1a0c, 0x14f6, 0xa082, 0x0040, 0x2008, 0x0804,
- 0xa252, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004,
- 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0,
- 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699,
- 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, 0x1170,
- 0x0804, 0xa295, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c,
- 0x14f6, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, 0x80be,
- 0x0005, 0xa22c, 0xa22e, 0xa22e, 0xa22c, 0xa22c, 0xa22c, 0xa22c,
- 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c,
- 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0x080c, 0x14f6, 0x080c, 0x6b73,
- 0x080c, 0x6c50, 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84,
- 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178,
- 0x2019, 0x0004, 0x080c, 0xa91f, 0x6013, 0x0000, 0x6014, 0xa005,
- 0x1120, 0x2001, 0xafa4, 0x2004, 0x6016, 0x6003, 0x0007, 0x00de,
- 0x003e, 0x0005, 0x0002, 0xa266, 0xa283, 0xa26f, 0xa28f, 0xa266,
- 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266,
- 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0x080c, 0x14f6,
- 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x080c,
- 0x6b73, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003,
- 0x0007, 0x2009, 0x0043, 0x080c, 0x80a7, 0x0010, 0x6003, 0x0002,
- 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73, 0x080c, 0xab55, 0x1120,
- 0x080c, 0x6618, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c,
- 0x6b73, 0x2009, 0x0041, 0x0804, 0xa3de, 0xa182, 0x0040, 0x0002,
- 0xa2ab, 0xa2ad, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ae,
- 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab,
- 0xa2ab, 0xa2b9, 0xa2ab, 0x080c, 0x14f6, 0x0005, 0x6003, 0x0004,
- 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824,
- 0x0005, 0x00d6, 0x080c, 0x6618, 0x00de, 0x080c, 0xabb4, 0x080c,
- 0x8078, 0x0005, 0xa182, 0x0040, 0x0002, 0xa2d8, 0xa2d8, 0xa2d8,
- 0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa2da, 0xa2d8, 0xa2dd, 0xa316,
- 0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa316, 0xa2d8, 0xa2d8, 0xa2d8,
- 0x080c, 0x14f6, 0x080c, 0x80be, 0x0005, 0x2001, 0xad71, 0x2004,
- 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0228,
- 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, 0x080c,
- 0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc,
- 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041,
- 0x00de, 0x0804, 0xa3de, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c,
- 0x6618, 0x00de, 0x0005, 0x080c, 0xab55, 0x0110, 0x00de, 0x0005,
- 0x080c, 0x6618, 0x080c, 0x8078, 0x00de, 0x0ca0, 0x0036, 0x080c,
- 0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004,
- 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0140,
- 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a,
- 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xa91f, 0x6014,
- 0xa005, 0x1128, 0x2001, 0xafa4, 0x2004, 0x8003, 0x6016, 0x6013,
- 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013,
- 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x080c, 0x6b73,
- 0x080c, 0x6c50, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014,
- 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x2001, 0x0007,
- 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50,
- 0x0005, 0xa182, 0x0040, 0x0002, 0xa37f, 0xa37f, 0xa37f, 0xa37f,
- 0xa37f, 0xa37f, 0xa37f, 0xa381, 0xa38d, 0xa37f, 0xa37f, 0xa37f,
- 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0x080c,
- 0x14f6, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
- 0x080c, 0x1824, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068,
- 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80,
- 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a,
- 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120,
- 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, 0x0000,
- 0x080c, 0x6618, 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c,
- 0x5029, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, 0x0005,
- 0x2009, 0xad0d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010,
- 0x6003, 0x0006, 0x0021, 0x080c, 0x661a, 0x00de, 0x0005, 0xd2fc,
- 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009,
- 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040,
- 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, 0x190c,
- 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005, 0xa401, 0xa408,
- 0xa414, 0xa420, 0xa401, 0xa401, 0xa401, 0xa42f, 0xa401, 0xa403,
- 0xa403, 0xa401, 0xa401, 0xa401, 0xa401, 0xa403, 0xa401, 0xa403,
- 0xa401, 0x080c, 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005,
- 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x6c50, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c,
- 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005,
- 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x680b, 0x080c, 0x6d0d, 0x012e, 0x0005, 0xa016,
- 0x080c, 0x1824, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6,
- 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, 0xa44f,
- 0xa451, 0xa463, 0xa47e, 0xa44f, 0xa44f, 0xa44f, 0xa493, 0xa44f,
- 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0x080c,
- 0x14f6, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003,
- 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168,
- 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0408, 0x6013, 0x0000, 0x6017,
- 0x0000, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00c0, 0x6010, 0x2068,
- 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68,
- 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b,
- 0x080c, 0x6d0d, 0x0018, 0xa016, 0x080c, 0x1824, 0x0005, 0x080c,
- 0x6b73, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa,
- 0x0036, 0x2019, 0x0029, 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c,
- 0x974e, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6c05, 0x6110, 0x81ff,
- 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa, 0x0036, 0x2019, 0x0029,
- 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c, 0x974e, 0x080c, 0x6d0d,
- 0x0005, 0xa182, 0x0085, 0x0002, 0xa4cd, 0xa4cb, 0xa4cb, 0xa4d9,
- 0xa4cb, 0xa4cb, 0xa4cb, 0x080c, 0x14f6, 0x6003, 0x000b, 0x6106,
- 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e,
- 0x0005, 0x0026, 0x00e6, 0x080c, 0xab4e, 0x0118, 0x080c, 0x8078,
- 0x00c8, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0xa7ce,
- 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296,
- 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160,
- 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c,
- 0x14f6, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186,
- 0x0014, 0x0118, 0x080c, 0x80be, 0x0050, 0x2001, 0x0007, 0x080c,
- 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
- 0xa527, 0xa529, 0xa529, 0xa527, 0xa527, 0xa527, 0xa527, 0x080c,
- 0x14f6, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
- 0xa182, 0x0085, 0x0a0c, 0x14f6, 0xa182, 0x008c, 0x1a0c, 0x14f6,
- 0xa182, 0x0085, 0x0002, 0xa542, 0xa542, 0xa542, 0xa544, 0xa542,
- 0xa542, 0xa542, 0x080c, 0x14f6, 0x0005, 0xa186, 0x0013, 0x0148,
- 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x80be,
- 0x0030, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
- 0x0036, 0x080c, 0xabb4, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031,
- 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036,
- 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c,
- 0x7b9a, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x7c34,
- 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086,
- 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c,
- 0xabb4, 0x601f, 0x0007, 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c,
- 0x190b, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f,
- 0x00de, 0x6013, 0x0000, 0x080c, 0xabb4, 0x601f, 0x0007, 0x2001,
- 0xafa3, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6,
- 0x0036, 0x0156, 0x2079, 0xb280, 0x7938, 0x783c, 0x080c, 0x2676,
- 0x1904, 0xa5f1, 0x0016, 0x00c6, 0x080c, 0x4cdc, 0x15c0, 0x2011,
- 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1578,
- 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x7cf4,
- 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x007e,
- 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, 0xa712, 0x007e, 0x080c,
- 0x4ecf, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
- 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2b87, 0x002e,
- 0x001e, 0x080c, 0x493a, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce,
- 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6,
- 0x00e6, 0x0016, 0x2009, 0xad20, 0x2104, 0xa086, 0x0074, 0x1904,
- 0xa64b, 0x2069, 0xb28e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908,
- 0xa184, 0x8000, 0x05e8, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x1160,
- 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4,
- 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610,
- 0x6914, 0x2069, 0xb2ae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182,
- 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001,
- 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100,
- 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013,
- 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028,
- 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008,
- 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6,
- 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff,
- 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00,
- 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6,
- 0x2d60, 0x080c, 0x4ceb, 0x00ce, 0x04c0, 0x2011, 0xb296, 0xad98,
- 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1580, 0x2011, 0xb29a,
- 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1538, 0x0046,
- 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xad52,
- 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6800,
- 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039,
- 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x2001,
- 0x0007, 0x080c, 0x4c5d, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e,
- 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xb28e, 0x6800,
- 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de,
- 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079,
- 0xb28c, 0x7930, 0x7834, 0x080c, 0x2676, 0x11a0, 0x080c, 0x4cdc,
- 0x1188, 0x2011, 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c,
- 0x8a7c, 0x1140, 0x2011, 0xb294, 0xac98, 0x0006, 0x20a9, 0x0004,
- 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce,
- 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011,
- 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x11a0, 0x080c,
- 0x4cdc, 0x1188, 0x2011, 0xb296, 0xac98, 0x000a, 0x20a9, 0x0004,
- 0x080c, 0x8a7c, 0x1140, 0x2011, 0xb29a, 0xac98, 0x0006, 0x20a9,
- 0x0004, 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e,
- 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056,
- 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xafd0,
- 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400, 0x2071, 0xad00,
- 0x7644, 0x7064, 0x81ff, 0x0128, 0x8001, 0xa602, 0x1a04, 0xa78e,
- 0x0018, 0xa606, 0x0904, 0xa78e, 0x2100, 0xac06, 0x0904, 0xa785,
- 0x080c, 0xa990, 0x0904, 0xa785, 0x671c, 0xa786, 0x0001, 0x0904,
- 0xa7a5, 0xa786, 0x0004, 0x0904, 0xa7a5, 0xa786, 0x0007, 0x05e8,
- 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, 0xa9a0,
- 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000,
- 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x190b, 0x001e, 0xa786,
- 0x0008, 0x1148, 0x080c, 0x9789, 0x1130, 0x080c, 0x85f3, 0x00de,
- 0x080c, 0x974e, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0190,
- 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
- 0x080c, 0xabfa, 0x0016, 0x080c, 0x97fd, 0x080c, 0x510c, 0x001e,
- 0x080c, 0x9742, 0x00de, 0x080c, 0x974e, 0xace0, 0x0018, 0x2001,
- 0xad16, 0x2004, 0xac02, 0x1210, 0x0804, 0xa726, 0x012e, 0x002e,
- 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005,
- 0xa786, 0x0006, 0x19c0, 0xa386, 0x0005, 0x0128, 0x080c, 0xabfa,
- 0x080c, 0xa91f, 0x08f8, 0x00de, 0x0c00, 0x080c, 0xa9a0, 0x19e8,
- 0x81ff, 0x09d8, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x0130,
- 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1978, 0x6000, 0xa086,
- 0x0002, 0x1958, 0x080c, 0x9778, 0x0130, 0x080c, 0x9789, 0x1928,
- 0x080c, 0x85f3, 0x0038, 0x080c, 0x2aff, 0x080c, 0x9789, 0x1110,
- 0x080c, 0x85f3, 0x080c, 0x974e, 0x0804, 0xa785, 0x00c6, 0x00e6,
- 0x0016, 0x2c08, 0x2170, 0x080c, 0xa940, 0x001e, 0x0120, 0x601c,
- 0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xa7e6, 0xa7e6,
- 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e8, 0xa7e6, 0xa006, 0x0005,
- 0x0046, 0x0016, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff,
- 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, 0xa96c, 0x001e, 0x004e,
- 0x0036, 0x2019, 0x0002, 0x080c, 0xa566, 0x003e, 0xa085, 0x0001,
- 0x0005, 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026,
- 0x0036, 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c,
- 0x8a7c, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6,
- 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091,
- 0x8000, 0x2740, 0x2061, 0xb400, 0x2079, 0x0001, 0x8fff, 0x0904,
- 0xa875, 0x2071, 0xad00, 0x7644, 0x7064, 0x8001, 0xa602, 0x1a04,
- 0xa875, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000,
- 0x080c, 0xa990, 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786,
- 0x0006, 0x1550, 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018,
- 0xa206, 0x1510, 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6,
- 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xabb4, 0x601f, 0x0007,
- 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c, 0x190b, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x0120, 0x0046, 0x080c, 0xa91f, 0x004e, 0x00de,
- 0x080c, 0x974e, 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xad16,
- 0x2004, 0xac02, 0x1210, 0x0804, 0xa826, 0xa006, 0x012e, 0x002e,
- 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5,
- 0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029,
- 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000,
- 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34,
- 0x080c, 0xa817, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056,
- 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009,
- 0x0000, 0x0016, 0x0036, 0x080c, 0x4cdc, 0x11b0, 0x2c10, 0x0056,
- 0x0086, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049,
- 0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c,
- 0x7c34, 0x080c, 0xa817, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04,
- 0xa8a9, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005,
- 0x0076, 0x0056, 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001,
- 0x2019, 0x0048, 0x0096, 0x2049, 0x0000, 0x080c, 0x7b9a, 0x009e,
- 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34, 0x2c20, 0x080c, 0xa817,
- 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6,
- 0x0156, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036,
- 0x080c, 0x4cdc, 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828,
- 0x0046, 0x2021, 0x0001, 0x080c, 0xab96, 0x004e, 0x0096, 0x2049,
- 0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c,
- 0x7c34, 0x080c, 0xa817, 0x003e, 0x001e, 0x8108, 0x1f04, 0xa8f6,
- 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016,
- 0x00f6, 0x3800, 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82,
- 0xad00, 0x0230, 0xad82, 0xe400, 0x0280, 0xad82, 0xffff, 0x1268,
- 0x6800, 0xa07d, 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x510c,
- 0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x510c, 0x00fe, 0x001e, 0x0005,
- 0x00e6, 0x0046, 0x0036, 0x2061, 0xb400, 0x2071, 0xad00, 0x7444,
- 0x7064, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000,
- 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0,
- 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xad16,
- 0x2004, 0xac02, 0x1220, 0x0c08, 0xa085, 0x0001, 0x0008, 0xa006,
- 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15d9,
- 0x000e, 0x090c, 0x14f6, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010,
- 0x080c, 0x9586, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014,
- 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006,
- 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x510c, 0x00de, 0x0005,
- 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, 0x0140, 0xa786,
- 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, 0x0001, 0x0005,
- 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005, 0x0016,
- 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, 0x6130, 0xa18c, 0x00ff,
- 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005,
- 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c, 0x6c50,
- 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, 0x6020, 0xd0e4, 0x0158,
- 0xd0cc, 0x0118, 0x080c, 0x9866, 0x0030, 0x080c, 0xabb4, 0x080c,
- 0x6618, 0x080c, 0x8078, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084,
- 0x000f, 0x0002, 0xa9e3, 0xa9e3, 0xa9e3, 0xa9e8, 0xa9e3, 0xa9e5,
- 0xa9e5, 0xa9e3, 0xa9e5, 0xa006, 0x0005, 0x00c6, 0x2260, 0x00ce,
- 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f,
- 0x0002, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xaa05,
- 0xa9fa, 0xa9fa, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00,
- 0x6003, 0x0001, 0x080c, 0x67a8, 0x0005, 0x00c6, 0x2260, 0x080c,
- 0xabb4, 0x603f, 0x0000, 0x6020, 0xc0f4, 0xc0cc, 0x6022, 0x6037,
- 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, 0x0007, 0x1904, 0xaa60,
- 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x1110,
- 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002, 0x1904,
- 0xaae7, 0x6010, 0xa005, 0x1138, 0x6000, 0xa086, 0x0007, 0x190c,
- 0x14f6, 0x0804, 0xaae7, 0xa08c, 0xf000, 0x1130, 0x0028, 0x2068,
- 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084,
- 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, 0x2068, 0x684c, 0xc0dc,
- 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043,
- 0x080c, 0xa3de, 0x0804, 0xaae7, 0x2009, 0x0041, 0x0804, 0xaae1,
- 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc,
- 0x1118, 0x00de, 0x0804, 0xa9fa, 0xd0b4, 0x0128, 0xd0fc, 0x090c,
- 0x14f6, 0x0804, 0xaa18, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c,
- 0x67a8, 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002,
- 0x0120, 0xa186, 0x0004, 0x1904, 0xaae7, 0x2071, 0xaffd, 0x7000,
- 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, 0x1110, 0x7003, 0x0000,
- 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000,
- 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0804,
- 0xaae1, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x15d9, 0x003e, 0x090c,
- 0x14f6, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b,
- 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872,
- 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, 0xa080, 0x0028, 0x2004,
- 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, 0x6846, 0x684f, 0x0000,
- 0x6d6a, 0x6e66, 0x686f, 0x0001, 0x080c, 0x510c, 0x2019, 0x0045,
- 0x6008, 0x2068, 0x080c, 0xa566, 0x2d00, 0x600a, 0x601f, 0x0006,
- 0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e,
- 0x0038, 0x603f, 0x0000, 0x6003, 0x0007, 0x080c, 0xa3de, 0x00ce,
- 0x00de, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085,
- 0x2008, 0x00c2, 0xa186, 0x0027, 0x1178, 0x080c, 0x6b73, 0x0036,
- 0x00d6, 0x6010, 0x2068, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00de,
- 0x003e, 0x080c, 0x6c50, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c,
- 0x80be, 0x0005, 0xab13, 0xab11, 0xab11, 0xab11, 0xab11, 0xab11,
- 0xab13, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x6003, 0x000c, 0x080c,
- 0x6c50, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208,
- 0x001a, 0x080c, 0x80be, 0x0005, 0xab2b, 0xab2b, 0xab2b, 0xab2b,
- 0xab2d, 0xab4b, 0xab2b, 0x080c, 0x14f6, 0x00d6, 0x2c68, 0x080c,
- 0x8022, 0x01a0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xb28e,
- 0x210c, 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x600b, 0xffff,
- 0x6918, 0x611a, 0x601f, 0x0004, 0x080c, 0x67a8, 0x2d60, 0x080c,
- 0x8078, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005, 0x00e6, 0x6018,
- 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa080, 0x0013,
- 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xad71, 0x2004, 0xd0ec, 0x05a8,
- 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, 0x00f6,
- 0x2c78, 0x080c, 0x5025, 0x00fe, 0x0150, 0x2001, 0xafa5, 0x2004,
- 0x603e, 0x2009, 0xad71, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009,
- 0xad71, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, 0xa006,
- 0x00a0, 0x2001, 0xafa5, 0x200c, 0x8103, 0xa100, 0x603e, 0x6018,
- 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, 0x0cd0,
- 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, 0x00c6,
- 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, 0x8cff, 0x0180,
- 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, 0x080c,
- 0x6618, 0x080c, 0x8078, 0x0010, 0xacf0, 0x0003, 0x2e64, 0x0c70,
- 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, 0x002b,
- 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, 0x0003,
- 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156,
- 0x2011, 0xad27, 0x2204, 0xa084, 0x00ff, 0x2019, 0xb28e, 0x2334,
- 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, 0xa636,
- 0x11a0, 0x2011, 0xb290, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004,
- 0x080c, 0x8a7c, 0x1150, 0x2011, 0xb294, 0x6018, 0xa098, 0x0006,
- 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1100, 0x015e, 0x003e, 0x002e,
- 0x0005, 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x080c, 0x28fa,
- 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108,
- 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6,
- 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126,
- 0x2091, 0x8000, 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424,
- 0x2061, 0xb400, 0x2071, 0xad00, 0x7644, 0x7064, 0xa606, 0x0578,
- 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500,
- 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xa990, 0x01b8,
- 0x080c, 0xa9a0, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016,
- 0x080c, 0x190b, 0x001e, 0x080c, 0x9778, 0x1110, 0x080c, 0x2aff,
- 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x080c, 0x974e, 0xace0,
- 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e,
- 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee,
- 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xad40,
- 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030,
- 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a, 0x0451, 0x00ee,
- 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000,
- 0x2071, 0xad40, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4,
- 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a,
- 0x0081, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6,
- 0x2091, 0x8000, 0x2071, 0xad42, 0x0021, 0x00ee, 0x000e, 0x012e,
- 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000,
- 0x2072, 0x0005, 0x00e6, 0x2071, 0xad40, 0x0c99, 0x00ee, 0x0005,
- 0x00e6, 0x2071, 0xad44, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002,
- 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200,
- 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x8529
-};
-
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index fa901fd65085..d5fdcb9a8842 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = MV_USE_Q_DEPTH,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = MV_MAX_SG_CT / 2,
@@ -748,7 +747,7 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port,
mv_dump_mem(mmio_base+0xf00, 0x4);
mv_dump_mem(mmio_base+0x1d00, 0x6c);
for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
- hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+ hc_base = mv_hc_base(mmio_base, hc);
DPRINTK("HC regs (HC %i):\n", hc);
mv_dump_mem(hc_base, 0x1c);
}
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index f77bf183dfab..9f553081b5e8 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -201,7 +201,6 @@ static struct scsi_host_template nv_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index cc928c68a479..7eb67a6bdc64 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 9ffe1ef0d205..886f3447dd48 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = QS_MAX_PRD,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 18c296c56899..106627299d55 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 068c98a4111b..f7264fd611c2 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index acc8439dea23..728530df2e07 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = ATA_MAX_PRD,
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 724f0ed6a52d..53b0d5c0a61f 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -290,7 +290,6 @@ static struct scsi_host_template k2_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index ae70f60c7c0d..4139ad4b1df0 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 7ac5a5f5a905..38b52bd3fa3f 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -81,7 +81,6 @@ static struct scsi_host_template uli_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 791bf652ba63..9e7ae4e0db32 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 836bbbb26ff2..8a29ce340b47 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -263,7 +263,6 @@ static struct scsi_host_template vsc_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 6913b0623167..73994e2ac2cb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -565,7 +565,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
/*
* If SCSI-2 or lower, store the LUN value in cmnd.
*/
- if (cmd->device->scsi_level <= SCSI_2) {
+ if (cmd->device->scsi_level <= SCSI_2 &&
+ cmd->device->scsi_level != SCSI_UNKNOWN) {
cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
(cmd->device->lun << 5 & 0xe0);
}
@@ -1243,7 +1244,7 @@ static int __init init_scsi(void)
if (error)
goto cleanup_sysctl;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
printk(KERN_NOTICE "SCSI subsystem initialized\n");
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 84c3937ae8fb..c750d3399a97 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -132,7 +132,9 @@ static struct {
{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */
{"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */
{"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */
- {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN},
+ {"COMPAQ", "ARRAY CONTROLLER", NULL, BLIST_SPARSELUN | BLIST_LARGELUN |
+ BLIST_MAX_512 | BLIST_REPORTLUN2}, /* Compaq RA4x00 */
+ {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN | BLIST_MAX_512}, /* Compaq RA4x00 */
{"COMPAQ", "CR3500", NULL, BLIST_FORCELUN},
{"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 5f0fdfb2618c..1c75646f9689 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1537,8 +1537,8 @@ int scsi_error_handler(void *data)
* what we need to do to get it up and online again (if we can).
* If we fail, we end up taking the thing offline.
*/
- if (shost->hostt->eh_strategy_handler)
- shost->hostt->eh_strategy_handler(shost);
+ if (shost->transportt->eh_strategy_handler)
+ shost->transportt->eh_strategy_handler(shost);
else
scsi_unjam_host(shost);
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 36e930066649..a89aff61d3d8 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -158,180 +158,6 @@ int scsi_set_medium_removal(struct scsi_device *sdev, char state)
EXPORT_SYMBOL(scsi_set_medium_removal);
/*
- * This interface is deprecated - users should use the scsi generic (sg)
- * interface instead, as this is a more flexible approach to performing
- * generic SCSI commands on a device.
- *
- * The structure that we are passed should look like:
- *
- * struct sdata {
- * unsigned int inlen; [i] Length of data to be written to device
- * unsigned int outlen; [i] Length of data to be read from device
- * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12).
- * [o] Data read from device starts here.
- * [o] On error, sense buffer starts here.
- * unsigned char wdata[y]; [i] Data written to device starts here.
- * };
- * Notes:
- * - The SCSI command length is determined by examining the 1st byte
- * of the given command. There is no way to override this.
- * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha).
- * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
- * accommodate the sense buffer when an error occurs.
- * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
- * old code will not be surprised.
- * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
- * a negative return and the Unix error code in 'errno'.
- * If the SCSI command succeeds then 0 is returned.
- * Positive numbers returned are the compacted SCSI error codes (4
- * bytes in one int) where the lowest byte is the SCSI status.
- * See the drivers/scsi/scsi.h file for more information on this.
- *
- */
-#define OMAX_SB_LEN 16 /* Old sense buffer length */
-
-int scsi_ioctl_send_command(struct scsi_device *sdev,
- struct scsi_ioctl_command __user *sic)
-{
- char *buf;
- unsigned char cmd[MAX_COMMAND_SIZE];
- unsigned char sense[SCSI_SENSE_BUFFERSIZE];
- char __user *cmd_in;
- unsigned char opcode;
- unsigned int inlen, outlen, cmdlen;
- unsigned int needed, buf_needed;
- int timeout, retries, result;
- int data_direction;
- gfp_t gfp_mask = GFP_KERNEL;
-
- if (!sic)
- return -EINVAL;
-
- if (sdev->host->unchecked_isa_dma)
- gfp_mask |= GFP_DMA;
-
- /*
- * Verify that we can read at least this much.
- */
- if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
- return -EFAULT;
-
- if(__get_user(inlen, &sic->inlen))
- return -EFAULT;
-
- if(__get_user(outlen, &sic->outlen))
- return -EFAULT;
-
- /*
- * We do not transfer more than MAX_BUF with this interface.
- * If the user needs to transfer more data than this, they
- * should use scsi_generics (sg) instead.
- */
- if (inlen > MAX_BUF)
- return -EINVAL;
- if (outlen > MAX_BUF)
- return -EINVAL;
-
- cmd_in = sic->data;
- if(get_user(opcode, cmd_in))
- return -EFAULT;
-
- needed = buf_needed = (inlen > outlen ? inlen : outlen);
- if (buf_needed) {
- buf_needed = (buf_needed + 511) & ~511;
- if (buf_needed > MAX_BUF)
- buf_needed = MAX_BUF;
- buf = kzalloc(buf_needed, gfp_mask);
- if (!buf)
- return -ENOMEM;
- if (inlen == 0) {
- data_direction = DMA_FROM_DEVICE;
- } else if (outlen == 0 ) {
- data_direction = DMA_TO_DEVICE;
- } else {
- /*
- * Can this ever happen?
- */
- data_direction = DMA_BIDIRECTIONAL;
- }
-
- } else {
- buf = NULL;
- data_direction = DMA_NONE;
- }
-
- /*
- * Obtain the command from the user's address space.
- */
- cmdlen = COMMAND_SIZE(opcode);
-
- result = -EFAULT;
-
- if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen))
- goto error;
-
- if(__copy_from_user(cmd, cmd_in, cmdlen))
- goto error;
-
- /*
- * Obtain the data to be sent to the device (if any).
- */
-
- if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen))
- goto error;
-
- switch (opcode) {
- case SEND_DIAGNOSTIC:
- case FORMAT_UNIT:
- timeout = FORMAT_UNIT_TIMEOUT;
- retries = 1;
- break;
- case START_STOP:
- timeout = START_STOP_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- case MOVE_MEDIUM:
- timeout = MOVE_MEDIUM_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- case READ_ELEMENT_STATUS:
- timeout = READ_ELEMENT_STATUS_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- case READ_DEFECT_DATA:
- timeout = READ_DEFECT_DATA_TIMEOUT;
- retries = 1;
- break;
- default:
- timeout = IOCTL_NORMAL_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- }
-
- result = scsi_execute(sdev, cmd, data_direction, buf, needed,
- sense, timeout, retries, 0);
-
- /*
- * If there was an error condition, pass the info back to the user.
- */
- if (result) {
- int sb_len = sizeof(*sense);
-
- sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
- if (copy_to_user(cmd_in, sense, sb_len))
- result = -EFAULT;
- } else {
- if (outlen && copy_to_user(cmd_in, buf, outlen))
- result = -EFAULT;
- }
-
-error:
- kfree(buf);
- return result;
-}
-EXPORT_SYMBOL(scsi_ioctl_send_command);
-
-/*
* The scsi_ioctl_get_pci() function places into arg the value
* pci_dev::slot_name (8 characters) for the PCI device (if any).
* Returns: 0 on success
@@ -409,7 +235,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
case SCSI_IOCTL_SEND_COMMAND:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- return scsi_ioctl_send_command(sdev, arg);
+ return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg);
case SCSI_IOCTL_DOORLOCK:
return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
case SCSI_IOCTL_DOORUNLOCK:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 8f010a314a3d..7b0f9a3810d2 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1479,6 +1479,8 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
static void scsi_kill_request(struct request *req, request_queue_t *q)
{
struct scsi_cmnd *cmd = req->special;
+ struct scsi_device *sdev = cmd->device;
+ struct Scsi_Host *shost = sdev->host;
blkdev_dequeue_request(req);
@@ -1491,6 +1493,19 @@ static void scsi_kill_request(struct request *req, request_queue_t *q)
scsi_init_cmd_errh(cmd);
cmd->result = DID_NO_CONNECT << 16;
atomic_inc(&cmd->device->iorequest_cnt);
+
+ /*
+ * SCSI request completion path will do scsi_device_unbusy(),
+ * bump busy counts. To bump the counters, we need to dance
+ * with the locks as normal issue path does.
+ */
+ sdev->device_busy++;
+ spin_unlock(sdev->request_queue->queue_lock);
+ spin_lock(shost->host_lock);
+ shost->host_busy++;
+ spin_unlock(shost->host_lock);
+ spin_lock(sdev->request_queue->queue_lock);
+
__scsi_done(cmd);
}
diff --git a/drivers/scsi/scsi_sas_internal.h b/drivers/scsi/scsi_sas_internal.h
new file mode 100644
index 000000000000..d76e6e3d8ca5
--- /dev/null
+++ b/drivers/scsi/scsi_sas_internal.h
@@ -0,0 +1,38 @@
+#ifndef _SCSI_SAS_INTERNAL_H
+#define _SCSI_SAS_INTERNAL_H
+
+#define SAS_HOST_ATTRS 0
+#define SAS_PORT_ATTRS 17
+#define SAS_RPORT_ATTRS 7
+#define SAS_END_DEV_ATTRS 3
+#define SAS_EXPANDER_ATTRS 7
+
+struct sas_internal {
+ struct scsi_transport_template t;
+ struct sas_function_template *f;
+ struct sas_domain_function_template *dft;
+
+ struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+ struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
+ struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+ struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
+ struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
+
+ struct transport_container phy_attr_cont;
+ struct transport_container rphy_attr_cont;
+ struct transport_container end_dev_attr_cont;
+ struct transport_container expander_attr_cont;
+
+ /*
+ * The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c
+ */
+ struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+ struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
+ struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+ struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
+ struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
+};
+#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
+
+#endif
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f14945996ede..1a5474bd11a1 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -673,6 +673,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
case TYPE_MEDIUM_CHANGER:
case TYPE_ENCLOSURE:
case TYPE_COMM:
+ case TYPE_RAID:
case TYPE_RBC:
sdev->writeable = 1;
break;
@@ -738,6 +739,13 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
sdev->select_no_atn = 1;
/*
+ * Maximum 512 sector transfer length
+ * broken RA4x00 Compaq Disk Array
+ */
+ if (*bflags & BLIST_MAX_512)
+ blk_queue_max_sectors(sdev->request_queue, 512);
+
+ /*
* Some devices may not want to have a start command automatically
* issued when a device is added.
*/
@@ -1123,10 +1131,13 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
* Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
* support more than 8 LUNs.
*/
- if ((bflags & BLIST_NOREPORTLUN) ||
- starget->scsi_level < SCSI_2 ||
- (starget->scsi_level < SCSI_3 &&
- (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
+ if (bflags & BLIST_NOREPORTLUN)
+ return 1;
+ if (starget->scsi_level < SCSI_2 &&
+ starget->scsi_level != SCSI_UNKNOWN)
+ return 1;
+ if (starget->scsi_level < SCSI_3 &&
+ (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8))
return 1;
if (bflags & BLIST_NOLUN)
return 0;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 8db656214b5c..95c5478dcdfd 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -34,6 +34,8 @@
#include <scsi/scsi_cmnd.h>
#include "scsi_priv.h"
+static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
+
/*
* Redefine so that we can have same named attributes in the
* sdev/starget/host objects.
@@ -213,10 +215,8 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
#define FC_MGMTSRVR_PORTID 0x00000a
-static void fc_shost_remove_rports(void *data);
static void fc_timeout_deleted_rport(void *data);
static void fc_scsi_scan_rport(void *data);
-static void fc_rport_terminate(struct fc_rport *rport);
/*
* Attribute counts pre object type...
@@ -288,42 +288,58 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
struct class_device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
/*
* Set default values easily detected by the midlayer as
* failure cases. The scsi lldd is responsible for initializing
* all transport attributes to valid values per host.
*/
- fc_host_node_name(shost) = -1;
- fc_host_port_name(shost) = -1;
- fc_host_permanent_port_name(shost) = -1;
- fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
- memset(fc_host_supported_fc4s(shost), 0,
- sizeof(fc_host_supported_fc4s(shost)));
- memset(fc_host_symbolic_name(shost), 0,
- sizeof(fc_host_symbolic_name(shost)));
- fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
- fc_host_maxframe_size(shost) = -1;
- memset(fc_host_serial_number(shost), 0,
- sizeof(fc_host_serial_number(shost)));
-
- fc_host_port_id(shost) = -1;
- fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
- fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
- memset(fc_host_active_fc4s(shost), 0,
- sizeof(fc_host_active_fc4s(shost)));
- fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
- fc_host_fabric_name(shost) = -1;
-
- fc_host_tgtid_bind_type(shost) = FC_TGTID_BIND_BY_WWPN;
-
- INIT_LIST_HEAD(&fc_host_rports(shost));
- INIT_LIST_HEAD(&fc_host_rport_bindings(shost));
- fc_host_next_rport_number(shost) = 0;
- fc_host_next_target_id(shost) = 0;
-
- fc_host_flags(shost) = 0;
- INIT_WORK(&fc_host_rport_del_work(shost), fc_shost_remove_rports, shost);
+ fc_host->node_name = -1;
+ fc_host->port_name = -1;
+ fc_host->permanent_port_name = -1;
+ fc_host->supported_classes = FC_COS_UNSPECIFIED;
+ memset(fc_host->supported_fc4s, 0,
+ sizeof(fc_host->supported_fc4s));
+ memset(fc_host->symbolic_name, 0,
+ sizeof(fc_host->symbolic_name));
+ fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
+ fc_host->maxframe_size = -1;
+ memset(fc_host->serial_number, 0,
+ sizeof(fc_host->serial_number));
+
+ fc_host->port_id = -1;
+ fc_host->port_type = FC_PORTTYPE_UNKNOWN;
+ fc_host->port_state = FC_PORTSTATE_UNKNOWN;
+ memset(fc_host->active_fc4s, 0,
+ sizeof(fc_host->active_fc4s));
+ fc_host->speed = FC_PORTSPEED_UNKNOWN;
+ fc_host->fabric_name = -1;
+
+ fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
+
+ INIT_LIST_HEAD(&fc_host->rports);
+ INIT_LIST_HEAD(&fc_host->rport_bindings);
+ fc_host->next_rport_number = 0;
+ fc_host->next_target_id = 0;
+
+ snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
+ shost->host_no);
+ fc_host->work_q = create_singlethread_workqueue(
+ fc_host->work_q_name);
+ if (!fc_host->work_q)
+ return -ENOMEM;
+
+ snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
+ shost->host_no);
+ fc_host->devloss_work_q = create_singlethread_workqueue(
+ fc_host->devloss_work_q_name);
+ if (!fc_host->devloss_work_q) {
+ destroy_workqueue(fc_host->work_q);
+ fc_host->work_q = NULL;
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -879,9 +895,9 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
while (!list_empty(&fc_host_rport_bindings(shost))) {
get_list_head_entry(rport,
&fc_host_rport_bindings(shost), peers);
- spin_unlock_irqrestore(shost->host_lock, flags);
- fc_rport_terminate(rport);
- spin_lock_irqsave(shost->host_lock, flags);
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -1262,6 +1278,90 @@ void fc_release_transport(struct scsi_transport_template *t)
}
EXPORT_SYMBOL(fc_release_transport);
+/**
+ * fc_queue_work - Queue work to the fc_host workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ * @work: Work to queue for execution.
+ *
+ * Return value:
+ * 0 on success / != 0 for error
+ **/
+static int
+fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
+{
+ if (unlikely(!fc_host_work_q(shost))) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to queue work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+
+ return -EINVAL;
+ }
+
+ return queue_work(fc_host_work_q(shost), work);
+}
+
+/**
+ * fc_flush_work - Flush a fc_host's workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ **/
+static void
+fc_flush_work(struct Scsi_Host *shost)
+{
+ if (!fc_host_work_q(shost)) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to flush work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+ return;
+ }
+
+ flush_workqueue(fc_host_work_q(shost));
+}
+
+/**
+ * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ * @work: Work to queue for execution.
+ * @delay: jiffies to delay the work queuing
+ *
+ * Return value:
+ * 0 on success / != 0 for error
+ **/
+static int
+fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
+ unsigned long delay)
+{
+ if (unlikely(!fc_host_devloss_work_q(shost))) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to queue work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+
+ return -EINVAL;
+ }
+
+ return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
+}
+
+/**
+ * fc_flush_devloss - Flush a fc_host's devloss workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ **/
+static void
+fc_flush_devloss(struct Scsi_Host *shost)
+{
+ if (!fc_host_devloss_work_q(shost)) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to flush work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+ return;
+ }
+
+ flush_workqueue(fc_host_devloss_work_q(shost));
+}
+
/**
* fc_remove_host - called to terminate any fc_transport-related elements
@@ -1283,36 +1383,103 @@ void
fc_remove_host(struct Scsi_Host *shost)
{
struct fc_rport *rport, *next_rport;
+ struct workqueue_struct *work_q;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
/* Remove any remote ports */
list_for_each_entry_safe(rport, next_rport,
- &fc_host_rports(shost), peers)
- fc_rport_terminate(rport);
+ &fc_host->rports, peers) {
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
+ }
+
list_for_each_entry_safe(rport, next_rport,
- &fc_host_rport_bindings(shost), peers)
- fc_rport_terminate(rport);
+ &fc_host->rport_bindings, peers) {
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
+ }
+
+ /* flush all scan work items */
+ scsi_flush_work(shost);
+
+ /* flush all stgt delete, and rport delete work items, then kill it */
+ if (fc_host->work_q) {
+ work_q = fc_host->work_q;
+ fc_host->work_q = NULL;
+ destroy_workqueue(work_q);
+ }
+
+ /* flush all devloss work items, then kill it */
+ if (fc_host->devloss_work_q) {
+ work_q = fc_host->devloss_work_q;
+ fc_host->devloss_work_q = NULL;
+ destroy_workqueue(work_q);
+ }
}
EXPORT_SYMBOL(fc_remove_host);
-/*
- * fc_rport_tgt_remove - Removes the scsi target on the remote port
- * @rport: The remote port to be operated on
- */
+
+/**
+ * fc_starget_delete - called to delete the scsi decendents of an rport
+ * (target and all sdevs)
+ *
+ * @data: remote port to be operated on.
+ **/
static void
-fc_rport_tgt_remove(struct fc_rport *rport)
+fc_starget_delete(void *data)
{
+ struct fc_rport *rport = (struct fc_rport *)data;
struct Scsi_Host *shost = rport_to_shost(rport);
+ unsigned long flags;
scsi_target_unblock(&rport->dev);
- /* Stop anything on the workq */
- if (!cancel_delayed_work(&rport->dev_loss_work))
- flush_scheduled_work();
- scsi_flush_work(shost);
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ if (!cancel_delayed_work(&rport->dev_loss_work))
+ fc_flush_devloss(shost);
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
scsi_remove_target(&rport->dev);
}
+
+/**
+ * fc_rport_final_delete - finish rport termination and delete it.
+ *
+ * @data: remote port to be deleted.
+ **/
+static void
+fc_rport_final_delete(void *data)
+{
+ struct fc_rport *rport = (struct fc_rport *)data;
+ struct device *dev = &rport->dev;
+ struct Scsi_Host *shost = rport_to_shost(rport);
+
+ /* Delete SCSI target and sdevs */
+ if (rport->scsi_target_id != -1)
+ fc_starget_delete(data);
+
+ /*
+ * if a scan is pending, flush the SCSI Host work_q so that
+ * that we can reclaim the rport scan work element.
+ */
+ if (rport->flags & FC_RPORT_SCAN_PENDING)
+ scsi_flush_work(shost);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(&shost->shost_gendev);
+}
+
+
/**
* fc_rport_create - allocates and creates a remote FC port.
* @shost: scsi host the remote port is connected to.
@@ -1330,8 +1497,7 @@ struct fc_rport *
fc_rport_create(struct Scsi_Host *shost, int channel,
struct fc_rport_identifiers *ids)
{
- struct fc_host_attrs *fc_host =
- (struct fc_host_attrs *)shost->shost_data;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
struct fc_internal *fci = to_fc_internal(shost->transportt);
struct fc_rport *rport;
struct device *dev;
@@ -1360,6 +1526,8 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
+ INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport);
+ INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport);
spin_lock_irqsave(shost->host_lock, flags);
@@ -1368,7 +1536,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
rport->scsi_target_id = fc_host->next_target_id++;
else
rport->scsi_target_id = -1;
- list_add_tail(&rport->peers, &fc_host_rports(shost));
+ list_add_tail(&rport->peers, &fc_host->rports);
get_device(&shost->shost_gendev);
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1389,9 +1557,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
transport_add_device(dev);
transport_configure_device(dev);
- if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
/* initiate a scan of the target */
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ }
return rport;
@@ -1451,10 +1621,14 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
struct fc_rport_identifiers *ids)
{
struct fc_internal *fci = to_fc_internal(shost->transportt);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
struct fc_rport *rport;
unsigned long flags;
int match = 0;
+ /* ensure any stgt delete functions are done */
+ fc_flush_work(shost);
+
/*
* Search the list of "active" rports, for an rport that has been
* deleted, but we've held off the real delete while the target
@@ -1462,12 +1636,12 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
*/
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+ list_for_each_entry(rport, &fc_host->rports, peers) {
if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
(rport->channel == channel)) {
- switch (fc_host_tgtid_bind_type(shost)) {
+ switch (fc_host->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
case FC_TGTID_BIND_NONE:
if (rport->port_name == ids->port_name)
@@ -1521,27 +1695,34 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
* transaction.
*/
if (!cancel_delayed_work(work))
- flush_scheduled_work();
+ fc_flush_devloss(shost);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
/* initiate a scan of the target */
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
return rport;
}
}
}
/* Search the bindings array */
- if (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE) {
+ if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
/* search for a matching consistent binding */
- list_for_each_entry(rport, &fc_host_rport_bindings(shost),
+ list_for_each_entry(rport, &fc_host->rport_bindings,
peers) {
if (rport->channel != channel)
continue;
- switch (fc_host_tgtid_bind_type(shost)) {
+ switch (fc_host->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
if (rport->port_name == ids->port_name)
match = 1;
@@ -1559,8 +1740,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
}
if (match) {
- list_move_tail(&rport->peers,
- &fc_host_rports(shost));
+ list_move_tail(&rport->peers, &fc_host->rports);
break;
}
}
@@ -1574,15 +1754,17 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
rport->roles = ids->roles;
rport->port_state = FC_PORTSTATE_ONLINE;
- spin_unlock_irqrestore(shost->host_lock, flags);
-
if (fci->f->dd_fcrport_size)
memset(rport->dd_data, 0,
fci->f->dd_fcrport_size);
- if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
/* initiate a scan of the target */
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
return rport;
}
@@ -1597,30 +1779,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
}
EXPORT_SYMBOL(fc_remote_port_add);
-/*
- * fc_rport_terminate - this routine tears down and deallocates a remote port.
- * @rport: The remote port to be terminated
- *
- * Notes:
- * This routine assumes no locks are held on entry.
- */
-static void
-fc_rport_terminate(struct fc_rport *rport)
-{
- struct Scsi_Host *shost = rport_to_shost(rport);
- struct device *dev = &rport->dev;
- unsigned long flags;
-
- fc_rport_tgt_remove(rport);
-
- transport_remove_device(dev);
- device_del(dev);
- transport_destroy_device(dev);
- spin_lock_irqsave(shost->host_lock, flags);
- list_del(&rport->peers);
- spin_unlock_irqrestore(shost->host_lock, flags);
- put_device(&shost->shost_gendev);
-}
/**
* fc_remote_port_delete - notifies the fc transport that a remote
@@ -1675,20 +1833,39 @@ fc_rport_terminate(struct fc_rport *rport)
void
fc_remote_port_delete(struct fc_rport *rport)
{
+ struct Scsi_Host *shost = rport_to_shost(rport);
int timeout = rport->dev_loss_tmo;
+ unsigned long flags;
+
+ /*
+ * No need to flush the fc_host work_q's, as all adds are synchronous.
+ *
+ * We do need to reclaim the rport scan work element, so eventually
+ * (in fc_rport_final_delete()) we'll flush the scsi host work_q if
+ * there's still a scan pending.
+ */
+
+ spin_lock_irqsave(shost->host_lock, flags);
/* If no scsi target id mapping, delete it */
if (rport->scsi_target_id == -1) {
- fc_rport_terminate(rport);
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
+ rport->port_state = FC_PORTSTATE_BLOCKED;
+
+ rport->flags |= FC_RPORT_DEVLOSS_PENDING;
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
scsi_target_block(&rport->dev);
/* cap the length the devices can be blocked until they are deleted */
- schedule_delayed_work(&rport->dev_loss_work, timeout * HZ);
-
- rport->port_state = FC_PORTSTATE_BLOCKED;
+ fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
}
EXPORT_SYMBOL(fc_remote_port_delete);
@@ -1716,8 +1893,7 @@ void
fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
{
struct Scsi_Host *shost = rport_to_shost(rport);
- struct fc_host_attrs *fc_host =
- (struct fc_host_attrs *)shost->shost_data;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
unsigned long flags;
int create = 0;
@@ -1729,10 +1905,11 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
} else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
create = 1;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
rport->roles = roles;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
if (create) {
/*
* There may have been a delete timer running on the
@@ -1747,10 +1924,20 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
* transaction.
*/
if (!cancel_delayed_work(&rport->dev_loss_work))
- flush_scheduled_work();
+ fc_flush_devloss(shost);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ /* ensure any stgt delete functions are done */
+ fc_flush_work(shost);
/* initiate a scan of the target */
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
}
EXPORT_SYMBOL(fc_remote_port_rolechg);
@@ -1767,22 +1954,24 @@ fc_timeout_deleted_rport(void *data)
{
struct fc_rport *rport = (struct fc_rport *)data;
struct Scsi_Host *shost = rport_to_shost(rport);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+
/*
- * If the port is ONLINE, then it came back, but was no longer an
- * FCP target. Thus we need to tear down the scsi_target on it.
+ * If the port is ONLINE, then it came back. Validate it's still an
+ * FCP target. If not, tear down the scsi_target on it.
*/
- if (rport->port_state == FC_PORTSTATE_ONLINE) {
- spin_unlock_irqrestore(shost->host_lock, flags);
-
+ if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+ !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
dev_printk(KERN_ERR, &rport->dev,
- "blocked FC remote port time out: removing target\n");
-
- fc_rport_tgt_remove(rport);
-
+ "blocked FC remote port time out: no longer"
+ " a FCP target, removing starget\n");
+ fc_queue_work(shost, &rport->stgt_delete_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
@@ -1793,11 +1982,13 @@ fc_timeout_deleted_rport(void *data)
return;
}
- if (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE) {
- spin_unlock_irqrestore(shost->host_lock, flags);
+ if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) {
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
dev_printk(KERN_ERR, &rport->dev,
"blocked FC remote port time out: removing target\n");
- fc_rport_terminate(rport);
+ fc_queue_work(shost, &rport->rport_delete_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
@@ -1805,7 +1996,7 @@ fc_timeout_deleted_rport(void *data)
"blocked FC remote port time out: removing target and "
"saving binding\n");
- list_move_tail(&rport->peers, &fc_host_rport_bindings(shost));
+ list_move_tail(&rport->peers, &fc_host->rport_bindings);
/*
* Note: We do not remove or clear the hostdata area. This allows
@@ -1819,10 +2010,10 @@ fc_timeout_deleted_rport(void *data)
rport->maxframe_size = -1;
rport->supported_classes = FC_COS_UNSPECIFIED;
rport->roles = FC_RPORT_ROLE_UNKNOWN;
- rport->port_state = FC_PORTSTATE_DELETED;
+ rport->port_state = FC_PORTSTATE_NOTPRESENT;
/* remove the identifiers that aren't used in the consisting binding */
- switch (fc_host_tgtid_bind_type(shost)) {
+ switch (fc_host->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
rport->node_name = -1;
rport->port_id = -1;
@@ -1843,17 +2034,8 @@ fc_timeout_deleted_rport(void *data)
* As this only occurs if the remote port (scsi target)
* went away and didn't come back - we'll remove
* all attached scsi devices.
- *
- * We'll schedule the shost work item to perform the actual removal
- * to avoid recursion in the different flush calls if we perform
- * the removal in each target - and there are lots of targets
- * whose timeouts fire at the same time.
*/
-
- if ( !(fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED)) {
- fc_host_flags(shost) |= FC_SHOST_RPORT_DEL_SCHEDULED;
- scsi_queue_work(shost, &fc_host_rport_del_work(shost));
- }
+ fc_queue_work(shost, &rport->stgt_delete_work);
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -1870,44 +2052,18 @@ static void
fc_scsi_scan_rport(void *data)
{
struct fc_rport *rport = (struct fc_rport *)data;
-
- scsi_target_unblock(&rport->dev);
- scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id,
- SCAN_WILD_CARD, 1);
-}
-
-
-/**
- * fc_shost_remove_rports - called to remove all rports that are marked
- * as in a deleted (not connected) state.
- *
- * @data: shost whose rports are to be looked at
- **/
-static void
-fc_shost_remove_rports(void *data)
-{
- struct Scsi_Host *shost = (struct Scsi_Host *)data;
- struct fc_rport *rport, *next_rport;
+ struct Scsi_Host *shost = rport_to_shost(rport);
unsigned long flags;
- spin_lock_irqsave(shost->host_lock, flags);
- while (fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED) {
-
- fc_host_flags(shost) &= ~FC_SHOST_RPORT_DEL_SCHEDULED;
-
-restart_search:
- list_for_each_entry_safe(rport, next_rport,
- &fc_host_rport_bindings(shost), peers) {
- if (rport->port_state == FC_PORTSTATE_DELETED) {
- rport->port_state = FC_PORTSTATE_NOTPRESENT;
- spin_unlock_irqrestore(shost->host_lock, flags);
- fc_rport_tgt_remove(rport);
- spin_lock_irqsave(shost->host_lock, flags);
- goto restart_search;
- }
- }
-
+ if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+ (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+ scsi_target_unblock(&rport->dev);
+ scsi_scan_target(&rport->dev, rport->channel,
+ rport->scsi_target_id, SCAN_WILD_CARD, 1);
}
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_SCAN_PENDING;
spin_unlock_irqrestore(shost->host_lock, flags);
}
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 134c44c8538a..8b6d65e21bae 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -35,40 +35,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-
-#define SAS_HOST_ATTRS 0
-#define SAS_PORT_ATTRS 17
-#define SAS_RPORT_ATTRS 7
-#define SAS_END_DEV_ATTRS 3
-#define SAS_EXPANDER_ATTRS 7
-
-struct sas_internal {
- struct scsi_transport_template t;
- struct sas_function_template *f;
-
- struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
- struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
- struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
- struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
- struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
-
- struct transport_container phy_attr_cont;
- struct transport_container rphy_attr_cont;
- struct transport_container end_dev_attr_cont;
- struct transport_container expander_attr_cont;
-
- /*
- * The array of null terminated pointers to attributes
- * needed by scsi_sysfs.c
- */
- struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
- struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
- struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
- struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
- struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
-};
-#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
-
+#include "scsi_sas_internal.h"
struct sas_host_attrs {
struct list_head rphy_list;
struct mutex lock;
@@ -406,8 +373,6 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
if (!phy)
return NULL;
- get_device(parent);
-
phy->number = number;
device_initialize(&phy->dev);
@@ -459,10 +424,7 @@ EXPORT_SYMBOL(sas_phy_add);
void sas_phy_free(struct sas_phy *phy)
{
transport_destroy_device(&phy->dev);
- put_device(phy->dev.parent);
- put_device(phy->dev.parent);
- put_device(phy->dev.parent);
- kfree(phy);
+ put_device(&phy->dev);
}
EXPORT_SYMBOL(sas_phy_free);
@@ -484,7 +446,7 @@ sas_phy_delete(struct sas_phy *phy)
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
- put_device(dev->parent);
+ put_device(dev);
}
EXPORT_SYMBOL(sas_phy_delete);
@@ -800,7 +762,6 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent)
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
- put_device(&parent->dev);
return NULL;
}
@@ -836,7 +797,6 @@ struct sas_rphy *sas_expander_alloc(struct sas_phy *parent,
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
- put_device(&parent->dev);
return NULL;
}
@@ -885,6 +845,8 @@ int sas_rphy_add(struct sas_rphy *rphy)
(identify->target_port_protocols &
(SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
rphy->scsi_target_id = sas_host->next_target_id++;
+ else if (identify->device_type == SAS_END_DEVICE)
+ rphy->scsi_target_id = -1;
mutex_unlock(&sas_host->lock);
if (identify->device_type == SAS_END_DEVICE &&
@@ -910,6 +872,7 @@ EXPORT_SYMBOL(sas_rphy_add);
*/
void sas_rphy_free(struct sas_rphy *rphy)
{
+ struct device *dev = &rphy->dev;
struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
@@ -917,21 +880,9 @@ void sas_rphy_free(struct sas_rphy *rphy)
list_del(&rphy->list);
mutex_unlock(&sas_host->lock);
- transport_destroy_device(&rphy->dev);
- put_device(rphy->dev.parent);
- put_device(rphy->dev.parent);
- put_device(rphy->dev.parent);
- if (rphy->identify.device_type == SAS_END_DEVICE) {
- struct sas_end_device *edev = rphy_to_end_device(rphy);
-
- kfree(edev);
- } else {
- /* must be expander */
- struct sas_expander_device *edev =
- rphy_to_expander_device(rphy);
+ transport_destroy_device(dev);
- kfree(edev);
- }
+ put_device(dev);
}
EXPORT_SYMBOL(sas_rphy_free);
@@ -971,7 +922,7 @@ sas_rphy_delete(struct sas_rphy *rphy)
parent->rphy = NULL;
- put_device(&parent->dev);
+ put_device(dev);
}
EXPORT_SYMBOL(sas_rphy_delete);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7405d0df95db..b098942445ec 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -748,6 +748,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
/*
* most likely out of mem, but could also be a bad map
*/
+ sg_finish_rem_req(srp);
return -ENOMEM;
} else
return 0;
@@ -1044,7 +1045,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (!sg_allow_access(opcode, sdp->device->type))
return -EPERM;
}
- return scsi_ioctl_send_command(sdp->device, p);
+ return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
case SG_SET_DEBUG:
result = get_user(val, ip);
if (result)
@@ -1798,8 +1799,10 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
res = st_map_user_pages(schp->buffer, mx_sc_elems,
(unsigned long)hp->dxferp, dxfer_len,
(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0);
- if (res <= 0)
+ if (res <= 0) {
+ sg_remove_scat(schp);
return 1;
+ }
schp->k_use_sg = res;
schp->dio_in_use = 1;
hp->info |= SG_INFO_DIRECT_IO;
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 3659dd7b9d76..defccc477d1e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.2.2"
+#define SYM_VERSION "2.2.3"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 1fffd2b3c654..9c83b4d39a26 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -134,66 +134,17 @@ static void sym2_setup_params(void)
}
}
-/*
- * We used to try to deal with 64-bit BARs here, but don't any more.
- * There are many parts of this driver which would need to be modified
- * to handle a 64-bit base address, including scripts. I'm uncomfortable
- * with making those changes when I have no way of testing it, so I'm
- * just going to disable it.
- *
- * Note that some machines (eg HP rx8620 and Superdome) have bus addresses
- * below 4GB and physical addresses above 4GB. These will continue to work.
- */
-static int __devinit
-pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep)
-{
- u32 tmp;
- unsigned long base;
-#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2))
-
- pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
- base = tmp;
- if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
- pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
- if (tmp > 0) {
- dev_err(&pdev->dev,
- "BAR %d is 64-bit, disabling\n", index - 1);
- base = 0;
- }
- }
-
- if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
- base &= PCI_BASE_ADDRESS_IO_MASK;
- } else {
- base &= PCI_BASE_ADDRESS_MEM_MASK;
- }
-
- *basep = base;
- return index;
-#undef PCI_BAR_OFFSET
-}
-
static struct scsi_transport_template *sym2_transport_template = NULL;
/*
- * Used by the eh thread to wait for command completion.
- * It is allocated on the eh thread stack.
- */
-struct sym_eh_wait {
- struct completion done;
- struct timer_list timer;
- void (*old_done)(struct scsi_cmnd *);
- int to_do;
- int timed_out;
-};
-
-/*
* Driver private area in the SCSI command structure.
*/
struct sym_ucmd { /* Override the SCSI pointer structure */
- dma_addr_t data_mapping;
- u_char data_mapped;
- struct sym_eh_wait *eh_wait;
+ dma_addr_t data_mapping;
+ unsigned char data_mapped;
+ unsigned char to_do; /* For error handling */
+ void (*old_done)(struct scsi_cmnd *); /* For error handling */
+ struct completion *eh_done; /* For error handling */
};
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
@@ -514,8 +465,6 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struc
*/
int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{
- struct sym_tcb *tp = &np->target[cp->target];
- struct sym_lcb *lp = sym_lp(tp, cp->lun);
u32 lastp, goalp;
int dir;
@@ -596,7 +545,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
/*
* activate this job.
*/
- sym_start_next_ccbs(np, lp, 2);
+ sym_put_start_queue(np, cp);
return 0;
out_abort:
@@ -751,80 +700,54 @@ static void sym53c8xx_timer(unsigned long npref)
* What we will do regarding the involved SCSI command.
*/
#define SYM_EH_DO_IGNORE 0
-#define SYM_EH_DO_COMPLETE 1
#define SYM_EH_DO_WAIT 2
/*
- * Our general completion handler.
+ * scsi_done() alias when error recovery is in progress.
*/
-static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out)
+static void sym_eh_done(struct scsi_cmnd *cmd)
{
- struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait;
- if (!ep)
- return;
-
- /* Try to avoid a race here (not 100% safe) */
- if (!timed_out) {
- ep->timed_out = 0;
- if (ep->to_do == SYM_EH_DO_WAIT && !del_timer(&ep->timer))
- return;
- }
+ struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
- /* Revert everything */
- SYM_UCMD_PTR(cmd)->eh_wait = NULL;
- cmd->scsi_done = ep->old_done;
+ cmd->scsi_done = ucmd->old_done;
- /* Wake up the eh thread if it wants to sleep */
- if (ep->to_do == SYM_EH_DO_WAIT)
- complete(&ep->done);
+ if (ucmd->to_do == SYM_EH_DO_WAIT)
+ complete(ucmd->eh_done);
}
/*
- * scsi_done() alias when error recovery is in progress.
- */
-static void sym_eh_done(struct scsi_cmnd *cmd) { __sym_eh_done(cmd, 0); }
-
-/*
- * Some timeout handler to avoid waiting too long.
- */
-static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); }
-
-/*
* Generic method for our eh processing.
* The 'op' argument tells what we have to do.
*/
static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
{
struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
+ struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ struct Scsi_Host *host = cmd->device->host;
SYM_QUEHEAD *qp;
int to_do = SYM_EH_DO_IGNORE;
int sts = -1;
- struct sym_eh_wait eh, *ep = &eh;
+ struct completion eh_done;
dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
+ spin_lock_irq(host->host_lock);
/* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->cmd == cmd) {
to_do = SYM_EH_DO_WAIT;
- goto prepare;
+ break;
}
}
-prepare:
- /* Prepare stuff to either ignore, complete or wait for completion */
- switch(to_do) {
- default:
- case SYM_EH_DO_IGNORE:
- break;
- case SYM_EH_DO_WAIT:
- init_completion(&ep->done);
- /* fall through */
- case SYM_EH_DO_COMPLETE:
- ep->old_done = cmd->scsi_done;
+ if (to_do == SYM_EH_DO_WAIT) {
+ init_completion(&eh_done);
+ ucmd->old_done = cmd->scsi_done;
+ ucmd->eh_done = &eh_done;
+ wmb();
cmd->scsi_done = sym_eh_done;
- SYM_UCMD_PTR(cmd)->eh_wait = ep;
}
/* Try to proceed the operation we have been asked for */
@@ -851,29 +774,19 @@ prepare:
/* On error, restore everything and cross fingers :) */
if (sts) {
- SYM_UCMD_PTR(cmd)->eh_wait = NULL;
- cmd->scsi_done = ep->old_done;
+ cmd->scsi_done = ucmd->old_done;
to_do = SYM_EH_DO_IGNORE;
}
- ep->to_do = to_do;
- /* Complete the command with locks held as required by the driver */
- if (to_do == SYM_EH_DO_COMPLETE)
- sym_xpt_done2(np, cmd, DID_ABORT);
+ ucmd->to_do = to_do;
+ spin_unlock_irq(host->host_lock);
- /* Wait for completion with locks released, as required by kernel */
if (to_do == SYM_EH_DO_WAIT) {
- init_timer(&ep->timer);
- ep->timer.expires = jiffies + (5*HZ);
- ep->timer.function = sym_eh_timeout;
- ep->timer.data = (u_long)cmd;
- ep->timed_out = 1; /* Be pessimistic for once :) */
- add_timer(&ep->timer);
- spin_unlock_irq(np->s.host->host_lock);
- wait_for_completion(&ep->done);
- spin_lock_irq(np->s.host->host_lock);
- if (ep->timed_out)
+ if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
+ ucmd->to_do = SYM_EH_DO_IGNORE;
+ wmb();
sts = -2;
+ }
}
dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
@@ -886,46 +799,22 @@ prepare:
*/
static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
}
static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
}
static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
}
static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
}
/*
@@ -944,15 +833,12 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
if (reqtags > lp->s.scdev_depth)
reqtags = lp->s.scdev_depth;
- lp->started_limit = reqtags ? reqtags : 2;
- lp->started_max = 1;
lp->s.reqtags = reqtags;
if (reqtags != oldtags) {
dev_info(&tp->starget->dev,
"tagged command queuing %s, command queue depth %d.\n",
- lp->s.reqtags ? "enabled" : "disabled",
- lp->started_limit);
+ lp->s.reqtags ? "enabled" : "disabled", reqtags);
}
}
@@ -1866,15 +1752,25 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
static void __devinit
sym_init_device(struct pci_dev *pdev, struct sym_device *device)
{
- int i;
+ int i = 2;
+ struct pci_bus_region bus_addr;
device->host_id = SYM_SETUP_HOST_ID;
device->pdev = pdev;
- i = pci_get_base_address(pdev, 1, &device->mmio_base);
- pci_get_base_address(pdev, i, &device->ram_base);
+ pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]);
+ device->mmio_base = bus_addr.start;
+
+ /*
+ * If the BAR is 64-bit, resource 2 will be occupied by the
+ * upper 32 bits
+ */
+ if (!pdev->resource[i].flags)
+ i++;
+ pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
+ device->ram_base = bus_addr.start;
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
+#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
if (device->mmio_base)
device->s.ioaddr = pci_iomap(pdev, 1,
pci_resource_len(pdev, 1));
@@ -1978,7 +1874,8 @@ static struct scsi_host_template sym2_template = {
.eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler,
.eh_host_reset_handler = sym53c8xx_eh_host_reset_handler,
.this_id = 7,
- .use_clustering = DISABLE_CLUSTERING,
+ .use_clustering = ENABLE_CLUSTERING,
+ .max_sectors = 0xFFFF,
#ifdef SYM_LINUX_PROC_INFO_SUPPORT
.proc_info = sym53c8xx_proc_info,
.proc_name = NAME53C8XX,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index cc92d0c70cd7..a446cda3f64c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -68,7 +68,7 @@
*/
#define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2)
-#define SYM_OPT_HANDLE_DEVICE_QUEUEING
+#undef SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 60850cbe3a85..a671bdc07450 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -72,7 +72,10 @@ static void sym_printl_hex(u_char *p, int n)
static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
{
- sym_print_addr(cp->cmd, "%s: ", label);
+ if (label)
+ sym_print_addr(cp->cmd, "%s: ", label);
+ else
+ sym_print_addr(cp->cmd, "");
spi_print_msg(msg);
printf("\n");
@@ -472,7 +475,7 @@ static int sym_getpciclock (struct sym_hcb *np)
* calculations more simple.
*/
#define _5M 5000000
-static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
+static const u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
/*
* Get clock factor and sync divisor for a given
@@ -645,6 +648,37 @@ static void sym_save_initial_setting (struct sym_hcb *np)
}
/*
+ * Set SCSI BUS mode.
+ * - LVD capable chips (895/895A/896/1010) report the current BUS mode
+ * through the STEST4 IO register.
+ * - For previous generation chips (825/825A/875), the user has to tell us
+ * how to check against HVD, since a 100% safe algorithm is not possible.
+ */
+static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram)
+{
+ if (np->scsi_mode)
+ return;
+
+ np->scsi_mode = SMODE_SE;
+ if (np->features & (FE_ULTRA2|FE_ULTRA3))
+ np->scsi_mode = (np->sv_stest4 & SMODE);
+ else if (np->features & FE_DIFF) {
+ if (SYM_SETUP_SCSI_DIFF == 1) {
+ if (np->sv_scntl3) {
+ if (np->sv_stest2 & 0x20)
+ np->scsi_mode = SMODE_HVD;
+ } else if (nvram->type == SYM_SYMBIOS_NVRAM) {
+ if (!(INB(np, nc_gpreg) & 0x08))
+ np->scsi_mode = SMODE_HVD;
+ }
+ } else if (SYM_SETUP_SCSI_DIFF == 2)
+ np->scsi_mode = SMODE_HVD;
+ }
+ if (np->scsi_mode == SMODE_HVD)
+ np->rv_stest2 |= 0x20;
+}
+
+/*
* Prepare io register values used by sym_start_up()
* according to selected and supported features.
*/
@@ -654,10 +688,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
u32 period;
int i;
- /*
- * Wide ?
- */
- np->maxwide = (np->features & FE_WIDE)? 1 : 0;
+ np->maxwide = (np->features & FE_WIDE) ? 1 : 0;
/*
* Guess the frequency of the chip's clock.
@@ -838,6 +869,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* Get parity checking, host ID and verbose mode from NVRAM
*/
np->myaddr = 255;
+ np->scsi_mode = 0;
sym_nvram_setup_host(shost, np, nvram);
/*
@@ -854,33 +886,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
*/
sym_init_burst(np, burst_max);
- /*
- * Set SCSI BUS mode.
- * - LVD capable chips (895/895A/896/1010) report the
- * current BUS mode through the STEST4 IO register.
- * - For previous generation chips (825/825A/875),
- * user has to tell us how to check against HVD,
- * since a 100% safe algorithm is not possible.
- */
- np->scsi_mode = SMODE_SE;
- if (np->features & (FE_ULTRA2|FE_ULTRA3))
- np->scsi_mode = (np->sv_stest4 & SMODE);
- else if (np->features & FE_DIFF) {
- if (SYM_SETUP_SCSI_DIFF == 1) {
- if (np->sv_scntl3) {
- if (np->sv_stest2 & 0x20)
- np->scsi_mode = SMODE_HVD;
- }
- else if (nvram->type == SYM_SYMBIOS_NVRAM) {
- if (!(INB(np, nc_gpreg) & 0x08))
- np->scsi_mode = SMODE_HVD;
- }
- }
- else if (SYM_SETUP_SCSI_DIFF == 2)
- np->scsi_mode = SMODE_HVD;
- }
- if (np->scsi_mode == SMODE_HVD)
- np->rv_stest2 |= 0x20;
+ sym_set_bus_mode(np, nvram);
/*
* Set LED support from SCRIPTS.
@@ -973,8 +979,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
*
* Has to be called with interrupts disabled.
*/
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
-static int sym_regtest (struct sym_hcb *np)
+#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
+static int sym_regtest(struct sym_hcb *np)
{
register volatile u32 data;
/*
@@ -992,20 +998,25 @@ static int sym_regtest (struct sym_hcb *np)
#endif
printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
(unsigned) data);
- return (0x10);
+ return 0x10;
}
- return (0);
+ return 0;
+}
+#else
+static inline int sym_regtest(struct sym_hcb *np)
+{
+ return 0;
}
#endif
-static int sym_snooptest (struct sym_hcb *np)
+static int sym_snooptest(struct sym_hcb *np)
{
- u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
- int i, err=0;
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
- err |= sym_regtest (np);
- if (err) return (err);
-#endif
+ u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
+ int i, err;
+
+ err = sym_regtest(np);
+ if (err)
+ return err;
restart_test:
/*
* Enable Master Parity Checking as we intend
@@ -1094,7 +1105,7 @@ restart_test:
err |= 4;
}
- return (err);
+ return err;
}
/*
@@ -1464,7 +1475,7 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
/*
* Insert a job into the start queue.
*/
-static void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
{
u_short qidx;
@@ -4481,7 +4492,7 @@ static void sym_int_sir (struct sym_hcb *np)
switch (np->msgin [2]) {
case M_X_MODIFY_DP:
if (DEBUG_FLAGS & DEBUG_POINTER)
- sym_print_msg(cp,"modify DP",np->msgin);
+ sym_print_msg(cp, NULL, np->msgin);
tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) +
(np->msgin[5]<<8) + (np->msgin[6]);
sym_modify_dp(np, tp, cp, tmp);
@@ -4508,7 +4519,7 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case M_IGN_RESIDUE:
if (DEBUG_FLAGS & DEBUG_POINTER)
- sym_print_msg(cp,"ign wide residue", np->msgin);
+ sym_print_msg(cp, NULL, np->msgin);
if (cp->host_flags & HF_SENSE)
OUTL_DSP(np, SCRIPTA_BA(np, clrack));
else
@@ -4597,7 +4608,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
* Debugging purpose.
*/
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- assert(lp->busy_itl == 0);
+ if (lp->busy_itl != 0)
+ goto out_free;
#endif
/*
* Allocate resources for tags if not yet.
@@ -4642,7 +4654,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
* Debugging purpose.
*/
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- assert(lp->busy_itl == 0 && lp->busy_itlq == 0);
+ if (lp->busy_itl != 0 || lp->busy_itlq != 0)
+ goto out_free;
#endif
/*
* Count this nexus for this LUN.
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 2456090bb241..79ab6a177039 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -1049,6 +1049,8 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
+#else
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#endif
void sym_start_up(struct sym_hcb *np, int reason);
void sym_interrupt(struct sym_hcb *np);
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index dfc1e86d3aa1..043f50b1d10c 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -20,7 +20,7 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong <wendyx@us.ibm.com>
*
***********************************************************************/
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index b1b66e71d281..b3e1f71be4da 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -20,7 +20,7 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong <wendyx@us.ibm.com>
*
*
***********************************************************************/
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 87e4e2cf8ce7..a5fc589d6ef5 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -20,7 +20,7 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong <wendyx@us.ibm.com>
*
***********************************************************************/
#include <linux/delay.h> /* For udelay */
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index e9c10c0a30fc..321a40f33b50 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -1057,7 +1057,6 @@ static void m32r_sio_console_write(struct console *co, const char *s,
{
struct uart_sio_port *up = &m32r_sio_ports[co->index];
unsigned int ier;
- int i;
/*
* First save the UER then disable the interrupts
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index c30333694fde..2c70773543e0 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -41,6 +41,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/serial_core.h>
+#include <linux/delay.h>
#include <linux/major.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -97,11 +98,13 @@ static const struct multi_id multi_id[] = {
#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
struct serial_info {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
int ndev;
int multi;
int slave;
int manfid;
+ int prodid;
+ int c950ctrl;
dev_node_t node[4];
int line[4];
};
@@ -113,9 +116,36 @@ struct serial_cfg_mem {
};
-static void serial_config(dev_link_t * link);
+static int serial_config(struct pcmcia_device * link);
+static void wakeup_card(struct serial_info *info)
+{
+ int ctrl = info->c950ctrl;
+
+ if (info->manfid == MANFID_OXSEMI) {
+ outb(12, ctrl + 1);
+ } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
+ /* request_region? oxsemi branch does no request_region too... */
+ /* This sequence is needed to properly initialize MC45 attached to OXCF950.
+ * I tried decreasing these msleep()s, but it worked properly (survived
+ * 1000 stop/start operations) with these timeouts (or bigger). */
+ outb(0xA, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(300);
+ outb(0xC, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(200);
+ outb(0xF, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(100);
+ outb(0xC, ctrl + 1);
+ }
+}
+
/*======================================================================
After a card is removed, serial_remove() will unregister
@@ -123,67 +153,45 @@ static void serial_config(dev_link_t * link);
======================================================================*/
-static void serial_remove(dev_link_t *link)
+static void serial_remove(struct pcmcia_device *link)
{
struct serial_info *info = link->priv;
int i;
- link->state &= ~DEV_PRESENT;
-
DEBUG(0, "serial_release(0x%p)\n", link);
/*
* Recheck to see if the device is still configured.
*/
- if (info->link.state & DEV_CONFIG) {
- for (i = 0; i < info->ndev; i++)
- serial8250_unregister_port(info->line[i]);
+ for (i = 0; i < info->ndev; i++)
+ serial8250_unregister_port(info->line[i]);
- info->link.dev = NULL;
+ info->p_dev->dev_node = NULL;
- if (!info->slave) {
- pcmcia_release_configuration(info->link.handle);
- pcmcia_release_io(info->link.handle, &info->link.io);
- pcmcia_release_irq(info->link.handle, &info->link.irq);
- }
-
- info->link.state &= ~DEV_CONFIG;
- }
+ if (!info->slave)
+ pcmcia_disable_device(link);
}
-static int serial_suspend(struct pcmcia_device *dev)
+static int serial_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
- link->state |= DEV_SUSPEND;
-
- if (link->state & DEV_CONFIG) {
- struct serial_info *info = link->priv;
- int i;
-
- for (i = 0; i < info->ndev; i++)
- serial8250_suspend_port(info->line[i]);
+ struct serial_info *info = link->priv;
+ int i;
- if (!info->slave)
- pcmcia_release_configuration(link->handle);
- }
+ for (i = 0; i < info->ndev; i++)
+ serial8250_suspend_port(info->line[i]);
return 0;
}
-static int serial_resume(struct pcmcia_device *dev)
+static int serial_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
- link->state &= ~DEV_SUSPEND;
-
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
struct serial_info *info = link->priv;
int i;
- if (!info->slave)
- pcmcia_request_configuration(link->handle, &link->conf);
-
for (i = 0; i < info->ndev; i++)
serial8250_resume_port(info->line[i]);
+ wakeup_card(info);
}
return 0;
@@ -197,10 +205,9 @@ static int serial_resume(struct pcmcia_device *dev)
======================================================================*/
-static int serial_probe(struct pcmcia_device *p_dev)
+static int serial_probe(struct pcmcia_device *link)
{
struct serial_info *info;
- dev_link_t *link;
DEBUG(0, "serial_attach()\n");
@@ -209,7 +216,7 @@ static int serial_probe(struct pcmcia_device *p_dev)
if (!info)
return -ENOMEM;
memset(info, 0, sizeof (*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -223,12 +230,7 @@ static int serial_probe(struct pcmcia_device *p_dev)
}
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- serial_config(link);
-
- return 0;
+ return serial_config(link);
}
/*======================================================================
@@ -240,9 +242,8 @@ static int serial_probe(struct pcmcia_device *p_dev)
======================================================================*/
-static void serial_detach(struct pcmcia_device *p_dev)
+static void serial_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct serial_info *info = link->priv;
DEBUG(0, "serial_detach(0x%p)\n", link);
@@ -263,7 +264,7 @@ static void serial_detach(struct pcmcia_device *p_dev)
/*====================================================================*/
-static int setup_serial(client_handle_t handle, struct serial_info * info,
+static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
kio_addr_t iobase, int irq)
{
struct uart_port port;
@@ -298,7 +299,7 @@ static int setup_serial(client_handle_t handle, struct serial_info * info,
/*====================================================================*/
static int
-first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
{
int i;
i = pcmcia_get_first_tuple(handle, tuple);
@@ -311,7 +312,7 @@ first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
}
static int
-next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
{
int i;
i = pcmcia_get_next_tuple(handle, tuple);
@@ -325,11 +326,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
/*====================================================================*/
-static int simple_config(dev_link_t *link)
+static int simple_config(struct pcmcia_device *link)
{
static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
static const int size_table[2] = { 8, 16 };
- client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -350,7 +350,7 @@ static int simple_config(dev_link_t *link)
buf = cfg_mem->buf;
/* If the card is already configured, look up the port and irq */
- i = pcmcia_get_configuration_info(handle, &config);
+ i = pcmcia_get_configuration_info(link, &config);
if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
kio_addr_t port = 0;
if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
@@ -363,10 +363,9 @@ static int simple_config(dev_link_t *link)
}
if (info->slave) {
kfree(cfg_mem);
- return setup_serial(handle, info, port, config.AssignedIRQ);
+ return setup_serial(link, info, port, config.AssignedIRQ);
}
}
- link->conf.Vcc = config.Vcc;
/* First pass: look for a config entry that looks normal. */
tuple->TupleData = (cisdata_t *) buf;
@@ -377,12 +376,12 @@ static int simple_config(dev_link_t *link)
/* Two tries: without IO aliases, then with aliases */
for (s = 0; s < 2; s++) {
for (try = 0; try < 2; try++) {
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
(cf->io.win[0].base != 0)) {
@@ -390,19 +389,19 @@ static int simple_config(dev_link_t *link)
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ?
16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
}
}
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -410,50 +409,48 @@ next_entry:
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
found_port:
if (i != CS_SUCCESS) {
printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n");
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
kfree(cfg_mem);
return -1;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
if (info->multi && (info->manfid == MANFID_3COM))
link->conf.ConfigIndex &= ~(0x08);
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
kfree(cfg_mem);
return -1;
}
kfree(cfg_mem);
- return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+ return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
}
-static int multi_config(dev_link_t * link)
+static int multi_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
u_char *buf;
cisparse_t *parse;
cistpl_cftable_entry_t *cf;
- config_info_t config;
int i, rc, base2 = 0;
cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
@@ -464,14 +461,6 @@ static int multi_config(dev_link_t * link)
cf = &parse->cftable_entry;
buf = cfg_mem->buf;
- i = pcmcia_get_configuration_info(handle, &config);
- if (i != CS_SUCCESS) {
- cs_error(handle, GetConfigurationInfo, i);
- rc = -1;
- goto free_cfg_mem;
- }
- link->conf.Vcc = config.Vcc;
-
tuple->TupleData = (cisdata_t *) buf;
tuple->TupleOffset = 0;
tuple->TupleDataMax = 255;
@@ -480,7 +469,7 @@ static int multi_config(dev_link_t * link)
/* First, look for a generic full-sized window */
link->io.NumPorts1 = info->multi * 8;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
/* The quad port cards have bad CIS's, so just look for a
window larger than 8 ports and assume it will be right */
@@ -490,19 +479,19 @@ static int multi_config(dev_link_t * link)
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines =
cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
base2 = link->io.BasePort1 + 8;
if (i == CS_SUCCESS)
break;
}
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
/* If that didn't work, look for two windows */
if (i != CS_SUCCESS) {
link->io.NumPorts1 = link->io.NumPorts2 = 8;
info->multi = 2;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
link->conf.ConfigIndex = cf->index;
@@ -510,26 +499,26 @@ static int multi_config(dev_link_t * link)
link->io.BasePort2 = cf->io.win[1].base;
link->io.IOAddrLines =
cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
base2 = link->io.BasePort2;
if (i == CS_SUCCESS)
break;
}
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
rc = -1;
goto free_cfg_mem;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n");
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
/* Socket Dual IO: this enables irq's for second port */
@@ -537,35 +526,43 @@ static int multi_config(dev_link_t * link)
link->conf.Present |= PRESENT_EXT_STATUS;
link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
rc = -1;
goto free_cfg_mem;
}
/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
- 8 registers are for the UART, the others are extra registers */
- if (info->manfid == MANFID_OXSEMI) {
+ * 8 registers are for the UART, the others are extra registers.
+ * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
+ */
+ if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
+ info->prodid == PRODID_POSSIO_GCC)) {
+ int err;
+
if (cf->index == 1 || cf->index == 3) {
- setup_serial(handle, info, base2, link->irq.AssignedIRQ);
- outb(12, link->io.BasePort1 + 1);
+ err = setup_serial(link, info, base2,
+ link->irq.AssignedIRQ);
+ base2 = link->io.BasePort1;
} else {
- setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
- outb(12, base2 + 1);
+ err = setup_serial(link, info, link->io.BasePort1,
+ link->irq.AssignedIRQ);
}
+ info->c950ctrl = base2;
+ wakeup_card(info);
rc = 0;
goto free_cfg_mem;
}
- setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+ setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
/* The Nokia cards are not really multiport cards */
if (info->manfid == MANFID_NOKIA) {
rc = 0;
goto free_cfg_mem;
}
for (i = 0; i < info->multi - 1; i++)
- setup_serial(handle, info, base2 + (8 * i),
+ setup_serial(link, info, base2 + (8 * i),
link->irq.AssignedIRQ);
rc = 0;
free_cfg_mem:
@@ -581,9 +578,8 @@ free_cfg_mem:
======================================================================*/
-void serial_config(dev_link_t * link)
+static int serial_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -609,7 +605,7 @@ void serial_config(dev_link_t * link)
tuple->Attributes = 0;
/* Get configuration register information */
tuple->DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, tuple, parse);
+ last_ret = first_tuple(link, tuple, parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -617,18 +613,16 @@ void serial_config(dev_link_t * link)
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Is this a compliant multifunction card? */
tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
- info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS);
+ info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
/* Is this a multiport card? */
tuple->DesiredTuple = CISTPL_MANFID;
- if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
info->manfid = parse->manfid.manf;
+ info->prodid = le16_to_cpu(buf[1]);
for (i = 0; i < MULTI_COUNT; i++)
if ((info->manfid == multi_id[i].manfid) &&
(parse->manfid.card == multi_id[i].prodid))
@@ -641,11 +635,11 @@ void serial_config(dev_link_t * link)
multifunction cards that ask for appropriate IO port ranges */
tuple->DesiredTuple = CISTPL_FUNCID;
if ((info->multi == 0) &&
- ((first_tuple(handle, tuple, parse) != CS_SUCCESS) ||
+ ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
(parse->funcid.func == CISTPL_FUNCID_MULTI) ||
(parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
- if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
info->multi = cf->io.win[0].len >> 3;
if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
@@ -664,31 +658,30 @@ void serial_config(dev_link_t * link)
if (info->manfid == MANFID_IBM) {
conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
- last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+ last_ret = pcmcia_access_configuration_register(link, &reg);
if (last_ret) {
last_fn = AccessConfigurationRegister;
goto cs_failed;
}
reg.Action = CS_WRITE;
reg.Value = reg.Value | 1;
- last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+ last_ret = pcmcia_access_configuration_register(link, &reg);
if (last_ret) {
last_fn = AccessConfigurationRegister;
goto cs_failed;
}
}
- link->dev = &info->node[0];
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node[0];
kfree(cfg_mem);
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
serial_remove(link);
- link->state &= ~DEV_CONFIG_PENDING;
kfree(cfg_mem);
+ return -ENODEV;
}
static struct pcmcia_device_id serial_ids[] = {
@@ -739,6 +732,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
+ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
@@ -757,6 +751,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
+ PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index 93449a1a0065..0b49ff78efc1 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
@@ -619,9 +620,9 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
pci_set_master(pdev);
#ifdef USE_64BIT_DMA
- ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
if (!ret) {
- ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ ret = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
if (ret < 0) {
printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
"for consistent allocations\n",
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index d3a7b0c3d38b..dda0ca45d904 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -35,73 +35,52 @@ typedef struct ixj_info_t {
} ixj_info_t;
static void ixj_detach(struct pcmcia_device *p_dev);
-static void ixj_config(dev_link_t * link);
-static void ixj_cs_release(dev_link_t * link);
+static int ixj_config(struct pcmcia_device * link);
+static void ixj_cs_release(struct pcmcia_device * link);
-static int ixj_attach(struct pcmcia_device *p_dev)
+static int ixj_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
-
DEBUG(0, "ixj_attach()\n");
/* Create new ixj device */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
- memset(link, 0, sizeof(struct dev_link_t));
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 3;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
- if (!link->priv) {
- kfree(link);
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 3;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
+ if (!p_dev->priv) {
return -ENOMEM;
}
- memset(link->priv, 0, sizeof(struct ixj_info_t));
-
- link->handle = p_dev;
- p_dev->instance = link;
+ memset(p_dev->priv, 0, sizeof(struct ixj_info_t));
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ixj_config(link);
-
- return 0;
+ return ixj_config(p_dev);
}
-static void ixj_detach(struct pcmcia_device *p_dev)
+static void ixj_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "ixj_detach(0x%p)\n", link);
- link->state &= ~DEV_RELEASE_PENDING;
- if (link->state & DEV_CONFIG)
- ixj_cs_release(link);
+ ixj_cs_release(link);
kfree(link->priv);
- kfree(link);
}
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void ixj_get_serial(dev_link_t * link, IXJ * j)
+static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
{
- client_handle_t handle;
tuple_t tuple;
u_short buf[128];
char *str;
int last_ret, last_fn, i, place;
- handle = link->handle;
DEBUG(0, "ixj_get_serial(0x%p)\n", link);
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 80;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
str = (char *) buf;
printk("PCMCIA Version %d.%d\n", str[0], str[1]);
str += 2;
@@ -149,22 +128,19 @@ static void ixj_get_serial(dev_link_t * link, IXJ * j)
return;
}
-static void ixj_config(dev_link_t * link)
+static int ixj_config(struct pcmcia_device * link)
{
IXJ *j;
- client_handle_t handle;
ixj_info_t *info;
tuple_t tuple;
u_short buf[128];
cisparse_t parse;
- config_info_t conf;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt =
{
0
};
int last_ret, last_fn;
- handle = link->handle;
info = link->priv;
DEBUG(0, "ixj_config(0x%p)\n", link);
tuple.TupleData = (cisdata_t *) buf;
@@ -172,19 +148,17 @@ static void ixj_config(dev_link_t * link)
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- link->state |= DEV_CONFIG;
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
@@ -195,7 +169,7 @@ static void ixj_config(dev_link_t * link)
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we've got this far, we're done */
break;
@@ -203,10 +177,10 @@ static void ixj_config(dev_link_t * link)
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
* Register the card with the core.
@@ -215,46 +189,21 @@ static void ixj_config(dev_link_t * link)
info->ndev = 1;
info->node.major = PHONE_MAJOR;
- link->dev = &info->node;
+ link->dev_node = &info->node;
ixj_get_serial(link, j);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
ixj_cs_release(link);
+ return -ENODEV;
}
-static void ixj_cs_release(dev_link_t *link)
+static void ixj_cs_release(struct pcmcia_device *link)
{
ixj_info_t *info = link->priv;
DEBUG(0, "ixj_cs_release(0x%p)\n", link);
info->ndev = 0;
- link->dev = NULL;
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- link->state &= ~DEV_CONFIG;
-}
-
-static int ixj_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int ixj_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
static struct pcmcia_device_id ixj_ids[] = {
@@ -268,11 +217,9 @@ static struct pcmcia_driver ixj_driver = {
.drv = {
.name = "ixj_cs",
},
- .probe = ixj_attach,
+ .probe = ixj_probe,
.remove = ixj_detach,
.id_table = ixj_ids,
- .suspend = ixj_suspend,
- .resume = ixj_resume,
};
static int __init ixj_pcmcia_init(void)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 830d2c982670..b38990adf1cd 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -68,7 +68,7 @@
#include "usbatm.h"
-#define EAGLEUSBVERSION "ueagle 1.2"
+#define EAGLEUSBVERSION "ueagle 1.3"
/*
@@ -243,7 +243,7 @@ enum {
#define BULK_TIMEOUT 300
#define CTRL_TIMEOUT 1000
-#define ACK_TIMEOUT msecs_to_jiffies(1500)
+#define ACK_TIMEOUT msecs_to_jiffies(3000)
#define UEA_INTR_IFACE_NO 0
#define UEA_US_IFACE_NO 1
@@ -314,6 +314,10 @@ struct cmv {
((d) & 0xff) << 16 | \
((a) & 0xff) << 8 | \
((b) & 0xff))
+#define GETSA1(a) ((a >> 8) & 0xff)
+#define GETSA2(a) (a & 0xff)
+#define GETSA3(a) ((a >> 24) & 0xff)
+#define GETSA4(a) ((a >> 16) & 0xff)
#define SA_CNTL MAKESA('C', 'N', 'T', 'L')
#define SA_DIAG MAKESA('D', 'I', 'A', 'G')
@@ -728,11 +732,12 @@ bad2:
uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
return;
bad1:
- uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+ uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
}
static inline void wake_up_cmv_ack(struct uea_softc *sc)
{
+ BUG_ON(sc->cmv_ack);
sc->cmv_ack = 1;
wake_up(&sc->cmv_ack_wait);
}
@@ -743,6 +748,9 @@ static inline int wait_cmv_ack(struct uea_softc *sc)
sc->cmv_ack, ACK_TIMEOUT);
sc->cmv_ack = 0;
+ uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n",
+ jiffies_to_msecs(ret));
+
if (ret < 0)
return ret;
@@ -791,6 +799,12 @@ static int uea_cmv(struct uea_softc *sc,
struct cmv cmv;
int ret;
+ uea_enters(INS_TO_USBDEV(sc));
+ uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
+ "offset : 0x%04x, data : 0x%08x\n",
+ FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function),
+ GETSA1(address), GETSA2(address), GETSA3(address),
+ GETSA4(address), offset, data);
/* we send a request, but we expect a reply */
sc->cmv_function = function | 0x2;
sc->cmv_idx++;
@@ -808,7 +822,9 @@ static int uea_cmv(struct uea_softc *sc,
ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
if (ret < 0)
return ret;
- return wait_cmv_ack(sc);
+ ret = wait_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
}
static inline int uea_read_cmv(struct uea_softc *sc,
@@ -922,7 +938,7 @@ static int uea_stat(struct uea_softc *sc)
* we check the status again in order to detect the failure earlier
*/
if (sc->stats.phy.flags) {
- uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+ uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
sc->stats.phy.flags);
return 0;
}
@@ -1063,7 +1079,13 @@ static int uea_start_reset(struct uea_softc *sc)
uea_enters(INS_TO_USBDEV(sc));
uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
+ /* mask interrupt */
sc->booting = 1;
+ /* We need to set this here because, a ack timeout could have occured,
+ * but before we start the reboot, the ack occurs and set this to 1.
+ * So we will failed to wait Ready CMV.
+ */
+ sc->cmv_ack = 0;
UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
/* reset statistics */
@@ -1089,6 +1111,7 @@ static int uea_start_reset(struct uea_softc *sc)
msleep(1000);
sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+ /* demask interrupt */
sc->booting = 0;
/* start loading DSP */
@@ -1101,6 +1124,8 @@ static int uea_start_reset(struct uea_softc *sc)
if (ret < 0)
return ret;
+ uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n");
+
/* Enter in R-IDLE (cmv) until instructed otherwise */
ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
if (ret < 0)
@@ -1121,6 +1146,7 @@ static int uea_start_reset(struct uea_softc *sc)
}
/* Enter in R-ACT-REQ */
ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+ uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
out:
release_firmware(cmvs_fw);
sc->reset = 0;
@@ -1235,6 +1261,7 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
wake_up_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
return;
}
@@ -1249,6 +1276,7 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
sc->data = sc->data << 16 | sc->data >> 16;
wake_up_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
return;
bad2:
@@ -1256,12 +1284,14 @@ bad2:
"Function : %d, Subfunction : %d\n",
FUNCTION_TYPE(cmv->bFunction),
FUNCTION_SUBTYPE(cmv->bFunction));
+ uea_leaves(INS_TO_USBDEV(sc));
return;
bad1:
uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
"wPreamble %d, bDirection %d\n",
le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+ uea_leaves(INS_TO_USBDEV(sc));
}
/*
@@ -1346,7 +1376,7 @@ static int uea_boot(struct uea_softc *sc)
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"urb submition failed with error %d\n", ret);
- goto err1;
+ goto err;
}
sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
@@ -1360,10 +1390,10 @@ static int uea_boot(struct uea_softc *sc)
err2:
usb_kill_urb(sc->urb_int);
-err1:
- kfree(intr);
err:
usb_free_urb(sc->urb_int);
+ sc->urb_int = NULL;
+ kfree(intr);
uea_leaves(INS_TO_USBDEV(sc));
return -ENOMEM;
}
@@ -1508,7 +1538,7 @@ static ssize_t read_##name(struct device *dev, \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
- mutex_lock(&uea_mutex); \
+ mutex_lock(&uea_mutex); \
sc = dev_to_uea(dev); \
if (!sc) \
goto out; \
@@ -1516,7 +1546,7 @@ static ssize_t read_##name(struct device *dev, \
if (reset) \
sc->stats.phy.name = 0; \
out: \
- mutex_unlock(&uea_mutex); \
+ mutex_unlock(&uea_mutex); \
return ret; \
} \
\
@@ -1643,7 +1673,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
if (!sc) {
- uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+ uea_err(usb, "uea_init: not enough memory !\n");
return -ENOMEM;
}
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index ff03184da403..a08787e253aa 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -99,4 +99,11 @@ config USB_OTG_WHITELIST
normal Linux-USB hosts do (other than the warning), and is
convenient for many stages of product development.
+config USB_OTG_BLACKLIST_HUB
+ bool "Disable external hubs"
+ depends on USB_OTG
+ help
+ If you say Y here, then Linux will refuse to enumerate
+ external hubs. OTG hosts are allowed to reduce hardware
+ and software costs by not supporting external hubs.
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 0d2193b69235..66b78404ab34 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
if (hcd->driver->suspend) {
retval = hcd->driver->suspend(hcd, message);
- if (retval) {
- dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n",
- retval);
+ suspend_report_result(hcd->driver->suspend, retval);
+ if (retval)
goto done;
- }
}
synchronize_irq(dev->irq);
@@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
* some device state (e.g. as part of clock reinit).
*/
retval = pci_set_power_state (dev, PCI_D3hot);
+ suspend_report_result(pci_set_power_state, retval);
if (retval == 0) {
int wake = device_can_wakeup(&hcd->self.root_hub->dev);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 8e65f7a237e4..0c87f73f2933 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -836,6 +836,13 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
+#ifdef CONFIG_USB_OTG_BLACKLIST_HUB
+ if (hdev->parent) {
+ dev_warn(&intf->dev, "ignoring external hub\n");
+ return -ENODEV;
+ }
+#endif
+
/* Some hubs have a subclass of 1, which AFAICT according to the */
/* specs is not defined, but it works */
if ((desc->desc.bInterfaceSubClass != 0) &&
@@ -1022,7 +1029,6 @@ void usb_set_device_state(struct usb_device *udev,
recursively_mark_NOTATTACHED(udev);
spin_unlock_irqrestore(&device_state_lock, flags);
}
-EXPORT_SYMBOL(usb_set_device_state);
#ifdef CONFIG_PM
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index d7352aa73b5e..b7fdc1cd134a 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1194,7 +1194,6 @@ EXPORT_SYMBOL(usb_disabled);
EXPORT_SYMBOL_GPL(usb_get_intf);
EXPORT_SYMBOL_GPL(usb_put_intf);
-EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_put_dev);
EXPORT_SYMBOL(usb_get_dev);
EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
@@ -1208,7 +1207,6 @@ EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_altnum_to_altsetting);
EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_disconnect);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d80f71877d68..363b2ad74ae6 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -69,11 +69,11 @@ choice
often need board-specific hooks.
config USB_GADGET_NET2280
- boolean "NetChip 2280"
+ boolean "NetChip 228x"
depends on PCI
select USB_GADGET_DUALSPEED
help
- NetChip 2280 is a PCI based USB peripheral controller which
+ NetChip 2280 / 2282 is a PCI based USB peripheral controller which
supports both full and high speed USB 2.0 data transfers.
It has six configurable endpoints, as well as endpoint zero
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 865858cfd1c2..b8d0b7825bf3 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1709,7 +1709,7 @@ static int __devexit at91udc_remove(struct platform_device *dev)
}
#ifdef CONFIG_PM
-static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level)
+static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg)
{
struct at91_udc *udc = platform_get_drvdata(dev);
@@ -1731,7 +1731,7 @@ static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level)
return 0;
}
-static int at91udc_resume(struct platform_device *dev, u32 level)
+static int at91udc_resume(struct platform_device *dev)
{
struct at91_udc *udc = platform_get_drvdata(dev);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index c3d8e5c5bf28..9c4422ac9de4 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2338,6 +2338,9 @@ autoconf_fail:
hs_subset_descriptors();
}
+ device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+ usb_gadget_set_selfpowered (gadget);
+
/* For now RNDIS is always a second config */
if (rndis)
device_desc.bNumConfigurations = 2;
@@ -2361,9 +2364,6 @@ autoconf_fail:
#endif
#endif /* DUALSPEED */
- device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
- usb_gadget_set_selfpowered (gadget);
-
if (gadget->is_otg) {
otg_descriptor.bmAttributes |= USB_OTG_HNP,
eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index cf3be299e353..6f887478b148 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -71,6 +71,12 @@
* requirement amounts to two 16K buffers, size configurable by a parameter.
* Support is included for both full-speed and high-speed operation.
*
+ * Note that the driver is slightly non-portable in that it assumes a
+ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
+ * interrupt-in endpoints. With most device controllers this isn't an
+ * issue, but there may be some with hardware restrictions that prevent
+ * a buffer from being used by more than one endpoint.
+ *
* Module options:
*
* file=filename[,filename...]
@@ -108,6 +114,14 @@
* setting are not allowed when the medium is loaded.
*
* This gadget driver is heavily based on "Gadget Zero" by David Brownell.
+ * The driver's SCSI command interface was based on the "Information
+ * technology - Small Computer System Interface - 2" document from
+ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
+ * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
+ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
+ * "Universal Serial Bus Mass Storage Class UFI Command Specification"
+ * document, Revision 1.0, December 14, 1998, available at
+ * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
*/
@@ -334,11 +348,9 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MAX_LUNS 8
- /* Arggh! There should be a module_param_array_named macro! */
-static char *file[MAX_LUNS];
-static int ro[MAX_LUNS];
-
static struct {
+ char *file[MAX_LUNS];
+ int ro[MAX_LUNS];
int num_filenames;
int num_ros;
unsigned int nluns;
@@ -370,10 +382,11 @@ static struct {
};
-module_param_array(file, charp, &mod_data.num_filenames, S_IRUGO);
+module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
+ S_IRUGO);
MODULE_PARM_DESC(file, "names of backing files or devices");
-module_param_array(ro, bool, &mod_data.num_ros, S_IRUGO);
+module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
MODULE_PARM_DESC(ro, "true to force read-only");
module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
@@ -1795,6 +1808,7 @@ static int do_write(struct fsg_dev *fsg)
* the bulk-out maxpacket size */
bh->outreq->length = bh->bulk_out_intended_length =
amount;
+ bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
@@ -2398,6 +2412,7 @@ static int throw_away_data(struct fsg_dev *fsg)
* the bulk-out maxpacket size */
bh->outreq->length = bh->bulk_out_intended_length =
amount;
+ bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
@@ -3029,6 +3044,7 @@ static int get_next_command(struct fsg_dev *fsg)
/* Queue a request to read a Bulk-only CBW */
set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+ bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
@@ -3859,7 +3875,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
for (i = 0; i < fsg->nluns; ++i) {
curlun = &fsg->luns[i];
- curlun->ro = ro[i];
+ curlun->ro = mod_data.ro[i];
curlun->dev.parent = &gadget->dev;
curlun->dev.driver = &fsg_driver.driver;
dev_set_drvdata(&curlun->dev, fsg);
@@ -3876,8 +3892,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
kref_get(&fsg->ref);
}
- if (file[i] && *file[i]) {
- if ((rc = open_backing_file(curlun, file[i])) != 0)
+ if (mod_data.file[i] && *mod_data.file[i]) {
+ if ((rc = open_backing_file(curlun,
+ mod_data.file[i])) != 0)
goto out;
} else if (!mod_data.removable) {
ERROR(fsg, "no file given for LUN%d\n", i);
@@ -3953,6 +3970,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
for (i = 0; i < NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &fsg->buffhds[i];
+ /* 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);
if (!bh->buf)
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index c4081407171f..aa80f0910720 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -100,9 +100,9 @@
#define gadget_is_musbhsfc(g) 0
#endif
-/* Mentor high speed "dual role" controller, peripheral mode */
-#ifdef CONFIG_USB_GADGET_MUSBHDRC
-#define gadget_is_musbhdrc(g) !strcmp("musbhdrc_udc", (g)->name)
+/* Mentor high speed "dual role" controller, in peripheral role */
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+#define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name)
#else
#define gadget_is_musbhdrc(g) 0
#endif
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 3f618ce6998d..0eb010a3f5bc 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -810,7 +810,7 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (value == 0)
data->state = STATE_EP_ENABLED;
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_SPEED_HIGH:
/* fails if caller didn't provide that descriptor... */
value = usb_ep_enable (ep, &data->hs_desc);
@@ -982,7 +982,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
/* assume that was SET_CONFIGURATION */
if (dev->current_config) {
unsigned power;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (dev->gadget->speed == USB_SPEED_HIGH)
power = dev->hs_config->bMaxPower;
else
@@ -1262,7 +1262,7 @@ static struct file_operations ep0_io_operations = {
* Unrecognized ep0 requests may be handled in user space.
*/
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
static void make_qualifier (struct dev_data *dev)
{
struct usb_qualifier_descriptor qual;
@@ -1291,7 +1291,7 @@ static int
config_buf (struct dev_data *dev, u8 type, unsigned index)
{
int len;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
int hs;
#endif
@@ -1299,7 +1299,7 @@ config_buf (struct dev_data *dev, u8 type, unsigned index)
if (index > 0)
return -EINVAL;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
hs = (dev->gadget->speed == USB_SPEED_HIGH);
if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs;
@@ -1335,12 +1335,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->state = STATE_CONNECTED;
dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) {
ERROR (dev, "no high speed config??\n");
return -EINVAL;
}
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
INFO (dev, "connected\n");
event = next_event (dev, GADGETFS_CONNECT);
@@ -1352,11 +1352,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* ... down_trylock (&data->lock) ... */
if (data->state != STATE_EP_DEFER_ENABLE)
continue;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH)
value = usb_ep_enable (ep, &data->hs_desc);
else
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
value = usb_ep_enable (ep, &data->desc);
if (value) {
ERROR (dev, "deferred %s enable --> %d\n",
@@ -1391,7 +1391,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min (w_length, (u16) sizeof *dev->dev);
req->buf = dev->dev;
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!dev->hs_config)
break;
@@ -1428,7 +1428,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
// user mode expected to disable endpoints
} else {
u8 config, power;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH) {
config = dev->hs_config->bConfigurationValue;
power = dev->hs_config->bMaxPower;
@@ -1614,6 +1614,7 @@ static int activate_ep_files (struct dev_data *dev)
data, &ep_config_operations,
&data->dentry);
if (!data->inode) {
+ usb_ep_free_request(ep, data->req);
kfree (data);
goto enomem;
}
@@ -1728,7 +1729,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
}
static struct usb_gadget_driver gadgetfs_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
#else
.speed = USB_SPEED_FULL,
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index fb73dc100535..0b9293493957 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -26,6 +26,8 @@
* Copyright (C) 2003 David Brownell
* Copyright (C) 2003-2005 PLX Technology, Inc.
*
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -71,8 +73,8 @@
#include <asm/unaligned.h>
-#define DRIVER_DESC "PLX NET2280 USB Peripheral Controller"
-#define DRIVER_VERSION "2005 Feb 03"
+#define DRIVER_DESC "PLX NET228x USB Peripheral Controller"
+#define DRIVER_VERSION "2005 Sept 27"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */
@@ -118,7 +120,7 @@ module_param (fifo_mode, ushort, 0644);
/* enable_suspend -- When enabled, the driver will respond to
* USB suspend requests by powering down the NET2280. Otherwise,
* USB suspend requests will be ignored. This is acceptible for
- * self-powered devices, and helps avoid some quirks.
+ * self-powered devices
*/
static int enable_suspend = 0;
@@ -223,6 +225,11 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
ep->is_in = (tmp & USB_DIR_IN) != 0;
if (!ep->is_in)
writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+ else if (dev->pdev->device != 0x2280) {
+ /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
+ writel ((1 << CLEAR_NAK_OUT_PACKETS)
+ | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
+ }
writel (tmp, &ep->regs->ep_cfg);
@@ -232,8 +239,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
writel (tmp, &dev->regs->pciirqenb0);
tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
- | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
- | readl (&ep->regs->ep_irqenb);
+ | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
+ if (dev->pdev->device == 0x2280)
+ tmp |= readl (&ep->regs->ep_irqenb);
writel (tmp, &ep->regs->ep_irqenb);
} else { /* dma, per-request */
tmp = (1 << (8 + ep->num)); /* completion */
@@ -314,10 +322,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
/* init to our chosen defaults, notably so that we NAK OUT
* packets until the driver queues a read (+note erratum 0112)
*/
- tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
+ if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
+ tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
| (1 << SET_NAK_OUT_PACKETS)
| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
| (1 << CLEAR_INTERRUPT_MODE);
+ } else {
+ /* added for 2282 */
+ tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
+ | (1 << CLEAR_NAK_OUT_PACKETS)
+ | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
+ | (1 << CLEAR_INTERRUPT_MODE);
+ }
if (ep->num != 0) {
tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
@@ -326,14 +342,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
writel (tmp, &ep->regs->ep_rsp);
/* scrub most status bits, and flush any fifo state */
- writel ( (1 << TIMEOUT)
+ if (ep->dev->pdev->device == 0x2280)
+ tmp = (1 << FIFO_OVERFLOW)
+ | (1 << FIFO_UNDERFLOW);
+ else
+ tmp = 0;
+
+ writel (tmp | (1 << TIMEOUT)
| (1 << USB_STALL_SENT)
| (1 << USB_IN_NAK_SENT)
| (1 << USB_IN_ACK_RCVD)
| (1 << USB_OUT_PING_NAK_SENT)
| (1 << USB_OUT_ACK_SENT)
- | (1 << FIFO_OVERFLOW)
- | (1 << FIFO_UNDERFLOW)
| (1 << FIFO_FLUSH)
| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
@@ -718,7 +738,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
*/
if (ep->is_in)
dmacount |= (1 << DMA_DIRECTION);
- else if ((dmacount % ep->ep.maxpacket) != 0)
+ if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
dmacount |= (1 << END_OF_CHAIN);
req->valid = valid;
@@ -760,9 +780,12 @@ static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
{
struct net2280_dma_regs __iomem *dma = ep->dma;
+ unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
+
+ if (ep->dev->pdev->device != 0x2280)
+ tmp |= (1 << END_OF_CHAIN);
- writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
- &dma->dmacount);
+ writel (tmp, &dma->dmacount);
writel (readl (&dma->dmastat), &dma->dmastat);
writel (td_dma, &dma->dmadesc);
@@ -2110,7 +2133,11 @@ static void handle_ep_small (struct net2280_ep *ep)
VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
ep->ep.name, t, req ? &req->req : 0);
#endif
- writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+ if (!ep->is_in || ep->dev->pdev->device == 0x2280)
+ writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+ else
+ /* Added for 2282 */
+ writel (t, &ep->regs->ep_stat);
/* for ep0, monitor token irqs to catch data stage length errors
* and to synchronize on status.
@@ -2139,7 +2166,7 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1;
set_halt (ep);
mode = 2;
- } else if (!req && ep->stopped)
+ } else if (!req && !ep->stopped)
write_fifo (ep, NULL);
}
} else {
@@ -2214,7 +2241,8 @@ static void handle_ep_small (struct net2280_ep *ep)
if (likely (req)) {
req->td->dmacount = 0;
t = readl (&ep->regs->ep_avail);
- dma_done (ep, req, count, t);
+ dma_done (ep, req, count,
+ (ep->out_overflow || t) ? -EOVERFLOW : 0);
}
/* also flush to prevent erratum 0106 trouble */
@@ -2252,9 +2280,7 @@ static void handle_ep_small (struct net2280_ep *ep)
/* if we wrote it all, we're usually done */
if (req->req.actual == req->req.length) {
if (ep->num == 0) {
- /* wait for control status */
- if (mode != 2)
- req = NULL;
+ /* send zlps until the status stage */
} else if (!req->req.zero || len != ep->ep.maxpacket)
mode = 2;
}
@@ -2337,7 +2363,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
u32 raw [2];
struct usb_ctrlrequest r;
} u;
- int tmp = 0;
+ int tmp;
struct net2280_request *req;
if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
@@ -2364,14 +2390,19 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
}
ep->stopped = 0;
dev->protocol_stall = 0;
- writel ( (1 << TIMEOUT)
+
+ if (ep->dev->pdev->device == 0x2280)
+ tmp = (1 << FIFO_OVERFLOW)
+ | (1 << FIFO_UNDERFLOW);
+ else
+ tmp = 0;
+
+ writel (tmp | (1 << TIMEOUT)
| (1 << USB_STALL_SENT)
| (1 << USB_IN_NAK_SENT)
| (1 << USB_IN_ACK_RCVD)
| (1 << USB_OUT_PING_NAK_SENT)
| (1 << USB_OUT_ACK_SENT)
- | (1 << FIFO_OVERFLOW)
- | (1 << FIFO_UNDERFLOW)
| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
@@ -2385,6 +2416,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
cpu_to_le32s (&u.raw [0]);
cpu_to_le32s (&u.raw [1]);
+ 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)
@@ -2594,10 +2627,17 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
writel (stat, &dev->regs->irqstat1);
/* some status we can just ignore */
- stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
- | (1 << SUSPEND_REQUEST_INTERRUPT)
- | (1 << RESUME_INTERRUPT)
- | (1 << SOF_INTERRUPT));
+ if (dev->pdev->device == 0x2280)
+ stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+ | (1 << SUSPEND_REQUEST_INTERRUPT)
+ | (1 << RESUME_INTERRUPT)
+ | (1 << SOF_INTERRUPT));
+ else
+ stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+ | (1 << RESUME_INTERRUPT)
+ | (1 << SOF_DOWN_INTERRUPT)
+ | (1 << SOF_INTERRUPT));
+
if (!stat)
return;
// DEBUG (dev, "irqstat1 %08x\n", stat);
@@ -2702,6 +2742,10 @@ static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r)
{
struct net2280 *dev = _dev;
+ /* shared interrupt, not ours */
+ if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
+ return IRQ_NONE;
+
spin_lock (&dev->lock);
/* handle disconnect, dma, and more */
@@ -2789,13 +2833,13 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
}
/* alloc, and start init */
- dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+ dev = kzalloc (sizeof *dev, SLAB_KERNEL);
if (dev == NULL){
retval = -ENOMEM;
goto done;
}
- memset (dev, 0, sizeof *dev);
+ pci_set_drvdata (pdev, dev);
spin_lock_init (&dev->lock);
dev->pdev = pdev;
dev->gadget.ops = &net2280_ops;
@@ -2908,7 +2952,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
/* done */
- pci_set_drvdata (pdev, dev);
INFO (dev, "%s\n", driver_desc);
INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
bufp, base, dev->chiprev);
@@ -2939,6 +2982,13 @@ static struct pci_device_id pci_ids [] = { {
.device = 0x2280,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+}, {
+ .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+ .class_mask = ~0,
+ .vendor = 0x17cc,
+ .device = 0x2282,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
}, { /* end: all zeroes */ }
};
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index fff4509cf340..957d6df34015 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -22,420 +22,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*-------------------------------------------------------------------------*/
-
-/* NET2280 MEMORY MAPPED REGISTERS
- *
- * The register layout came from the chip documentation, and the bit
- * number definitions were extracted from chip specification.
- *
- * Use the shift operator ('<<') to build bit masks, with readl/writel
- * to access the registers through PCI.
- */
-
-/* main registers, BAR0 + 0x0000 */
-struct net2280_regs {
- // offset 0x0000
- u32 devinit;
-#define LOCAL_CLOCK_FREQUENCY 8
-#define FORCE_PCI_RESET 7
-#define PCI_ID 6
-#define PCI_ENABLE 5
-#define FIFO_SOFT_RESET 4
-#define CFG_SOFT_RESET 3
-#define PCI_SOFT_RESET 2
-#define USB_SOFT_RESET 1
-#define M8051_RESET 0
- u32 eectl;
-#define EEPROM_ADDRESS_WIDTH 23
-#define EEPROM_CHIP_SELECT_ACTIVE 22
-#define EEPROM_PRESENT 21
-#define EEPROM_VALID 20
-#define EEPROM_BUSY 19
-#define EEPROM_CHIP_SELECT_ENABLE 18
-#define EEPROM_BYTE_READ_START 17
-#define EEPROM_BYTE_WRITE_START 16
-#define EEPROM_READ_DATA 8
-#define EEPROM_WRITE_DATA 0
- u32 eeclkfreq;
- u32 _unused0;
- // offset 0x0010
-
- u32 pciirqenb0; /* interrupt PCI master ... */
-#define SETUP_PACKET_INTERRUPT_ENABLE 7
-#define ENDPOINT_F_INTERRUPT_ENABLE 6
-#define ENDPOINT_E_INTERRUPT_ENABLE 5
-#define ENDPOINT_D_INTERRUPT_ENABLE 4
-#define ENDPOINT_C_INTERRUPT_ENABLE 3
-#define ENDPOINT_B_INTERRUPT_ENABLE 2
-#define ENDPOINT_A_INTERRUPT_ENABLE 1
-#define ENDPOINT_0_INTERRUPT_ENABLE 0
- u32 pciirqenb1;
-#define PCI_INTERRUPT_ENABLE 31
-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-#define GPIO_INTERRUPT_ENABLE 13
-#define DMA_D_INTERRUPT_ENABLE 12
-#define DMA_C_INTERRUPT_ENABLE 11
-#define DMA_B_INTERRUPT_ENABLE 10
-#define DMA_A_INTERRUPT_ENABLE 9
-#define EEPROM_DONE_INTERRUPT_ENABLE 8
-#define VBUS_INTERRUPT_ENABLE 7
-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-#define RESUME_INTERRUPT_ENABLE 1
-#define SOF_INTERRUPT_ENABLE 0
- u32 cpu_irqenb0; /* ... or onboard 8051 */
-#define SETUP_PACKET_INTERRUPT_ENABLE 7
-#define ENDPOINT_F_INTERRUPT_ENABLE 6
-#define ENDPOINT_E_INTERRUPT_ENABLE 5
-#define ENDPOINT_D_INTERRUPT_ENABLE 4
-#define ENDPOINT_C_INTERRUPT_ENABLE 3
-#define ENDPOINT_B_INTERRUPT_ENABLE 2
-#define ENDPOINT_A_INTERRUPT_ENABLE 1
-#define ENDPOINT_0_INTERRUPT_ENABLE 0
- u32 cpu_irqenb1;
-#define CPU_INTERRUPT_ENABLE 31
-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-#define PCI_INTA_INTERRUPT_ENABLE 24
-#define PCI_PME_INTERRUPT_ENABLE 23
-#define PCI_SERR_INTERRUPT_ENABLE 22
-#define PCI_PERR_INTERRUPT_ENABLE 21
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-#define GPIO_INTERRUPT_ENABLE 13
-#define DMA_D_INTERRUPT_ENABLE 12
-#define DMA_C_INTERRUPT_ENABLE 11
-#define DMA_B_INTERRUPT_ENABLE 10
-#define DMA_A_INTERRUPT_ENABLE 9
-#define EEPROM_DONE_INTERRUPT_ENABLE 8
-#define VBUS_INTERRUPT_ENABLE 7
-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-#define RESUME_INTERRUPT_ENABLE 1
-#define SOF_INTERRUPT_ENABLE 0
-
- // offset 0x0020
- u32 _unused1;
- u32 usbirqenb1;
-#define USB_INTERRUPT_ENABLE 31
-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-#define PCI_INTA_INTERRUPT_ENABLE 24
-#define PCI_PME_INTERRUPT_ENABLE 23
-#define PCI_SERR_INTERRUPT_ENABLE 22
-#define PCI_PERR_INTERRUPT_ENABLE 21
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-#define GPIO_INTERRUPT_ENABLE 13
-#define DMA_D_INTERRUPT_ENABLE 12
-#define DMA_C_INTERRUPT_ENABLE 11
-#define DMA_B_INTERRUPT_ENABLE 10
-#define DMA_A_INTERRUPT_ENABLE 9
-#define EEPROM_DONE_INTERRUPT_ENABLE 8
-#define VBUS_INTERRUPT_ENABLE 7
-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-#define RESUME_INTERRUPT_ENABLE 1
-#define SOF_INTERRUPT_ENABLE 0
- u32 irqstat0;
-#define INTA_ASSERTED 12
-#define SETUP_PACKET_INTERRUPT 7
-#define ENDPOINT_F_INTERRUPT 6
-#define ENDPOINT_E_INTERRUPT 5
-#define ENDPOINT_D_INTERRUPT 4
-#define ENDPOINT_C_INTERRUPT 3
-#define ENDPOINT_B_INTERRUPT 2
-#define ENDPOINT_A_INTERRUPT 1
-#define ENDPOINT_0_INTERRUPT 0
- u32 irqstat1;
-#define POWER_STATE_CHANGE_INTERRUPT 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
-#define PCI_PARITY_ERROR_INTERRUPT 25
-#define PCI_INTA_INTERRUPT 24
-#define PCI_PME_INTERRUPT 23
-#define PCI_SERR_INTERRUPT 22
-#define PCI_PERR_INTERRUPT 21
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
-#define PCI_RETRY_ABORT_INTERRUPT 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
-#define GPIO_INTERRUPT 13
-#define DMA_D_INTERRUPT 12
-#define DMA_C_INTERRUPT 11
-#define DMA_B_INTERRUPT 10
-#define DMA_A_INTERRUPT 9
-#define EEPROM_DONE_INTERRUPT 8
-#define VBUS_INTERRUPT 7
-#define CONTROL_STATUS_INTERRUPT 6
-#define ROOT_PORT_RESET_INTERRUPT 4
-#define SUSPEND_REQUEST_INTERRUPT 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
-#define RESUME_INTERRUPT 1
-#define SOF_INTERRUPT 0
- // offset 0x0030
- u32 idxaddr;
- u32 idxdata;
- u32 fifoctl;
-#define PCI_BASE2_RANGE 16
-#define IGNORE_FIFO_AVAILABILITY 3
-#define PCI_BASE2_SELECT 2
-#define FIFO_CONFIGURATION_SELECT 0
- u32 _unused2;
- // offset 0x0040
- u32 memaddr;
-#define START 28
-#define DIRECTION 27
-#define FIFO_DIAGNOSTIC_SELECT 24
-#define MEMORY_ADDRESS 0
- u32 memdata0;
- u32 memdata1;
- u32 _unused3;
- // offset 0x0050
- u32 gpioctl;
-#define GPIO3_LED_SELECT 12
-#define GPIO3_INTERRUPT_ENABLE 11
-#define GPIO2_INTERRUPT_ENABLE 10
-#define GPIO1_INTERRUPT_ENABLE 9
-#define GPIO0_INTERRUPT_ENABLE 8
-#define GPIO3_OUTPUT_ENABLE 7
-#define GPIO2_OUTPUT_ENABLE 6
-#define GPIO1_OUTPUT_ENABLE 5
-#define GPIO0_OUTPUT_ENABLE 4
-#define GPIO3_DATA 3
-#define GPIO2_DATA 2
-#define GPIO1_DATA 1
-#define GPIO0_DATA 0
- u32 gpiostat;
-#define GPIO3_INTERRUPT 3
-#define GPIO2_INTERRUPT 2
-#define GPIO1_INTERRUPT 1
-#define GPIO0_INTERRUPT 0
-} __attribute__ ((packed));
-
-/* usb control, BAR0 + 0x0080 */
-struct net2280_usb_regs {
- // offset 0x0080
- u32 stdrsp;
-#define STALL_UNSUPPORTED_REQUESTS 31
-#define SET_TEST_MODE 16
-#define GET_OTHER_SPEED_CONFIGURATION 15
-#define GET_DEVICE_QUALIFIER 14
-#define SET_ADDRESS 13
-#define ENDPOINT_SET_CLEAR_HALT 12
-#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
-#define GET_STRING_DESCRIPTOR_2 10
-#define GET_STRING_DESCRIPTOR_1 9
-#define GET_STRING_DESCRIPTOR_0 8
-#define GET_SET_INTERFACE 6
-#define GET_SET_CONFIGURATION 5
-#define GET_CONFIGURATION_DESCRIPTOR 4
-#define GET_DEVICE_DESCRIPTOR 3
-#define GET_ENDPOINT_STATUS 2
-#define GET_INTERFACE_STATUS 1
-#define GET_DEVICE_STATUS 0
- u32 prodvendid;
-#define PRODUCT_ID 16
-#define VENDOR_ID 0
- u32 relnum;
- u32 usbctl;
-#define SERIAL_NUMBER_INDEX 16
-#define PRODUCT_ID_STRING_ENABLE 13
-#define VENDOR_ID_STRING_ENABLE 12
-#define USB_ROOT_PORT_WAKEUP_ENABLE 11
-#define VBUS_PIN 10
-#define TIMED_DISCONNECT 9
-#define SUSPEND_IMMEDIATELY 7
-#define SELF_POWERED_USB_DEVICE 6
-#define REMOTE_WAKEUP_SUPPORT 5
-#define PME_POLARITY 4
-#define USB_DETECT_ENABLE 3
-#define PME_WAKEUP_ENABLE 2
-#define DEVICE_REMOTE_WAKEUP_ENABLE 1
-#define SELF_POWERED_STATUS 0
- // offset 0x0090
- u32 usbstat;
-#define HIGH_SPEED 7
-#define FULL_SPEED 6
-#define GENERATE_RESUME 5
-#define GENERATE_DEVICE_REMOTE_WAKEUP 4
- u32 xcvrdiag;
-#define FORCE_HIGH_SPEED_MODE 31
-#define FORCE_FULL_SPEED_MODE 30
-#define USB_TEST_MODE 24
-#define LINE_STATE 16
-#define TRANSCEIVER_OPERATION_MODE 2
-#define TRANSCEIVER_SELECT 1
-#define TERMINATION_SELECT 0
- u32 setup0123;
- u32 setup4567;
- // offset 0x0090
- u32 _unused0;
- u32 ouraddr;
-#define FORCE_IMMEDIATE 7
-#define OUR_USB_ADDRESS 0
- u32 ourconfig;
-} __attribute__ ((packed));
-
-/* pci control, BAR0 + 0x0100 */
-struct net2280_pci_regs {
- // offset 0x0100
- u32 pcimstctl;
-#define PCI_ARBITER_PARK_SELECT 13
-#define PCI_MULTI LEVEL_ARBITER 12
-#define PCI_RETRY_ABORT_ENABLE 11
-#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
-#define DMA_READ_MULTIPLE_ENABLE 9
-#define DMA_READ_LINE_ENABLE 8
-#define PCI_MASTER_COMMAND_SELECT 6
-#define MEM_READ_OR_WRITE 0
-#define IO_READ_OR_WRITE 1
-#define CFG_READ_OR_WRITE 2
-#define PCI_MASTER_START 5
-#define PCI_MASTER_READ_WRITE 4
-#define PCI_MASTER_WRITE 0
-#define PCI_MASTER_READ 1
-#define PCI_MASTER_BYTE_WRITE_ENABLES 0
- u32 pcimstaddr;
- u32 pcimstdata;
- u32 pcimststat;
-#define PCI_ARBITER_CLEAR 2
-#define PCI_EXTERNAL_ARBITER 1
-#define PCI_HOST_MODE 0
-} __attribute__ ((packed));
-
-/* dma control, BAR0 + 0x0180 ... array of four structs like this,
- * for channels 0..3. see also struct net2280_dma: descriptor
- * that can be loaded into some of these registers.
- */
-struct net2280_dma_regs { /* [11.7] */
- // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
- u32 dmactl;
-#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
-#define DMA_CLEAR_COUNT_ENABLE 21
-#define DESCRIPTOR_POLLING_RATE 19
-#define POLL_CONTINUOUS 0
-#define POLL_1_USEC 1
-#define POLL_100_USEC 2
-#define POLL_1_MSEC 3
-#define DMA_VALID_BIT_POLLING_ENABLE 18
-#define DMA_VALID_BIT_ENABLE 17
-#define DMA_SCATTER_GATHER_ENABLE 16
-#define DMA_OUT_AUTO_START_ENABLE 4
-#define DMA_PREEMPT_ENABLE 3
-#define DMA_FIFO_VALIDATE 2
-#define DMA_ENABLE 1
-#define DMA_ADDRESS_HOLD 0
- u32 dmastat;
-#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
-#define DMA_TRANSACTION_DONE_INTERRUPT 24
-#define DMA_ABORT 1
-#define DMA_START 0
- u32 _unused0 [2];
- // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
- u32 dmacount;
-#define VALID_BIT 31
-#define DMA_DIRECTION 30
-#define DMA_DONE_INTERRUPT_ENABLE 29
-#define END_OF_CHAIN 28
-#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
-#define DMA_BYTE_COUNT 0
- u32 dmaaddr;
- u32 dmadesc;
- u32 _unused1;
-} __attribute__ ((packed));
-
-/* dedicated endpoint registers, BAR0 + 0x0200 */
-
-struct net2280_dep_regs { /* [11.8] */
- // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
- u32 dep_cfg;
- // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
- u32 dep_rsp;
- u32 _unused [2];
-} __attribute__ ((packed));
-
-/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
- * like this, for ep0 then the configurable endpoints A..F
- * ep0 reserved for control; E and F have only 64 bytes of fifo
- */
-struct net2280_ep_regs { /* [11.9] */
- // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
- u32 ep_cfg;
-#define ENDPOINT_BYTE_COUNT 16
-#define ENDPOINT_ENABLE 10
-#define ENDPOINT_TYPE 8
-#define ENDPOINT_DIRECTION 7
-#define ENDPOINT_NUMBER 0
- u32 ep_rsp;
-#define SET_NAK_OUT_PACKETS 15
-#define SET_EP_HIDE_STATUS_PHASE 14
-#define SET_EP_FORCE_CRC_ERROR 13
-#define SET_INTERRUPT_MODE 12
-#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
-#define SET_NAK_OUT_PACKETS_MODE 10
-#define SET_ENDPOINT_TOGGLE 9
-#define SET_ENDPOINT_HALT 8
-#define CLEAR_NAK_OUT_PACKETS 7
-#define CLEAR_EP_HIDE_STATUS_PHASE 6
-#define CLEAR_EP_FORCE_CRC_ERROR 5
-#define CLEAR_INTERRUPT_MODE 4
-#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
-#define CLEAR_NAK_OUT_PACKETS_MODE 2
-#define CLEAR_ENDPOINT_TOGGLE 1
-#define CLEAR_ENDPOINT_HALT 0
- u32 ep_irqenb;
-#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
-#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
-#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
-#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
-#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
-#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
- u32 ep_stat;
-#define FIFO_VALID_COUNT 24
-#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
-#define TIMEOUT 21
-#define USB_STALL_SENT 20
-#define USB_IN_NAK_SENT 19
-#define USB_IN_ACK_RCVD 18
-#define USB_OUT_PING_NAK_SENT 17
-#define USB_OUT_ACK_SENT 16
-#define FIFO_OVERFLOW 13
-#define FIFO_UNDERFLOW 12
-#define FIFO_FULL 11
-#define FIFO_EMPTY 10
-#define FIFO_FLUSH 9
-#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
-#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
-#define NAK_OUT_PACKETS 4
-#define DATA_PACKET_RECEIVED_INTERRUPT 3
-#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
-#define DATA_OUT_PING_TOKEN_INTERRUPT 1
-#define DATA_IN_TOKEN_INTERRUPT 0
- // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
- u32 ep_avail;
- u32 ep_data;
- u32 _unused0 [2];
-} __attribute__ ((packed));
+#include <linux/usb/net2280.h>
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 51424f66a765..68e3d8f5da89 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -572,9 +572,10 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
switch (status) {
case 0: /* normal completion? */
- if (ep == dev->out_ep)
+ if (ep == dev->out_ep) {
check_read_data (dev, ep, req);
- else
+ memset (req->buf, 0x55, req->length);
+ } else
reinit_write_data (dev, ep, req);
break;
@@ -626,6 +627,8 @@ source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
if (strcmp (ep->name, EP_IN_NAME) == 0)
reinit_write_data (ep->driver_data, ep, req);
+ else
+ memset (req->buf, 0x55, req->length);
status = usb_ep_queue (ep, req, gfp_flags);
if (status) {
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 1e03f1a5a5fd..a1bd2bea6deb 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -350,7 +350,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
/* PCI driver selection metadata; PCI hotplugging uses this */
static const struct pci_device_id pci_ids [] = { {
/* handle any USB 2.0 EHCI controller */
- PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
.driver_data = (unsigned long) &ehci_pci_hc_driver,
},
{ /* end: all zeroes */ }
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 980030d684d5..6b7350b52419 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -20,7 +20,7 @@
#include <asm/arch/board.h>
#ifndef CONFIG_ARCH_AT91RM9200
-#error "This file is AT91RM9200 bus glue. CONFIG_ARCH_AT91RM9200 must be defined."
+#error "CONFIG_ARCH_AT91RM9200 must be defined."
#endif
/* interface and function clocks */
@@ -84,8 +84,6 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
* 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.
- *
- * Store this function in the HCD's struct pci_driver as probe().
*/
int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev)
{
@@ -148,7 +146,6 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *
}
-/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
@@ -166,11 +163,11 @@ static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pde
usb_remove_hcd(hcd);
at91_stop_hc(pdev);
iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- clk_put(fclk);
- clk_put(iclk);
- fclk = iclk = NULL;
+ clk_put(fclk);
+ clk_put(iclk);
+ fclk = iclk = NULL;
dev_set_drvdata(&pdev->dev, NULL);
return 0;
@@ -235,8 +232,8 @@ static const struct hc_driver ohci_at91_hc_driver = {
.hub_control = ohci_hub_control,
#ifdef CONFIG_PM
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
@@ -254,21 +251,21 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *dev)
}
#ifdef CONFIG_PM
-static int ohci_hcd_at91_drv_suspend(struct platform_device *dev, u32 state, u32 level)
-{
- printk("%s(%s:%d): not implemented yet\n",
- __func__, __FILE__, __LINE__);
+/* REVISIT suspend/resume look "too" simple here */
+
+static int
+ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg)
+{
clk_disable(fclk);
+ clk_disable(iclk);
return 0;
}
-static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state)
+static int ohci_hcd_at91_drv_resume(struct platform_device *dev)
{
- printk("%s(%s:%d): not implemented yet\n",
- __func__, __FILE__, __LINE__);
-
+ clk_enable(iclk);
clk_enable(fclk);
return 0;
@@ -278,6 +275,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state)
#define ohci_hcd_at91_drv_resume NULL
#endif
+MODULE_ALIAS("at91rm9200-ohci");
+
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
.remove = ohci_hcd_at91_drv_remove,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 1bfe96f4d045..b268537e389e 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -206,7 +206,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
static const struct pci_device_id pci_ids [] = { {
/* handle any USB OHCI controller */
- PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0),
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
.driver_data = (unsigned long) &ohci_pci_hc_driver,
}, { /* end: all zeroes */ }
};
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 682bf2215660..1da5de573a6f 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -30,6 +30,7 @@
/* clock device associated with the hcd */
static struct clk *clk;
+static struct clk *usb_clk;
/* forward definitions */
@@ -37,7 +38,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
/* conversion functions */
-struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
+static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
{
return hcd->self.controller->platform_data;
}
@@ -47,6 +48,10 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
struct s3c2410_hcd_info *info = dev->dev.platform_data;
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
+
+ clk_enable(usb_clk);
+ mdelay(2); /* let the bus clock stabilise */
+
clk_enable(clk);
if (info != NULL) {
@@ -75,6 +80,7 @@ static void s3c2410_stop_hc(struct platform_device *dev)
}
clk_disable(clk);
+ clk_disable(usb_clk);
}
/* ohci_s3c2410_hub_status_data
@@ -316,7 +322,8 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
*
*/
-void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
+static void
+usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
@@ -334,8 +341,8 @@ void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
* through the hotplug entry's driver_data.
*
*/
-int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
- struct platform_device *dev)
+static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
+ struct platform_device *dev)
{
struct usb_hcd *hcd = NULL;
int retval;
@@ -353,14 +360,21 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
dev_err(&dev->dev, "request_mem_region failed");
retval = -EBUSY;
- goto err0;
+ goto err_put;
}
- clk = clk_get(NULL, "usb-host");
+ clk = clk_get(&dev->dev, "usb-host");
if (IS_ERR(clk)) {
dev_err(&dev->dev, "cannot get usb-host clock\n");
retval = -ENOENT;
- goto err1;
+ goto err_mem;
+ }
+
+ usb_clk = clk_get(&dev->dev, "upll");
+ if (IS_ERR(usb_clk)) {
+ dev_err(&dev->dev, "cannot get usb-host clock\n");
+ retval = -ENOENT;
+ goto err_clk;
}
s3c2410_start_hc(dev, hcd);
@@ -369,26 +383,29 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
if (!hcd->regs) {
dev_err(&dev->dev, "ioremap failed\n");
retval = -ENOMEM;
- goto err2;
+ goto err_ioremap;
}
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
if (retval != 0)
- goto err2;
+ goto err_ioremap;
return 0;
- err2:
+ err_ioremap:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
+ clk_put(usb_clk);
+
+ err_clk:
clk_put(clk);
- err1:
+ err_mem:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err0:
+ err_put:
usb_put_hcd(hcd);
return retval;
}
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 9e81c26313f9..1045f846fbe2 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/acpi.h>
+#include "pci-quirks.h"
#define UHCI_USBLEGSUP 0xc0 /* legacy support */
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
new file mode 100644
index 000000000000..1564edfff6fe
--- /dev/null
+++ b/drivers/usb/host/pci-quirks.h
@@ -0,0 +1,7 @@
+#ifndef __LINUX_USB_PCI_QUIRKS_H
+#define __LINUX_USB_PCI_QUIRKS_H
+
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+
+#endif /* __LINUX_USB_PCI_QUIRKS_H */
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 134d2000128a..302aa1ec312f 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -67,11 +67,11 @@ module_param(pc_debug, int, 0644);
static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
} local_info_t;
-static void sl811_cs_release(dev_link_t * link);
+static void sl811_cs_release(struct pcmcia_device * link);
/*====================================================================*/
@@ -138,41 +138,27 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
/*====================================================================*/
-static void sl811_cs_detach(struct pcmcia_device *p_dev)
+static void sl811_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DBG(0, "sl811_cs_detach(0x%p)\n", link);
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- sl811_cs_release(link);
+ sl811_cs_release(link);
/* This points to the parent local_info_t struct */
kfree(link->priv);
}
-static void sl811_cs_release(dev_link_t * link)
+static void sl811_cs_release(struct pcmcia_device * link)
{
-
DBG(0, "sl811_cs_release(0x%p)\n", link);
- /* Unlink the device chain */
- link->dev = NULL;
-
+ pcmcia_disable_device(link);
platform_device_unregister(&platform_dev);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
}
-static void sl811_cs_config(dev_link_t *link)
+static int sl811_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
- struct device *parent = &handle_to_dev(handle);
+ struct device *parent = &handle_to_dev(link);
local_info_t *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -188,27 +174,23 @@ static void sl811_cs_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0
- || pcmcia_parse_tuple(handle, &tuple, &parse)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0
+ || pcmcia_parse_tuple(link, &tuple, &parse)
!= 0)
goto next_entry;
@@ -234,10 +216,10 @@ static void sl811_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* we need an interrupt */
@@ -254,15 +236,14 @@ static void sl811_cs_config(dev_link_t *link)
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
break;
next_entry:
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ pcmcia_disable_device(link);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
}
/* require an IRQ and two registers */
@@ -270,71 +251,46 @@ next_entry:
goto cs_failed;
if (link->conf.Attributes & CONF_ENABLE_IRQ)
CS_CHECK(RequestIRQ,
- pcmcia_request_irq(link->handle, &link->irq));
+ pcmcia_request_irq(link, &link->irq));
else
goto cs_failed;
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
sprintf(dev->node.dev_name, driver_name);
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
printk(", irq %d", link->irq.AssignedIRQ);
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
< 0) {
cs_failed:
printk("sl811_cs_config failed\n");
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
sl811_cs_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
}
-}
-
-static int sl811_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int sl811_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
return 0;
}
-static int sl811_cs_attach(struct pcmcia_device *p_dev)
+static int sl811_cs_probe(struct pcmcia_device *link)
{
local_info_t *local;
- dev_link_t *link;
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
- link = &local->link;
+ local->p_dev = link;
link->priv = local;
/* Initialize */
@@ -343,16 +299,9 @@ static int sl811_cs_attach(struct pcmcia_device *p_dev)
link->irq.Handler = NULL;
link->conf.Attributes = 0;
- link->conf.Vcc = 33;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sl811_cs_config(link);
-
- return 0;
+ return sl811_cs_config(link);
}
static struct pcmcia_device_id sl811_ids[] = {
@@ -366,11 +315,9 @@ static struct pcmcia_driver sl811_cs_driver = {
.drv = {
.name = (char *)driver_name,
},
- .probe = sl811_cs_attach,
+ .probe = sl811_cs_probe,
.remove = sl811_cs_detach,
.id_table = sl811_ids,
- .suspend = sl811_suspend,
- .resume = sl811_resume,
};
/*====================================================================*/
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 4edb8330c440..d225e11f4055 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -50,6 +50,7 @@
#include "../core/hcd.h"
#include "uhci-hcd.h"
+#include "pci-quirks.h"
/*
* Version Information
@@ -100,9 +101,6 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
#include "uhci-q.c"
#include "uhci-hub.c"
-extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
-extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-
/*
* Finish up a host controller reset and update the recorded state.
*/
@@ -117,8 +115,7 @@ static void finish_reset(struct uhci_hcd *uhci)
for (port = 0; port < uhci->rh_numports; ++port)
outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
- uhci->port_c_suspend = uhci->suspended_ports =
- uhci->resuming_ports = 0;
+ uhci->port_c_suspend = uhci->resuming_ports = 0;
uhci->rh_state = UHCI_RH_RESET;
uhci->is_stopped = UHCI_IS_STOPPED;
uhci_to_hcd(uhci)->state = HC_STATE_HALT;
@@ -861,7 +858,7 @@ static const struct hc_driver uhci_driver = {
static const struct pci_device_id uhci_pci_ids[] = { {
/* handle any USB UHCI controller */
- PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x00), ~0),
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0),
.driver_data = (unsigned long) &uhci_driver,
}, { /* end: all zeroes */ }
};
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 4a69c7eb09bd..d5c8f4d92823 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -415,7 +415,6 @@ struct uhci_hcd {
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
- unsigned long suspended_ports;
unsigned long resuming_ports;
unsigned long ports_timeout; /* Time to stop signalling */
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 152971d16769..c8451d9578f1 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -85,11 +85,10 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
{
int status;
- if (test_bit(port, &uhci->suspended_ports)) {
+ if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
- clear_bit(port, &uhci->suspended_ports);
- clear_bit(port, &uhci->resuming_ports);
- set_bit(port, &uhci->port_c_suspend);
+ if (test_bit(port, &uhci->resuming_ports))
+ set_bit(port, &uhci->port_c_suspend);
/* The controller won't actually turn off the RD bit until
* it has had a chance to send a low-speed EOP sequence,
@@ -97,6 +96,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
* slightly longer for good luck. */
udelay(4);
}
+ clear_bit(port, &uhci->resuming_ports);
}
/* Wait for the UHCI controller in HP's iLO2 server management chip.
@@ -265,8 +265,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortChange |= USB_PORT_STAT_C_SUSPEND;
lstatus |= 1;
}
- if (test_bit(port, &uhci->suspended_ports))
- lstatus |= 2;
if (test_bit(port, &uhci->resuming_ports))
lstatus |= 4;
@@ -309,7 +307,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
- set_bit(port, &uhci->suspended_ports);
SET_RH_PORTSTAT(USBPORTSC_SUSP);
OK(0);
case USB_PORT_FEAT_RESET:
@@ -343,8 +340,11 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
CLR_RH_PORTSTAT(USBPORTSC_PEC);
OK(0);
case USB_PORT_FEAT_SUSPEND:
- if (test_bit(port, &uhci->suspended_ports) &&
- !test_and_set_bit(port,
+ if (!(inw(port_addr) & USBPORTSC_SUSP)) {
+
+ /* Make certain the port isn't suspended */
+ uhci_finish_suspend(uhci, port, port_addr);
+ } else if (!test_and_set_bit(port,
&uhci->resuming_ports)) {
SET_RH_PORTSTAT(USBPORTSC_RD);
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 5246b35301de..650103bc9618 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -200,45 +200,41 @@ config USB_POWERMATE
To compile this driver as a module, choose M here: the
module will be called powermate.
-config USB_MTOUCH
- tristate "MicroTouch USB Touchscreen Driver"
+config USB_TOUCHSCREEN
+ tristate "USB Touchscreen Driver"
depends on USB && INPUT
---help---
- Say Y here if you want to use a MicroTouch (Now 3M) USB
- Touchscreen controller.
+ USB Touchscreen driver for:
+ - eGalax Touchkit USB
+ - PanJit TouchSet USB
+ - 3M MicroTouch USB
+ - ITM
- See <file:Documentation/usb/mtouch.txt> for additional information.
-
- To compile this driver as a module, choose M here: the
- module will be called mtouchusb.
-
-config USB_ITMTOUCH
- tristate "ITM Touch USB Touchscreen Driver"
- depends on USB && INPUT
- ---help---
- Say Y here if you want to use a ITM Touch USB
- Touchscreen controller.
-
- This touchscreen is used in LG 1510SF monitors.
+ Have a look at <http://linux.chapter7.ch/touchkit/> for
+ a usage description and the required user-space stuff.
To compile this driver as a module, choose M here: the
- module will be called itmtouch.
+ module will be called usbtouchscreen.
-config USB_EGALAX
- tristate "eGalax TouchKit USB Touchscreen Driver"
- depends on USB && INPUT
- ---help---
- Say Y here if you want to use a eGalax TouchKit USB
- Touchscreen controller.
+config USB_TOUCHSCREEN_EGALAX
+ default y
+ bool "eGalax device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
- The driver has been tested on a Xenarc 700TSV monitor
- with eGalax touchscreen.
+config USB_TOUCHSCREEN_PANJIT
+ default y
+ bool "PanJit device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
- Have a look at <http://linux.chapter7.ch/touchkit/> for
- a usage description and the required user-space stuff.
+config USB_TOUCHSCREEN_3M
+ default y
+ bool "3M/Microtouch device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
- To compile this driver as a module, choose M here: the
- module will be called touchkitusb.
+config USB_TOUCHSCREEN_ITM
+ default y
+ bool "ITM device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
config USB_YEALINK
tristate "Yealink usb-p1k voip phone"
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index d512d9f488fe..764114529c56 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o
obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o
obj-$(CONFIG_USB_EGALAX) += touchkitusb.o
+obj-$(CONFIG_USB_TOUCHSCREEN) += usbtouchscreen.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index d4bf1701046b..f419bd82ab7f 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1372,6 +1372,11 @@ void hid_close(struct hid_device *hid)
usb_kill_urb(hid->urbin);
}
+#define USB_VENDOR_ID_PANJIT 0x134c
+
+#define USB_VENDOR_ID_SILVERCREST 0x062a
+#define USB_DEVICE_ID_SILVERCREST_KB 0x0201
+
/*
* Initialize all reports
*/
@@ -1655,9 +1660,12 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
@@ -1675,6 +1683,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
@@ -1701,6 +1710,11 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
+
{ 0, 0 }
};
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index 72e698658b53..d5c91ee67991 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -34,12 +34,6 @@
#include "hid.h"
-/* Drivers' initializing functions */
-extern int hid_lgff_init(struct hid_device* hid);
-extern int hid_lg3d_init(struct hid_device* hid);
-extern int hid_pid_init(struct hid_device* hid);
-extern int hid_tmff_init(struct hid_device* hid);
-
/*
* This table contains pointers to initializers. To add support for new
* devices, you need to add the USB vendor and product ids here.
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 4e1b784fe527..9c62837b5b89 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -533,3 +533,8 @@ static inline int hid_ff_event(struct hid_device *hid, struct input_dev *input,
return hid->ff_event(hid, input, type, code, value);
return -ENOSYS;
}
+
+int hid_lgff_init(struct hid_device* hid);
+int hid_tmff_init(struct hid_device* hid);
+int hid_pid_init(struct hid_device* hid);
+
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index b4a051b549d1..3d911976f378 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -297,6 +297,8 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs)
remote->data.bits_left -= 6;
} else {
err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+ remote->stage = 0;
+ return;
}
keyspan_load_tester(remote, 5);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
new file mode 100644
index 000000000000..e9a07c1e905b
--- /dev/null
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -0,0 +1,605 @@
+/******************************************************************************
+ * usbtouchscreen.c
+ * Driver for USB Touchscreens, supporting those devices:
+ * - eGalax Touchkit
+ * - 3M/Microtouch
+ * - ITM
+ * - PanJit TouchSet
+ *
+ * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
+ * Copyright (C) by Todd E. Johnson (mtouchusb.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) 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.
+ *
+ * Driver is based on touchkitusb.c
+ * - ITM parts are from itmtouch.c
+ * - 3M parts are from mtouchusb.c
+ * - PanJit parts are from an unmerged driver by Lanslott Gish
+ *
+ *****************************************************************************/
+
+//#define DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb_input.h>
+
+
+#define DRIVER_VERSION "v0.3"
+#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
+#define DRIVER_DESC "USB Touchscreen Driver"
+
+static int swap_xy;
+module_param(swap_xy, bool, 0644);
+MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
+
+/* device specifc data/functions */
+struct usbtouch_usb;
+struct usbtouch_device_info {
+ int min_xc, max_xc;
+ int min_yc, max_yc;
+ int min_press, max_press;
+ int rept_size;
+ int flags;
+
+ void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
+ int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press);
+ int (*init) (struct usbtouch_usb *usbtouch);
+};
+
+#define USBTOUCH_FLG_BUFFER 0x01
+
+
+/* a usbtouch device */
+struct usbtouch_usb {
+ unsigned char *data;
+ dma_addr_t data_dma;
+ unsigned char *buffer;
+ int buf_len;
+ struct urb *irq;
+ struct usb_device *udev;
+ struct input_dev *input;
+ struct usbtouch_device_info *type;
+ char name[128];
+ char phys[64];
+};
+
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+ struct pt_regs *regs, unsigned char *pkt, int len);
+
+/* device types */
+enum {
+ DEVTPYE_DUMMY = -1,
+ DEVTYPE_EGALAX,
+ DEVTYPE_PANJIT,
+ DEVTYPE_3M,
+ DEVTYPE_ITM,
+};
+
+static struct usb_device_id usbtouch_devices[] = {
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+ {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
+ {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
+ {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
+ {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_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
+ {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+ {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
+#endif
+
+ {}
+};
+
+
+/*****************************************************************************
+ * eGalax part
+ */
+
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+
+#define EGALAX_PKT_TYPE_MASK 0xFE
+#define EGALAX_PKT_TYPE_REPT 0x80
+#define EGALAX_PKT_TYPE_DIAG 0x0A
+
+static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
+ return 0;
+
+ *x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
+ *y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
+ *touch = pkt[0] & 0x01;
+
+ return 1;
+
+}
+
+static int egalax_get_pkt_len(unsigned char *buf)
+{
+ switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
+ case EGALAX_PKT_TYPE_REPT:
+ return 5;
+
+ case EGALAX_PKT_TYPE_DIAG:
+ return buf[1] + 2;
+ }
+
+ return 0;
+}
+
+static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
+ unsigned char *pkt, int len)
+{
+ unsigned char *buffer;
+ int pkt_len, buf_len, pos;
+
+ /* if the buffer contains data, append */
+ if (unlikely(usbtouch->buf_len)) {
+ int tmp;
+
+ /* if only 1 byte in buffer, add another one to get length */
+ if (usbtouch->buf_len == 1)
+ usbtouch->buffer[1] = pkt[0];
+
+ pkt_len = egalax_get_pkt_len(usbtouch->buffer);
+
+ /* unknown packet: drop everything */
+ if (!pkt_len)
+ return;
+
+ /* append, process */
+ tmp = pkt_len - usbtouch->buf_len;
+ memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
+ usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
+
+ buffer = pkt + tmp;
+ buf_len = len - tmp;
+ } else {
+ buffer = pkt;
+ buf_len = len;
+ }
+
+ /* only one byte left in buffer */
+ if (unlikely(buf_len == 1)) {
+ usbtouch->buffer[0] = buffer[0];
+ usbtouch->buf_len = 1;
+ return;
+ }
+
+ /* loop over the buffer */
+ pos = 0;
+ while (pos < buf_len) {
+ /* get packet len */
+ pkt_len = egalax_get_pkt_len(buffer + pos);
+
+ /* unknown packet: drop everything */
+ if (unlikely(!pkt_len))
+ return;
+
+ /* full packet: process */
+ if (likely(pkt_len <= buf_len)) {
+ usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+ } else {
+ /* incomplete packet: save in buffer */
+ memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
+ usbtouch->buf_len = buf_len - pos;
+ }
+ pos += pkt_len;
+ }
+}
+#endif
+
+
+/*****************************************************************************
+ * PanJit Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = ((pkt[2] & 0x0F) << 8) | pkt[1];
+ *y = ((pkt[4] & 0x0F) << 8) | pkt[3];
+ *touch = pkt[0] & 0x01;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
+ * 3M/Microtouch Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+
+#define MTOUCHUSB_ASYNC_REPORT 1
+#define MTOUCHUSB_RESET 7
+#define MTOUCHUSB_REQ_CTRLLR_ID 10
+
+static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = (pkt[8] << 8) | pkt[7];
+ *y = (pkt[10] << 8) | pkt[9];
+ *touch = (pkt[2] & 0x40) ? 1 : 0;
+
+ return 1;
+}
+
+static int mtouch_init(struct usbtouch_usb *usbtouch)
+{
+ int ret;
+
+ ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+ MTOUCHUSB_RESET,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
+ __FUNCTION__, ret);
+ if (ret < 0)
+ return ret;
+
+ ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+ MTOUCHUSB_ASYNC_REPORT,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
+ __FUNCTION__, ret);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * ITM Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
+ *x = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+ *press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F);
+ *touch = ~pkt[7] & 0x20;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
+ * the different device descriptors
+ */
+static struct usbtouch_device_info usbtouch_dev_info[] = {
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+ [DEVTYPE_EGALAX] = {
+ .min_xc = 0x0,
+ .max_xc = 0x07ff,
+ .min_yc = 0x0,
+ .max_yc = 0x07ff,
+ .rept_size = 16,
+ .flags = USBTOUCH_FLG_BUFFER,
+ .process_pkt = egalax_process,
+ .read_data = egalax_read_data,
+ },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+ [DEVTYPE_PANJIT] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .read_data = panjit_read_data,
+ },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+ [DEVTYPE_3M] = {
+ .min_xc = 0x0,
+ .max_xc = 0x4000,
+ .min_yc = 0x0,
+ .max_yc = 0x4000,
+ .rept_size = 11,
+ .read_data = mtouch_read_data,
+ .init = mtouch_init,
+ },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+ [DEVTYPE_ITM] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .max_press = 0xff,
+ .rept_size = 8,
+ .read_data = itm_read_data,
+ },
+#endif
+};
+
+
+/*****************************************************************************
+ * Generic Part
+ */
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+ struct pt_regs *regs, unsigned char *pkt, int len)
+{
+ int x, y, touch, press;
+ struct usbtouch_device_info *type = usbtouch->type;
+
+ if (!type->read_data(pkt, &x, &y, &touch, &press))
+ return;
+
+ input_regs(usbtouch->input, regs);
+ input_report_key(usbtouch->input, BTN_TOUCH, touch);
+
+ if (swap_xy) {
+ input_report_abs(usbtouch->input, ABS_X, y);
+ input_report_abs(usbtouch->input, ABS_Y, x);
+ } else {
+ input_report_abs(usbtouch->input, ABS_X, x);
+ input_report_abs(usbtouch->input, ABS_Y, y);
+ }
+ if (type->max_press)
+ input_report_abs(usbtouch->input, ABS_PRESSURE, press);
+ input_sync(usbtouch->input);
+}
+
+
+static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct usbtouch_usb *usbtouch = urb->context;
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ETIMEDOUT:
+ /* this urb is timing out */
+ dbg("%s - urb timed out - was the device unplugged?",
+ __FUNCTION__);
+ return;
+ 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;
+ }
+
+ usbtouch->type->process_pkt(usbtouch, regs, usbtouch->data, urb->actual_length);
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result: %d",
+ __FUNCTION__, retval);
+}
+
+static int usbtouch_open(struct input_dev *input)
+{
+ struct usbtouch_usb *usbtouch = input->private;
+
+ usbtouch->irq->dev = usbtouch->udev;
+
+ if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
+ return -EIO;
+
+ return 0;
+}
+
+static void usbtouch_close(struct input_dev *input)
+{
+ struct usbtouch_usb *usbtouch = input->private;
+
+ usb_kill_urb(usbtouch->irq);
+}
+
+
+static void usbtouch_free_buffers(struct usb_device *udev,
+ struct usbtouch_usb *usbtouch)
+{
+ if (usbtouch->data)
+ usb_buffer_free(udev, usbtouch->type->rept_size,
+ usbtouch->data, usbtouch->data_dma);
+ kfree(usbtouch->buffer);
+}
+
+
+static int usbtouch_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usbtouch_usb *usbtouch;
+ struct input_dev *input_dev;
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usbtouch_device_info *type;
+ int err;
+
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
+
+ usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!usbtouch || !input_dev)
+ goto out_free;
+
+ type = &usbtouch_dev_info[id->driver_info];
+ usbtouch->type = type;
+ if (!type->process_pkt)
+ type->process_pkt = usbtouch_process_pkt;
+
+ usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
+ SLAB_KERNEL, &usbtouch->data_dma);
+ if (!usbtouch->data)
+ goto out_free;
+
+ if (type->flags & USBTOUCH_FLG_BUFFER) {
+ usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
+ if (!usbtouch->buffer)
+ goto out_free_buffers;
+ }
+
+ usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!usbtouch->irq) {
+ dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__);
+ goto out_free_buffers;
+ }
+
+ usbtouch->udev = udev;
+ usbtouch->input = input_dev;
+
+ if (udev->manufacturer)
+ strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
+ strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
+ }
+
+ if (!strlen(usbtouch->name))
+ snprintf(usbtouch->name, sizeof(usbtouch->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
+ strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
+
+ input_dev->name = usbtouch->name;
+ input_dev->phys = usbtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = usbtouch;
+ input_dev->open = usbtouch_open;
+ input_dev->close = usbtouch_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
+ if (type->max_press)
+ input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
+ type->max_press, 0, 0);
+
+ usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
+ usb_rcvintpipe(usbtouch->udev, 0x81),
+ usbtouch->data, type->rept_size,
+ usbtouch_irq, usbtouch, endpoint->bInterval);
+
+ usbtouch->irq->transfer_dma = usbtouch->data_dma;
+ usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* device specific init */
+ if (type->init) {
+ err = type->init(usbtouch);
+ if (err) {
+ dbg("%s - type->init() failed, err: %d", __FUNCTION__, err);
+ goto out_free_buffers;
+ }
+ }
+
+ err = input_register_device(usbtouch->input);
+ if (err) {
+ dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err);
+ goto out_free_buffers;
+ }
+
+ usb_set_intfdata(intf, usbtouch);
+
+ return 0;
+
+out_free_buffers:
+ usbtouch_free_buffers(udev, usbtouch);
+out_free:
+ input_free_device(input_dev);
+ kfree(usbtouch);
+ return -ENOMEM;
+}
+
+static void usbtouch_disconnect(struct usb_interface *intf)
+{
+ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+
+ dbg("%s - called", __FUNCTION__);
+
+ if (!usbtouch)
+ return;
+
+ dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__);
+ usb_set_intfdata(intf, NULL);
+ usb_kill_urb(usbtouch->irq);
+ input_unregister_device(usbtouch->input);
+ usb_free_urb(usbtouch->irq);
+ usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
+ kfree(usbtouch);
+}
+
+MODULE_DEVICE_TABLE(usb, usbtouch_devices);
+
+static struct usb_driver usbtouch_driver = {
+ .name = "usbtouchscreen",
+ .probe = usbtouch_probe,
+ .disconnect = usbtouch_disconnect,
+ .id_table = usbtouch_devices,
+};
+
+static int __init usbtouch_init(void)
+{
+ return usb_register(&usbtouch_driver);
+}
+
+static void __exit usbtouch_cleanup(void)
+{
+ usb_deregister(&usbtouch_driver);
+}
+
+module_init(usbtouch_init);
+module_exit(usbtouch_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("touchkitusb");
+MODULE_ALIAS("itmtouch");
+MODULE_ALIAS("mtouchusb");
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index d3e15df9e815..cf84c6096f29 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -9,7 +9,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-2005 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -56,6 +56,8 @@
* - Merged wacom_intuos3_irq into wacom_intuos_irq
* v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
* - Report Device IDs
+ * v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ * - Minor data report fix
*/
/*
@@ -78,7 +80,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.44"
+#define DRIVER_VERSION "v1.45"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -99,6 +101,8 @@ enum {
PL,
INTUOS,
INTUOS3,
+ INTUOS312,
+ INTUOS319,
CINTIQ,
MAX_TYPE
};
@@ -127,7 +131,19 @@ struct wacom {
char phys[32];
};
+#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_SET_REPORT 0x09
+
+static int usb_get_report(struct usb_interface *intf, unsigned char type,
+ unsigned char id, void *buf, int size)
+{
+ return usb_control_msg(interface_to_usbdev(intf),
+ usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+ USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+ buf, size, 100);
+}
+
static int usb_set_report(struct usb_interface *intf, unsigned char type,
unsigned char id, void *buf, int size)
{
@@ -206,7 +222,8 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
wacom->tool[1] = BTN_TOOL_PEN;
id = STYLUS_DEVICE_ID;
}
- input_report_key(dev, wacom->tool[1], id); /* report in proximity for tool */
+ input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
+ input_report_abs(dev, ABS_MISC, id); /* report tool id */
input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
input_report_abs(dev, ABS_PRESSURE, pressure);
@@ -239,7 +256,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = wacom->dev;
- int retval;
+ int retval, id;
switch (urb->status) {
case 0:
@@ -263,12 +280,15 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
input_regs(dev, regs);
if (data[1] & 0x04) {
- input_report_key(dev, BTN_TOOL_RUBBER, (data[1] & 0x20) ? ERASER_DEVICE_ID : 0);
+ input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
+ id = ERASER_DEVICE_ID;
} else {
- input_report_key(dev, BTN_TOOL_PEN, (data[1] & 0x20) ? STYLUS_DEVICE_ID : 0);
+ input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+ id = STYLUS_DEVICE_ID;
}
+ input_report_abs(dev, ABS_MISC, id); /* report tool id */
input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
@@ -312,7 +332,8 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
}
input_regs(dev, regs);
- input_report_key(dev, BTN_TOOL_PEN, STYLUS_DEVICE_ID);
+ input_report_key(dev, BTN_TOOL_PEN, 1);
+ input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
@@ -350,6 +371,8 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
+ if (data[0] == 99) return; /* for Volito tablets */
+
if (data[0] != 2) {
dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
goto exit;
@@ -374,10 +397,10 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
case 2: /* Mouse with wheel */
input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
if (wacom->features->type == WACOM_G4) {
- rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
- input_report_rel(dev, REL_WHEEL, rw);
+ rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
+ input_report_rel(dev, REL_WHEEL, -rw);
} else
- input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+ input_report_rel(dev, REL_WHEEL, -(signed char) data[6]);
/* fall through */
case 3: /* Mouse without wheel */
@@ -406,39 +429,27 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
}
}
- input_report_key(dev, wacom->tool[0], (data[1] & 0x10) ? id : 0);
+ if (data[1] & 0x10)
+ input_report_abs(dev, ABS_MISC, id); /* report tool id */
+ else
+ input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
+ input_report_key(dev, wacom->tool[0], data[1] & 0x10);
input_sync(dev);
/* send pad data */
if (wacom->features->type == WACOM_G4) {
- /* fist time sending pad data */
- if (wacom->tool[1] != BTN_TOOL_FINGER) {
- wacom->id[1] = 0;
- wacom->serial[1] = (data[7] & 0x38) >> 2;
- }
- if (data[7] & 0xf8) {
+ if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) {
+ wacom->id[1] = 1;
+ wacom->serial[1] = (data[7] & 0xf8);
input_report_key(dev, BTN_0, (data[7] & 0x40));
input_report_key(dev, BTN_4, (data[7] & 0x80));
- if (((data[7] & 0x38) >> 2) == (wacom->serial[1] & 0x0e))
- /* alter REL_WHEEL value so X apps can get it */
- wacom->serial[1] += (wacom->serial[1] & 0x01) ? -1 : 1;
- else
- wacom->serial[1] = (data[7] & 0x38 ) >> 2;
-
- /* don't alter the value when there is no wheel event */
- if (wacom->serial[1] == 1)
- wacom->serial[1] = 0;
- rw = wacom->serial[1];
- rw = (rw & 0x08) ? -(rw & 0x07) : (rw & 0x07);
+ rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
input_report_rel(dev, REL_WHEEL, rw);
- wacom->tool[1] = BTN_TOOL_FINGER;
- wacom->id[1] = data[7] & 0xf8;
- input_report_key(dev, wacom->tool[1], 0xf0);
+ input_report_key(dev, BTN_TOOL_FINGER, 0xf0);
input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
} else if (wacom->id[1]) {
wacom->id[1] = 0;
- wacom->serial[1] = 0;
- input_report_key(dev, wacom->tool[1], 0);
+ input_report_key(dev, BTN_TOOL_FINGER, 0);
input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
}
input_sync(dev);
@@ -516,21 +527,31 @@ static int wacom_intuos_inout(struct urb *urb)
default: /* Unknown tool */
wacom->tool[idx] = BTN_TOOL_PEN;
}
- input_report_key(dev, wacom->tool[idx], wacom->id[idx]);
- input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
- input_sync(dev);
+ if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
+ ((wacom->features->type == INTUOS312)
+ || (wacom->features->type == INTUOS319)))) {
+ input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
+ input_report_key(dev, wacom->tool[idx], 1);
+ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ input_sync(dev);
+ }
return 1;
}
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
input_report_key(dev, wacom->tool[idx], 0);
+ input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
input_sync(dev);
return 1;
}
- return 0;
+ if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312)
+ || (wacom->features->type == INTUOS319)))
+ return 1;
+ else
+ return 0;
}
static void wacom_intuos_general(struct urb *urb)
@@ -600,10 +621,9 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
/* pad packets. Works as a second tool and is always in prox */
if (data[0] == 12) {
/* initiate the pad as a device */
- if (wacom->tool[1] != BTN_TOOL_FINGER) {
+ if (wacom->tool[1] != BTN_TOOL_FINGER)
wacom->tool[1] = BTN_TOOL_FINGER;
- input_report_key(dev, wacom->tool[1], 1);
- }
+
input_report_key(dev, BTN_0, (data[5] & 0x01));
input_report_key(dev, BTN_1, (data[5] & 0x02));
input_report_key(dev, BTN_2, (data[5] & 0x04));
@@ -614,6 +634,11 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
input_report_key(dev, BTN_7, (data[6] & 0x08));
input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+ if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
+ input_report_key(dev, wacom->tool[1], 1);
+ else
+ input_report_key(dev, wacom->tool[1], 0);
input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
input_sync(dev);
goto exit;
@@ -676,8 +701,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
input_report_key(dev, BTN_LEFT, data[8] & 0x04);
input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
input_report_key(dev, BTN_RIGHT, data[8] & 0x10);
- input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1)
- - (data[8] & 0x01));
+ input_report_rel(dev, REL_WHEEL, (data[8] & 0x01)
+ - ((data[8] & 0x02) >> 1));
/* I3 2D mouse side buttons */
if (wacom->features->type == INTUOS3) {
@@ -695,7 +720,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
}
}
- input_report_key(dev, wacom->tool[idx], wacom->id[idx]);
+ input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
+ input_report_key(dev, wacom->tool[idx], 1);
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
input_sync(dev);
@@ -733,7 +759,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq },
{ "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_pl_irq },
{ "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq },
- { "Wacom PL710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq },
+ { "Wacom DTU710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq },
+ { "Wacom DTF521", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq },
{ "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_pl_irq },
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq },
{ "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq },
@@ -744,6 +771,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq },
{ "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq },
{ "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq },
+ { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312, wacom_intuos_irq },
+ { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319, wacom_intuos_irq },
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_intuos_irq },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq },
@@ -779,6 +808,7 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
@@ -788,6 +818,8 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
@@ -820,7 +852,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
struct input_dev *input_dev;
- char rep_data[2] = {0x02, 0x02};
+ char rep_data[2], limit = 0;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
input_dev = input_allocate_device();
@@ -857,6 +889,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0);
input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
+ input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
switch (wacom->features->type) {
case WACOM_G4:
@@ -875,6 +908,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
break;
case INTUOS3:
+ case INTUOS312:
+ case INTUOS319:
case CINTIQ:
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
@@ -916,10 +951,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_register_device(wacom->dev);
- /* ask the tablet to report tablet data */
- usb_set_report(intf, 3, 2, rep_data, 2);
- /* repeat once (not sure why the first call often fails) */
- usb_set_report(intf, 3, 2, rep_data, 2);
+ /* Ask the tablet to report tablet data. Repeat until it succeeds */
+ do {
+ rep_data[0] = 2;
+ rep_data[1] = 2;
+ usb_set_report(intf, 3, 2, rep_data, 2);
+ usb_get_report(intf, 3, 2, rep_data, 2);
+ } while (rep_data[1] != 2 && limit++ < 5);
usb_set_intfdata(intf, wacom);
return 0;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 9d59b901841c..ccc5e8238bd8 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -381,6 +381,7 @@ alloc_sglist (int nents, int max, int vary)
for (i = 0; i < nents; i++) {
char *buf;
+ unsigned j;
buf = kzalloc (size, SLAB_KERNEL);
if (!buf) {
@@ -391,6 +392,16 @@ alloc_sglist (int nents, int max, int vary)
/* kmalloc pages are always physically contiguous! */
sg_init_one(&sg[i], buf, size);
+ switch (pattern) {
+ case 0:
+ /* already zeroed */
+ break;
+ case 1:
+ for (j = 0; j < size; j++)
+ *buf++ = (u8) (j % 63);
+ break;
+ }
+
if (vary) {
size += vary;
size %= max;
@@ -425,6 +436,8 @@ static int perform_sglist (
usb_sg_wait (req);
retval = req->status;
+ /* FIXME check resulting data pattern */
+
/* FIXME if endpoint halted, clear halt (and log) */
}
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 3094970615cb..12b599a0b539 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -37,7 +37,6 @@
#include "usbnet.h"
-
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define AX_CMD_SET_SW_MII 0x06
@@ -109,7 +108,7 @@
#define AX_EEPROM_MAGIC 0xdeadbeef
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-struct ax8817x_data {
+struct asix_data {
u8 multi_filter[AX_MCAST_FILTER_SIZE];
};
@@ -121,7 +120,7 @@ struct ax88172_int_data {
u16 res3;
} __attribute__ ((packed));
-static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
return usb_control_msg(
@@ -136,7 +135,7 @@ static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
USB_CTRL_GET_TIMEOUT);
}
-static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
return usb_control_msg(
@@ -151,19 +150,80 @@ static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
USB_CTRL_SET_TIMEOUT);
}
-static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
if (urb->status < 0)
- printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
+ printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
urb->status);
kfree(req);
usb_free_urb(urb);
}
-static void ax8817x_status(struct usbnet *dev, struct urb *urb)
+static inline int asix_set_sw_mii(struct usbnet *dev)
+{
+ int ret;
+ ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev, "Failed to enable software MII access");
+ return ret;
+}
+
+static inline int asix_set_hw_mii(struct usbnet *dev)
+{
+ int ret;
+ ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev, "Failed to enable hardware MII access");
+ return ret;
+}
+
+static inline int asix_get_phyid(struct usbnet *dev)
+{
+ int ret = 0;
+ void *buf;
+
+ buf = kmalloc(2, GFP_KERNEL);
+ if (!buf)
+ goto out1;
+
+ if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 2) {
+ devdbg(dev, "Error reading PHYID register: %02x", ret);
+ goto out2;
+ }
+ ret = *((u8 *)buf + 1);
+out2:
+ kfree(buf);
+out1:
+ return ret;
+}
+
+static int asix_sw_reset(struct usbnet *dev, u8 flags)
+{
+ int ret;
+
+ ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev,"Failed to send software reset: %02x", ret);
+
+ return ret;
+}
+
+static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
+{
+ int ret;
+
+ ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev, "Failed to write RX_CTL mode: %02x", ret);
+
+ return ret;
+}
+
+static void asix_status(struct usbnet *dev, struct urb *urb)
{
struct ax88172_int_data *event;
int link;
@@ -179,12 +239,12 @@ static void ax8817x_status(struct usbnet *dev, struct urb *urb)
usbnet_defer_kevent (dev, EVENT_LINK_RESET );
} else
netif_carrier_off(dev->net);
- devdbg(dev, "ax8817x - Link Status is: %d", link);
+ devdbg(dev, "Link Status is: %d", link);
}
}
static void
-ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
struct usb_ctrlrequest *req;
@@ -211,7 +271,7 @@ ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
usb_fill_control_urb(urb, dev->udev,
usb_sndctrlpipe(dev->udev, 0),
(void *)req, data, size,
- ax8817x_async_cmd_callback, req);
+ asix_async_cmd_callback, req);
if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
deverr(dev, "Error submitting the control message: status=%d",
@@ -221,10 +281,10 @@ ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
}
}
-static void ax8817x_set_multicast(struct net_device *net)
+static void asix_set_multicast(struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ struct asix_data *data = (struct asix_data *)&dev->data;
u8 rx_ctl = 0x8c;
if (net->flags & IFF_PROMISC) {
@@ -255,53 +315,51 @@ static void ax8817x_set_multicast(struct net_device *net)
mc_list = mc_list->next;
}
- ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+ asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
AX_MCAST_FILTER_SIZE, data->multi_filter);
rx_ctl |= 0x10;
}
- ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+ asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
}
-static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
+static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
struct usbnet *dev = netdev_priv(netdev);
u16 res;
- u8 buf[1];
- ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
+ asix_set_sw_mii(dev);
+ asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
(__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+ asix_set_hw_mii(dev);
return res & 0xffff;
}
/* same as above, but converts resulting value to cpu byte order */
-static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
+static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
{
- return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc));
+ return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc));
}
static void
-ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
{
struct usbnet *dev = netdev_priv(netdev);
u16 res = val;
- u8 buf[1];
- ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ asix_set_sw_mii(dev);
+ asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
(__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+ asix_set_hw_mii(dev);
}
/* same as above, but converts new value to le16 byte order before writing */
static void
-ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
{
- ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+ asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
}
static int ax88172_link_reset(struct usbnet *dev)
@@ -312,23 +370,23 @@ static int ax88172_link_reset(struct usbnet *dev)
u8 mode;
mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
- lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
- adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
res = mii_nway_result(lpa|adv);
if (res & LPA_DUPLEX)
mode |= AX_MEDIUM_FULL_DUPLEX;
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+ asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
return 0;
}
static void
-ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = netdev_priv(net);
u8 opt;
- if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
+ if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
wolinfo->supported = 0;
wolinfo->wolopts = 0;
return;
@@ -344,7 +402,7 @@ ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
}
static int
-ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = netdev_priv(net);
u8 opt = 0;
@@ -357,19 +415,19 @@ ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
if (opt != 0)
opt |= AX_MONITOR_MODE;
- if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
+ if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
opt, 0, 0, &buf) < 0)
return -EINVAL;
return 0;
}
-static int ax8817x_get_eeprom_len(struct net_device *net)
+static int asix_get_eeprom_len(struct net_device *net)
{
return AX_EEPROM_LEN;
}
-static int ax8817x_get_eeprom(struct net_device *net,
+static int asix_get_eeprom(struct net_device *net,
struct ethtool_eeprom *eeprom, u8 *data)
{
struct usbnet *dev = netdev_priv(net);
@@ -386,14 +444,14 @@ static int ax8817x_get_eeprom(struct net_device *net,
/* ax8817x returns 2 bytes from eeprom on read */
for (i=0; i < eeprom->len / 2; i++) {
- if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+ if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
return -EINVAL;
}
return 0;
}
-static void ax8817x_get_drvinfo (struct net_device *net,
+static void asix_get_drvinfo (struct net_device *net,
struct ethtool_drvinfo *info)
{
/* Inherit standard device info */
@@ -401,14 +459,14 @@ static void ax8817x_get_drvinfo (struct net_device *net,
info->eedump_len = 0x3e;
}
-static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
return mii_ethtool_gset(&dev->mii,cmd);
}
-static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
@@ -418,27 +476,27 @@ static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
/* We need to override some ethtool_ops so we require our
own structure so we don't interfere with other usbnet
devices that may be connected at the same time. */
-static struct ethtool_ops ax8817x_ethtool_ops = {
- .get_drvinfo = ax8817x_get_drvinfo,
+static struct ethtool_ops ax88172_ethtool_ops = {
+ .get_drvinfo = asix_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
- .get_wol = ax8817x_get_wol,
- .set_wol = ax8817x_set_wol,
- .get_eeprom_len = ax8817x_get_eeprom_len,
- .get_eeprom = ax8817x_get_eeprom,
- .get_settings = ax8817x_get_settings,
- .set_settings = ax8817x_set_settings,
+ .get_wol = asix_get_wol,
+ .set_wol = asix_set_wol,
+ .get_eeprom_len = asix_get_eeprom_len,
+ .get_eeprom = asix_get_eeprom,
+ .get_settings = asix_get_settings,
+ .set_settings = asix_set_settings,
};
-static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
struct usbnet *dev = netdev_priv(net);
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
}
-static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
+static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
{
int ret = 0;
void *buf;
@@ -455,55 +513,39 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
/* Toggle the GPIOs in a manufacturer/model specific way */
for (i = 2; i >= 0; i--) {
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
(gpio_bits >> (i * 8)) & 0xff, 0, 0,
buf)) < 0)
goto out2;
msleep(5);
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
- 0x80, 0, 0, buf)) < 0) {
- dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+ if ((ret = asix_write_rx_ctl(dev,0x80)) < 0)
goto out2;
- }
/* Get the MAC address */
memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID,
+ if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
0, 0, 6, buf)) < 0) {
dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
goto out2;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
- 0, 0, 2, buf)) < 0) {
- dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
- goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
- ret);
- ret = -EIO;
- goto out2;
- }
-
/* Initialize MII structure */
dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.mdio_read = asix_mdio_read;
+ dev->mii.mdio_write = asix_mdio_write;
dev->mii.phy_id_mask = 0x3f;
dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = *((u8 *)buf + 1);
- dev->net->do_ioctl = ax8817x_ioctl;
+ dev->mii.phy_id = asix_get_phyid(dev);
+ dev->net->do_ioctl = asix_ioctl;
- dev->net->set_multicast_list = ax8817x_set_multicast;
- dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+ dev->net->set_multicast_list = asix_set_multicast;
+ dev->net->ethtool_ops = &ax88172_ethtool_ops;
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
mii_nway_restart(&dev->mii);
@@ -515,16 +557,16 @@ out1:
}
static struct ethtool_ops ax88772_ethtool_ops = {
- .get_drvinfo = ax8817x_get_drvinfo,
+ .get_drvinfo = asix_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
- .get_wol = ax8817x_get_wol,
- .set_wol = ax8817x_set_wol,
- .get_eeprom_len = ax8817x_get_eeprom_len,
- .get_eeprom = ax8817x_get_eeprom,
- .get_settings = ax8817x_get_settings,
- .set_settings = ax8817x_set_settings,
+ .get_wol = asix_get_wol,
+ .set_wol = asix_set_wol,
+ .get_eeprom_len = asix_get_eeprom_len,
+ .get_eeprom = asix_get_eeprom,
+ .get_settings = asix_get_settings,
+ .set_settings = asix_set_settings,
};
static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -541,62 +583,45 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out1;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
0x00B0, 0, 0, buf)) < 0)
goto out2;
msleep(5);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
0x0001, 0, 0, buf)) < 0) {
dbg("Select PHY #1 failed: %d", ret);
goto out2;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
- 0, 0, buf)) < 0) {
- dbg("Failed to power down internal PHY: %d", ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD)) < 0)
goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
- 0, 0, buf)) < 0) {
- dbg("Failed to perform software reset: %d", ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0)
goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
- AX_SWRESET_IPRL | AX_SWRESET_PRL,
- 0, 0, buf)) < 0) {
- dbg("Failed to set Internal/External PHY reset control: %d",
- ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
- 0x0000, 0, 0, buf)) < 0) {
- dbg("Failed to reset RX_CTL: %d", ret);
+ if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0)
goto out2;
- }
/* Get the MAC address */
memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+ if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
0, 0, ETH_ALEN, buf)) < 0) {
dbg("Failed to read MAC address: %d", ret);
goto out2;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
- 0, 0, 0, buf)) < 0) {
- dbg("Enabling software MII failed: %d", ret);
+ if ((ret = asix_set_sw_mii(dev)) < 0)
goto out2;
- }
- if (((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG,
+ if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG,
0x0010, 2, 2, buf)) < 0)
|| (*((u16 *)buf) != 0x003b)) {
dbg("Read PHY register 2 must be 0x3b00: %d", ret);
@@ -605,74 +630,49 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
/* Initialize MII structure */
dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.mdio_read = asix_mdio_read;
+ dev->mii.mdio_write = asix_mdio_write;
dev->mii.phy_id_mask = 0xff;
dev->mii.reg_num_mask = 0xff;
- dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->do_ioctl = asix_ioctl;
+ dev->mii.phy_id = asix_get_phyid(dev);
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
- 0, 0, 2, buf)) < 0) {
- dbg("Error reading PHY ID: %02x", ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
- ret);
- ret = -EIO;
- goto out2;
- }
- dev->mii.phy_id = *((u8 *)buf + 1);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL,
- 0, 0, buf)) < 0) {
- dbg("Set external PHY reset pin level: %d", ret);
- goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
- AX_SWRESET_IPRL | AX_SWRESET_PRL,
- 0, 0, buf)) < 0) {
- dbg("Set Internal/External PHY reset control: %d", ret);
+
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
goto out2;
- }
- msleep(150);
+ msleep(150);
- dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->set_multicast_list = asix_set_multicast;
dev->net->ethtool_ops = &ax88772_ethtool_ops;
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA);
mii_nway_restart(&dev->mii);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
dbg("Write medium mode register: %d", ret);
goto out2;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
goto out2;
}
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
- dbg("Failed to set hardware MII: %02x", ret);
+ if ((ret = asix_set_hw_mii(dev)) < 0)
goto out2;
- }
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
- buf)) < 0) {
- dbg("Reset RX_CTL failed: %d", ret);
+ if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0)
goto out2;
- }
kfree(buf);
@@ -794,23 +794,23 @@ static int ax88772_link_reset(struct usbnet *dev)
u16 mode;
mode = AX88772_MEDIUM_DEFAULT;
- lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
- adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
res = mii_nway_result(lpa|adv);
if ((res & LPA_DUPLEX) == 0)
mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
if ((res & LPA_100) == 0)
mode &= ~AX88772_MEDIUM_100MB;
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+ asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
return 0;
}
static const struct driver_info ax8817x_info = {
.description = "ASIX AX8817x USB 2.0 Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -819,8 +819,8 @@ static const struct driver_info ax8817x_info = {
static const struct driver_info dlink_dub_e100_info = {
.description = "DLink DUB-E100 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -829,8 +829,8 @@ static const struct driver_info dlink_dub_e100_info = {
static const struct driver_info netgear_fa120_info = {
.description = "Netgear FA-120 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -839,8 +839,8 @@ static const struct driver_info netgear_fa120_info = {
static const struct driver_info hawking_uf200_info = {
.description = "Hawking UF200 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -850,13 +850,12 @@ static const struct driver_info hawking_uf200_info = {
static const struct driver_info ax88772_info = {
.description = "ASIX AX88772 USB 2.0 Ethernet",
.bind = ax88772_bind,
- .status = ax8817x_status,
+ .status = asix_status,
.link_reset = ax88772_link_reset,
.reset = ax88772_link_reset,
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
.rx_fixup = ax88772_rx_fixup,
.tx_fixup = ax88772_tx_fixup,
- .data = 0x00130103,
};
static const struct usb_device_id products [] = {
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 5b6675684567..2deb4c01539e 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -262,7 +262,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb, 0),
(char *) &pegasus->dr,
- &tmp, 1, ctrl_callback, pegasus);
+ tmp, 1, ctrl_callback, pegasus);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 49991ac1bf3b..94ddfe16fdda 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -39,6 +39,20 @@
* RNDIS is NDIS remoted over USB. It's a MSFT variant of CDC ACM ... of
* course ACM was intended for modems, not Ethernet links! USB's standard
* for Ethernet links is "CDC Ethernet", which is significantly simpler.
+ *
+ * NOTE that Microsoft's "RNDIS 1.0" specification is incomplete. Issues
+ * include:
+ * - Power management in particular relies on information that's scattered
+ * through other documentation, and which is incomplete or incorrect even
+ * there.
+ * - There are various undocumented protocol requirements, such as the
+ * need to send unused garbage in control-OUT messages.
+ * - In some cases, MS-Windows will emit undocumented requests; this
+ * matters more to peripheral implementations than host ones.
+ *
+ * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in
+ * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and
+ * currently rare) "Ethernet Emulation Model" (EEM).
*/
/*
@@ -72,17 +86,17 @@ struct rndis_msg_hdr {
*/
#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */
#define RNDIS_MSG_INIT ccpu2(0x00000002)
-#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_HALT ccpu2(0x00000003)
#define RNDIS_MSG_QUERY ccpu2(0x00000004)
-#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_SET ccpu2(0x00000005)
-#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_RESET ccpu2(0x00000006)
-#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_INDICATE ccpu2(0x00000007)
#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008)
-#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
/* codes for "status" field of completion messages */
#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000)
@@ -596,13 +610,13 @@ static struct usb_driver rndis_driver = {
static int __init rndis_init(void)
{
- return usb_register(&rndis_driver);
+ return usb_register(&rndis_driver);
}
module_init(rndis_init);
static void __exit rndis_exit(void)
{
- usb_deregister(&rndis_driver);
+ usb_deregister(&rndis_driver);
}
module_exit(rndis_exit);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 5a8a2c91c2b2..f96b73f54bf1 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -158,6 +158,15 @@ config USB_SERIAL_FTDI_SIO
To compile this driver as a module, choose M here: the
module will be called ftdi_sio.
+config USB_SERIAL_FUNSOFT
+ tristate "USB Fundamental Software Dongle Driver"
+ depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use the Fundamental Software dongle.
+
+ To compile this driver as a module, choose M here: the
+ module will be called funsoft.
+
config USB_SERIAL_VISOR
tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index f7fe4172efed..93c21245b1af 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
+obj-$(CONFIG_USB_SERIAL_FUNSOFT) += funsoft.o
obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
obj-$(CONFIG_USB_SERIAL_HP4X) += hp4x.o
obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 167f8ec56131..8023bb7279b1 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -54,7 +54,7 @@ static struct console usbcons;
* serial.c code, except that the specifier is "ttyUSB" instead
* of "ttyS".
*/
-static int __init usb_console_setup(struct console *co, char *options)
+static int usb_console_setup(struct console *co, char *options)
{
struct usbcons_info *info = &usbcons_info;
int baud = 9600;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f3af81b4dd29..82151207d814 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -308,6 +308,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
@@ -489,10 +490,14 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
+ { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8da773c2744d..2c55a5ea9c99 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -39,6 +39,9 @@
/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
+/* iPlus device */
+#define FTDI_IPLUS_PID 0xD070 /* Product Id */
+
/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
/* they use the ftdi chipset for the USB interface and the vendor id is the same */
#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */
@@ -153,6 +156,11 @@
#define ICOM_ID1_PID 0x0004
/*
+ * ASK.fr devices
+ */
+#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */
+
+/*
* DSS-20 Sync Station for Sony Ericsson P800
*/
@@ -399,6 +407,26 @@
#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */
#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */
+/*
+ * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
+ */
+#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */
+
+/*
+ * Eclo (http://www.eclo.pt/) product IDs.
+ * PID 0xEA90 submitted by Martin Grill.
+ */
+#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */
+
+/*
+ * Papouch products (http://www.papouch.com/)
+ * Submitted by Folkert van Heusden
+ */
+
+#define PAPOUCH_VID 0x5050 /* Vendor ID */
+#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */
+
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
new file mode 100644
index 000000000000..803721b97e2e
--- /dev/null
+++ b/drivers/usb/serial/funsoft.c
@@ -0,0 +1,65 @@
+/*
+ * Funsoft Serial USB driver
+ *
+ * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x1404, 0xcddc) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver funsoft_driver = {
+ .name = "funsoft",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
+static struct usb_serial_driver funsoft_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "funsoft",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+};
+
+static int __init funsoft_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&funsoft_device);
+ if (retval)
+ return retval;
+ retval = usb_register(&funsoft_driver);
+ if (retval)
+ usb_serial_deregister(&funsoft_device);
+ return retval;
+}
+
+static void __exit funsoft_exit(void)
+{
+ usb_deregister(&funsoft_driver);
+ usb_serial_deregister(&funsoft_device);
+}
+
+module_init(funsoft_init);
+module_exit(funsoft_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 495db5755df9..5cf2b80add7a 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -28,6 +28,7 @@
2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard
2005-09-20 v0.4.4 increased recv buffer size: the card sometimes
wants to send >2000 bytes.
+ 2006-04-10 v0.4.2 fixed two array overrun errors :-/
Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
@@ -582,14 +583,14 @@ static void option_setup_urbs(struct usb_serial *serial)
portdata = usb_get_serial_port_data(port);
/* Do indat endpoints first */
- for (j = 0; j <= N_IN_URB; ++j) {
+ for (j = 0; j < N_IN_URB; ++j) {
portdata->in_urbs[j] = option_setup_urb (serial,
port->bulk_in_endpointAddress, USB_DIR_IN, port,
portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
}
/* outdat endpoints */
- for (j = 0; j <= N_OUT_URB; ++j) {
+ for (j = 0; j < N_OUT_URB; ++j) {
portdata->out_urbs[j] = option_setup_urb (serial,
port->bulk_out_endpointAddress, USB_DIR_OUT, port,
portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index b3014fda645c..c96714bb1cb8 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -61,6 +61,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
+ { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
@@ -78,6 +79,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
+ { USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 77901d143979..7f29e81d3e35 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -26,6 +26,7 @@
#define ITEGNO_VENDOR_ID 0x0eba
#define ITEGNO_PRODUCT_ID 0x1080
+#define ITEGNO_PRODUCT_ID_2080 0x2080
#define MA620_VENDOR_ID 0x0df7
#define MA620_PRODUCT_ID 0x0620
@@ -79,3 +80,7 @@
/* USB GSM cable from Speed Dragon Multimedia, Ltd */
#define SPEEDDRAGON_VENDOR_ID 0x0e55
#define SPEEDDRAGON_PRODUCT_ID 0x110b
+
+/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */
+#define OTI_VENDOR_ID 0x0ea0
+#define OTI_PRODUCT_ID 0x6858
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 097f4e8488fe..071f86a59c08 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -27,10 +27,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <linux/usb.h>
#include "usb-serial.h"
#include "pl2303.h"
@@ -192,7 +192,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
if (!port)
return -ENODEV;
- if (down_interruptible(&port->sem))
+ if (mutex_lock_interruptible(&port->mutex))
return -ERESTARTSYS;
++port->open_count;
@@ -219,7 +219,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
goto bailout_module_put;
}
- up(&port->sem);
+ mutex_unlock(&port->mutex);
return 0;
bailout_module_put:
@@ -227,7 +227,7 @@ bailout_module_put:
bailout_kref_put:
kref_put(&serial->kref, destroy_serial);
port->open_count = 0;
- up(&port->sem);
+ mutex_unlock(&port->mutex);
return retval;
}
@@ -240,10 +240,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number);
- down(&port->sem);
+ mutex_lock(&port->mutex);
if (port->open_count == 0) {
- up(&port->sem);
+ mutex_unlock(&port->mutex);
return;
}
@@ -262,7 +262,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
module_put(port->serial->type->driver.owner);
}
- up(&port->sem);
+ mutex_unlock(&port->mutex);
kref_put(&port->serial->kref, destroy_serial);
}
@@ -783,7 +783,7 @@ int usb_serial_probe(struct usb_interface *interface,
port->number = i + serial->minor;
port->serial = serial;
spin_lock_init(&port->lock);
- sema_init(&port->sem, 1);
+ mutex_init(&port->mutex);
INIT_WORK(&port->work, usb_serial_port_softint, port);
serial->port[i] = port;
}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index d7d27c3385b3..dc89d8710460 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -16,7 +16,7 @@
#include <linux/config.h>
#include <linux/kref.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
@@ -31,7 +31,7 @@
* @serial: pointer back to the struct usb_serial owner of this port.
* @tty: pointer to the corresponding tty for this port.
* @lock: spinlock to grab when updating portions of this structure.
- * @sem: semaphore used to synchronize serial_open() and serial_close()
+ * @mutex: mutex used to synchronize serial_open() and serial_close()
* access for this port.
* @number: the number of the port (the minor number).
* @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
@@ -63,7 +63,7 @@ struct usb_serial_port {
struct usb_serial * serial;
struct tty_struct * tty;
spinlock_t lock;
- struct semaphore sem;
+ struct mutex mutex;
unsigned char number;
unsigned char * interrupt_in_buffer;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 557411c6e7c7..f806553cd9a4 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -508,6 +508,7 @@ no_firmware:
err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
err("%s: please contact support@connecttech.com\n", serial->type->description);
+ kfree(result);
return -ENODEV;
no_command_private:
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 92be101feba7..be9eec225743 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -48,7 +48,8 @@ config USB_STORAGE_FREECOM
config USB_STORAGE_ISD200
bool "ISD-200 USB/ATA Bridge support"
- depends on USB_STORAGE && BLK_DEV_IDE
+ depends on USB_STORAGE
+ depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE
---help---
Say Y here if you want to use USB Mass Store devices based
on the In-Systems Design ISD-200 USB/ATA bridge.
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c4a9dcff5f2b..aec5ea8682d5 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -411,7 +411,7 @@ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
"Iomega",
"USB Clik! 40",
- US_SC_8070, US_PR_BULK, NULL,
+ US_SC_8070, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
/* Yakumo Mega Image 37
@@ -773,6 +773,13 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Olivier Blondeau <zeitoun@gmail.com> */
+UNUSUAL_DEV( 0x0727, 0x0306, 0x0100, 0x0100,
+ "ATMEL",
+ "SND1 Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE),
+
/* Submitted by Roman Hodek <roman@hodek.net> */
UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
"Sandisk",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f87c0171f4ec..4587087d777a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -400,6 +400,8 @@ config FB_ASILIANT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Asiliant 69030 chipset
config FB_IMSTT
bool "IMS Twin Turbo display support"
@@ -961,7 +963,7 @@ config FB_ATY128
config FB_ATY
tristate "ATI Mach64 display support" if PCI || ATARI
- depends on FB
+ depends on FB && !SPARC32
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index b39e72d5413b..d9d7d3c4cae2 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3400,7 +3400,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
struct atyfb_par *par;
int i, rc = -ENOMEM;
- for (i = ARRAY_SIZE(aty_chips); i >= 0; i--)
+ for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
if (pdev->device == aty_chips[i].pci_id)
break;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 9a6b5b39b88e..387a18a47ac2 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2265,7 +2265,7 @@ static struct bin_attribute edid2_attr = {
};
-static int radeonfb_pci_register (struct pci_dev *pdev,
+static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct fb_info *info;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 944855b3e4af..372aa1776827 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -435,6 +435,11 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
depth = info->var.green.length;
}
+ if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
+ /* assume console colormap */
+ depth = 4;
+ }
+
if (depth >= 8) {
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
@@ -669,13 +674,19 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
total_size = info->fix.smem_len;
if (p > total_size)
- return 0;
+ return -EFBIG;
- if (count >= total_size)
+ if (count > total_size) {
+ err = -EFBIG;
count = total_size;
+ }
+
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
- if (count + p > total_size)
count = total_size - p;
+ }
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
@@ -717,7 +728,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
kfree(buffer);
- return (err) ? err : cnt;
+ return (cnt) ? cnt : err;
}
#ifdef CONFIG_KMOD
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index b72b05250a9d..34e07399756b 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -305,94 +305,6 @@ static ssize_t show_stride(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
}
-/* Format for cmap is "%02x%c%4x%4x%4x\n" */
-/* %02x entry %c transp %4x red %4x blue %4x green \n */
-/* 256 rows at 16 chars equals 4096, the normal page size */
-/* the code will automatically adjust for different page sizes */
-static ssize_t store_cmap(struct class_device *class_device, const char *buf,
- size_t count)
-{
- struct fb_info *fb_info = class_get_devdata(class_device);
- int rc, i, start, length, transp = 0;
-
- if ((count > PAGE_SIZE) || ((count % 16) != 0))
- return -EINVAL;
-
- if (!fb_info->fbops->fb_setcolreg && !fb_info->fbops->fb_setcmap)
- return -EINVAL;
-
- sscanf(buf, "%02x", &start);
- length = count / 16;
-
- for (i = 0; i < length; i++)
- if (buf[i * 16 + 2] != ' ')
- transp = 1;
-
- /* If we can batch, do it */
- if (fb_info->fbops->fb_setcmap && length > 1) {
- struct fb_cmap umap;
-
- memset(&umap, 0, sizeof(umap));
- if ((rc = fb_alloc_cmap(&umap, length, transp)))
- return rc;
-
- umap.start = start;
- for (i = 0; i < length; i++) {
- sscanf(&buf[i * 16 + 3], "%4hx", &umap.red[i]);
- sscanf(&buf[i * 16 + 7], "%4hx", &umap.blue[i]);
- sscanf(&buf[i * 16 + 11], "%4hx", &umap.green[i]);
- if (transp)
- umap.transp[i] = (buf[i * 16 + 2] != ' ');
- }
- rc = fb_info->fbops->fb_setcmap(&umap, fb_info);
- fb_copy_cmap(&umap, &fb_info->cmap);
- fb_dealloc_cmap(&umap);
-
- return rc ?: count;
- }
- for (i = 0; i < length; i++) {
- u16 red, blue, green, tsp;
-
- sscanf(&buf[i * 16 + 3], "%4hx", &red);
- sscanf(&buf[i * 16 + 7], "%4hx", &blue);
- sscanf(&buf[i * 16 + 11], "%4hx", &green);
- tsp = (buf[i * 16 + 2] != ' ');
- if ((rc = fb_info->fbops->fb_setcolreg(start++,
- red, green, blue, tsp, fb_info)))
- return rc;
-
- fb_info->cmap.red[i] = red;
- fb_info->cmap.blue[i] = blue;
- fb_info->cmap.green[i] = green;
- if (transp)
- fb_info->cmap.transp[i] = tsp;
- }
- return count;
-}
-
-static ssize_t show_cmap(struct class_device *class_device, char *buf)
-{
- struct fb_info *fb_info = class_get_devdata(class_device);
- unsigned int i;
-
- if (!fb_info->cmap.red || !fb_info->cmap.blue ||
- !fb_info->cmap.green)
- return -EINVAL;
-
- if (fb_info->cmap.len > PAGE_SIZE / 16)
- return -EINVAL;
-
- /* don't mess with the format, the buffer is PAGE_SIZE */
- /* 256 entries at 16 chars per line equals 4096 = PAGE_SIZE */
- for (i = 0; i < fb_info->cmap.len; i++) {
- snprintf(&buf[ i * 16], PAGE_SIZE - i * 16, "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start,
- ((fb_info->cmap.transp && fb_info->cmap.transp[i]) ? '*' : ' '),
- fb_info->cmap.red[i], fb_info->cmap.blue[i],
- fb_info->cmap.green[i]);
- }
- return 16 * fb_info->cmap.len;
-}
-
static ssize_t store_blank(struct class_device *class_device, const char * buf,
size_t count)
{
@@ -502,10 +414,12 @@ static ssize_t show_fbstate(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
}
+/* When cmap is added back in it should be a binary attribute
+ * not a text one. Consideration should also be given to converting
+ * fbdev to use configfs instead of sysfs */
static struct class_device_attribute class_device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
- __ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap),
__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 5fe197943deb..4e963930b50a 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -73,8 +73,8 @@ static char *mode __devinitdata = NULL;
* these flags allow the user to specify that requests for +ve sync
* should be silently turned in -ve sync.
*/
-static int lowhsync __devinitdata = 0;
-static int lowvsync __devinitdata = 0;
+static int lowhsync;
+static int lowvsync;
/*
* The hardware state of the graphics card that isn't part of the
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 10e6b3aab9ea..0da624e6524f 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -73,7 +73,7 @@
/* --------------------------------------------------------------------- */
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
#ifdef MODULE
@@ -1545,7 +1545,7 @@ static int __devinit savage_map_mmio (struct fb_info *info)
return 0;
}
-static void __devinit savage_unmap_mmio (struct fb_info *info)
+static void savage_unmap_mmio (struct fb_info *info)
{
struct savagefb_par *par = info->par;
DBG ("savage_unmap_mmio");
@@ -1597,7 +1597,7 @@ static int __devinit savage_map_video (struct fb_info *info,
return 0;
}
-static void __devinit savage_unmap_video (struct fb_info *info)
+static void savage_unmap_video (struct fb_info *info)
{
struct savagefb_par *par = info->par;
@@ -1614,7 +1614,7 @@ static void __devinit savage_unmap_video (struct fb_info *info)
}
}
-static int __devinit savage_init_hw (struct savagefb_par *par)
+static int savage_init_hw (struct savagefb_par *par)
{
unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 8982e540214c..b0b9acfdd430 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -57,7 +57,7 @@ static unsigned short *pmi_base = NULL;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static int depth;
-
+static int vga_compat;
/* --------------------------------------------------------------------- */
static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
static void vesa_setpalette(int regno, unsigned red, unsigned green,
unsigned blue)
{
+ int shift = 16 - depth;
+
#ifdef __i386__
struct { u_char blue, green, red, pad; } entry;
- int shift = 16 - depth;
if (pmi_setpal) {
entry.red = red >> shift;
@@ -101,14 +102,20 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green,
"d" (regno), /* EDX */
"D" (&entry), /* EDI */
"S" (&pmi_pal)); /* ESI */
- } else {
- /* without protected mode interface, try VGA registers... */
+ return;
+ }
+#endif
+
+/*
+ * without protected mode interface and if VGA compatible,
+ * try VGA registers...
+ */
+ if (vga_compat) {
outb_p(regno, dac_reg);
outb_p(red >> shift, dac_val);
outb_p(green >> shift, dac_val);
outb_p(blue >> shift, dac_val);
}
-#endif
}
static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -214,6 +221,7 @@ static int __init vesafb_probe(struct platform_device *dev)
if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
return -ENODEV;
+ vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
vesafb_fix.smem_start = screen_info.lfb_base;
vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
if (15 == vesafb_defined.bits_per_pixel)
@@ -318,6 +326,12 @@ static int __init vesafb_probe(struct platform_device *dev)
}
}
+ if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
+ printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
+ " colors may be incorrect\n");
+ vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ }
+
vesafb_defined.xres_virtual = vesafb_defined.xres;
vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
@@ -354,7 +368,8 @@ static int __init vesafb_probe(struct platform_device *dev)
printk(KERN_INFO "vesafb: %s: "
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
(vesafb_defined.bits_per_pixel > 8) ?
- "Truecolor" : "Pseudocolor",
+ "Truecolor" : (vga_compat || pmi_setpal) ?
+ "Pseudocolor" : "Static Pseudocolor",
screen_info.rsvd_size,
screen_info.red_size,
screen_info.green_size,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index b0a0ae509c00..61c599b4a1e3 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -127,12 +127,13 @@ static struct super_block *v9fs_get_sb(struct file_system_type
if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
dprintk(DEBUG_ERROR, "problem initiating session\n");
- kfree(v9ses);
- return ERR_PTR(newfid);
+ sb = ERR_PTR(newfid);
+ goto out_free_session;
}
sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
-
+ if (IS_ERR(sb))
+ goto out_close_session;
v9fs_fill_super(sb, v9ses, flags);
inode = v9fs_get_inode(sb, S_IFDIR | mode);
@@ -185,6 +186,12 @@ static struct super_block *v9fs_get_sb(struct file_system_type
return sb;
+out_close_session:
+ v9fs_session_close(v9ses);
+out_free_session:
+ kfree(v9ses);
+ return sb;
+
put_back_sb:
/* deactivate_super calls v9fs_kill_super which will frees the rest */
up_write(&sb->s_umount);
diff --git a/fs/Kconfig b/fs/Kconfig
index e207be68d4ca..f9b5842c8d2d 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -799,6 +799,7 @@ config PROC_KCORE
config PROC_VMCORE
bool "/proc/vmcore support (EXPERIMENTAL)"
depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP
+ default y
help
Exports the dump image of crashed kernel in ELF format.
@@ -841,6 +842,12 @@ config TMPFS
config HUGETLBFS
bool "HugeTLB file system support"
depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+ help
+ hugetlbfs is a filesystem backing for HugeTLB pages, based on
+ ramfs. For architectures that support it, say Y here and read
+ <file:Documentation/vm/hugetlbpage.txt> for details.
+
+ If unsure, say N.
config HUGETLB_PAGE
def_bool HUGETLBFS
@@ -861,7 +868,7 @@ config RAMFS
config CONFIGFS_FS
tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ depends on SYSFS && EXPERIMENTAL
help
configfs is a ram-based filesystem that provides the converse
of sysfs's functionality. Where sysfs is a filesystem-based
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 8a2de038882e..1a27ecb46c9a 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,11 @@
Version 1.42
------------
Fix slow oplock break when mounted to different servers at the same time and
-the tids match and we try to find matching fid on wrong server.
+the tids match and we try to find matching fid on wrong server. Fix read
+looping when signing required by server (2.6.16 kernel only). Fix readdir
+vs. rename race which could cause each to hang. Return . and .. even
+if server does not. Allow searches to skip first three entries and
+begin at any location. Fix oops in find_writeable_file.
Version 1.41
------------
diff --git a/fs/cifs/README b/fs/cifs/README
index b2b4d0803761..0355003f4f0a 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -511,6 +511,14 @@ LinuxExtensionsEnabled If set to one then the client will attempt to
support and want to map the uid and gid fields
to values supplied at mount (rather than the
actual values, then set this to zero. (default 1)
+Experimental When set to 1 used to enable certain experimental
+ features (currently enables multipage writes
+ when signing is enabled, the multipage write
+ performance enhancement was disabled when
+ signing turned on in case buffer was modified
+ just before it was sent, also this flag will
+ be used to use the new experimental sessionsetup
+ code).
These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d4b713e5affb..c262d8874ce9 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -33,6 +33,7 @@
#include <linux/vfs.h>
#include <linux/mempool.h>
#include <linux/delay.h>
+#include <linux/kthread.h>
#include "cifsfs.h"
#include "cifspdu.h"
#define DECLARE_GLOBALS_HERE
@@ -75,9 +76,6 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ;
module_param(cifs_max_pending, int, 0);
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
-static DECLARE_COMPLETION(cifs_oplock_exited);
-static DECLARE_COMPLETION(cifs_dnotify_exited);
-
extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp;
@@ -841,10 +839,6 @@ static int cifs_oplock_thread(void * dummyarg)
__u16 netfid;
int rc;
- daemonize("cifsoplockd");
- allow_signal(SIGTERM);
-
- oplockThread = current;
do {
if (try_to_freeze())
continue;
@@ -900,9 +894,9 @@ static int cifs_oplock_thread(void * dummyarg)
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1); /* yield in case q were corrupt */
}
- } while(!signal_pending(current));
- oplockThread = NULL;
- complete_and_exit (&cifs_oplock_exited, 0);
+ } while (!kthread_should_stop());
+
+ return 0;
}
static int cifs_dnotify_thread(void * dummyarg)
@@ -910,10 +904,6 @@ static int cifs_dnotify_thread(void * dummyarg)
struct list_head *tmp;
struct cifsSesInfo *ses;
- daemonize("cifsdnotifyd");
- allow_signal(SIGTERM);
-
- dnotifyThread = current;
do {
if(try_to_freeze())
continue;
@@ -931,8 +921,9 @@ static int cifs_dnotify_thread(void * dummyarg)
wake_up_all(&ses->server->response_q);
}
read_unlock(&GlobalSMBSeslock);
- } while(!signal_pending(current));
- complete_and_exit (&cifs_dnotify_exited, 0);
+ } while (!kthread_should_stop());
+
+ return 0;
}
static int __init
@@ -982,32 +973,48 @@ init_cifs(void)
}
rc = cifs_init_inodecache();
- if (!rc) {
- rc = cifs_init_mids();
- if (!rc) {
- rc = cifs_init_request_bufs();
- if (!rc) {
- rc = register_filesystem(&cifs_fs_type);
- if (!rc) {
- rc = (int)kernel_thread(cifs_oplock_thread, NULL,
- CLONE_FS | CLONE_FILES | CLONE_VM);
- if(rc > 0) {
- rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
- CLONE_FS | CLONE_FILES | CLONE_VM);
- if(rc > 0)
- return 0;
- else
- cERROR(1,("error %d create dnotify thread", rc));
- } else {
- cERROR(1,("error %d create oplock thread",rc));
- }
- }
- cifs_destroy_request_bufs();
- }
- cifs_destroy_mids();
- }
- cifs_destroy_inodecache();
+ if (rc)
+ goto out_clean_proc;
+
+ rc = cifs_init_mids();
+ if (rc)
+ goto out_destroy_inodecache;
+
+ rc = cifs_init_request_bufs();
+ if (rc)
+ goto out_destroy_mids;
+
+ rc = register_filesystem(&cifs_fs_type);
+ if (rc)
+ goto out_destroy_request_bufs;
+
+ oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
+ if (IS_ERR(oplockThread)) {
+ rc = PTR_ERR(oplockThread);
+ cERROR(1,("error %d create oplock thread", rc));
+ goto out_unregister_filesystem;
}
+
+ dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
+ if (IS_ERR(dnotifyThread)) {
+ rc = PTR_ERR(dnotifyThread);
+ cERROR(1,("error %d create dnotify thread", rc));
+ goto out_stop_oplock_thread;
+ }
+
+ return 0;
+
+ out_stop_oplock_thread:
+ kthread_stop(oplockThread);
+ out_unregister_filesystem:
+ unregister_filesystem(&cifs_fs_type);
+ out_destroy_request_bufs:
+ cifs_destroy_request_bufs();
+ out_destroy_mids:
+ cifs_destroy_mids();
+ out_destroy_inodecache:
+ cifs_destroy_inodecache();
+ out_clean_proc:
#ifdef CONFIG_PROC_FS
cifs_proc_clean();
#endif
@@ -1025,14 +1032,8 @@ exit_cifs(void)
cifs_destroy_inodecache();
cifs_destroy_mids();
cifs_destroy_request_bufs();
- if(oplockThread) {
- send_sig(SIGTERM, oplockThread, 1);
- wait_for_completion(&cifs_oplock_exited);
- }
- if(dnotifyThread) {
- send_sig(SIGTERM, dnotifyThread, 1);
- wait_for_completion(&cifs_dnotify_exited);
- }
+ kthread_stop(oplockThread);
+ kthread_stop(dnotifyThread);
}
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d705500aa283..fd36892eda55 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3119,7 +3119,7 @@ findFirstRetry:
psrch_inf->endOfSearch = FALSE;
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
- psrch_inf->index_of_last_entry =
+ psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
psrch_inf->entries_in_buffer;
*pnetfid = parms->SearchHandle;
} else {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0b86d5ca9014..d2ec806a4f32 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3447,6 +3447,12 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
pSesInfo->server->secMode,
pSesInfo->server->capabilities,
pSesInfo->server->timeZone));
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if(experimEnabled > 1)
+ rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
+ &ntlmv2_flag, nls_info);
+ else
+#endif
if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) {
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1d0ca3eaaca5..82315edc77d7 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -139,9 +139,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -316,9 +314,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL)
rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) {
@@ -440,6 +436,20 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
pTcon = cifs_sb->tcon;
+ /*
+ * Don't allow the separator character in a path component.
+ * The VFS will not allow "/", but "\" is allowed by posix.
+ */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+ int i;
+ for (i = 0; i < direntry->d_name.len; i++)
+ if (direntry->d_name.name[i] == '\\') {
+ cFYI(1, ("Invalid file name"));
+ FreeXid(xid);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
/* can not grab the rename sem here since it would
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index ec4dfe9bf5ef..633a93811328 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -86,9 +86,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
- mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
rc = -ENOMEM;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5c497c529772..e152bf6afa60 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -203,9 +203,7 @@ int cifs_open(struct inode *inode, struct file *file)
}
}
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -906,8 +904,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (rc != 0)
break;
}
- /* BB FIXME We can not sign across two buffers yet */
- if((pTcon->ses->server->secMode &
+ if(experimEnabled || (pTcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
struct kvec iov[2];
unsigned int len;
@@ -923,13 +920,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
*poffset, &bytes_written,
iov, 1, long_op);
} else
- /* BB FIXME fixup indentation of line below */
- rc = CIFSSMBWrite(xid, pTcon,
- open_file->netfid,
- min_t(const int, cifs_sb->wsize,
- write_size - total_written),
- *poffset, &bytes_written,
- write_data + total_written, NULL, long_op);
+ rc = CIFSSMBWrite(xid, pTcon,
+ open_file->netfid,
+ min_t(const int, cifs_sb->wsize,
+ write_size - total_written),
+ *poffset, &bytes_written,
+ write_data + total_written,
+ NULL, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
@@ -968,6 +965,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
struct cifsFileInfo *open_file;
int rc;
+ /* Having a null inode here (because mapping->host was set to zero by
+ the VFS or MM) should not happen but we had reports of on oops (due to
+ it being zero) during stress testcases so we need to check for it */
+
+ if(cifs_inode == NULL) {
+ cERROR(1,("Null inode passed to cifs_writeable_file"));
+ dump_stack();
+ return NULL;
+ }
+
read_lock(&GlobalSMBSeslock);
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
@@ -1093,12 +1100,11 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
- /* BB FIXME we do not have code to sign across multiple buffers yet,
- so go to older writepage style write which we can sign if needed */
if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
if(cifs_sb->tcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- return generic_writepages(mapping, wbc);
+ if(!experimEnabled)
+ return generic_writepages(mapping, wbc);
/*
* BB: Is this meaningful for a non-block-device file system?
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 957ddd1571c6..4093764ef461 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -722,9 +722,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -807,9 +805,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -1141,9 +1137,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = 0;
}
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 9562f5bba65c..2ec99f833142 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -48,10 +48,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
/* No need to check for cross device links since server will do that
BB note DFS case in future though (when we may have to check) */
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_hl_exit;
@@ -103,9 +101,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid();
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if (!full_path)
goto out_no_free;
@@ -164,9 +160,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
index 78866f925747..115359cc7a32 100644
--- a/fs/cifs/ntlmssp.c
+++ b/fs/cifs/ntlmssp.c
@@ -121,6 +121,20 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
}
+ /* copy session key */
+
+ /* if Unicode, align strings to two byte boundary */
+
+ /* copy user name */ /* BB Do we need to special case null user name? */
+
+ /* copy domain name */
+
+ /* copy Linux version */
+
+ /* copy network operating system name */
+
+ /* update bcc and smb buffer length */
+
/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
/* SMB request buf freed in SendReceive2 */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 2f6e2825571e..b689c5035124 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -404,9 +404,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
if(pTcon == NULL)
return -EINVAL;
- mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
- mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
return -ENOMEM;
@@ -592,6 +590,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
first_entry_in_buffer =
cifsFile->srch_inf.index_of_last_entry -
cifsFile->srch_inf.entries_in_buffer;
+
+ /* if first entry in buf is zero then is first buffer
+ in search response data which means it is likely . and ..
+ will be in this buffer, although some servers do not return
+ . and .. for the root of a drive and for those we need
+ to start two entries earlier */
+
/* dump_cifs_file_struct(file, "In fce ");*/
if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
is_dir_changed(file)) ||
@@ -634,23 +639,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
smbCalcSize((struct smb_hdr *)
cifsFile->srch_inf.ntwrk_buf_start);
+
+ current_entry = cifsFile->srch_inf.srch_entries_start;
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
- cifsFile->srch_inf.entries_in_buffer;
pos_in_buf = index_to_find - first_entry_in_buffer;
cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
- current_entry = cifsFile->srch_inf.srch_entries_start;
for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
/* go entry by entry figuring out which is first */
- /* if( . or ..)
- skip */
- rc = cifs_entry_is_dot(current_entry,cifsFile);
- if(rc == 1) /* is . or .. so skip */ {
- cFYI(1,("Entry is .")); /* BB removeme BB */
- /* continue; */
- } else if (rc == 2 ) {
- cFYI(1,("Entry is ..")); /* BB removeme BB */
- /* continue; */
- }
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
if((current_entry == NULL) && (i < pos_in_buf)) {
@@ -770,6 +766,11 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if(file->f_dentry == NULL)
return -ENOENT;
+ rc = cifs_entry_is_dot(pfindEntry,pCifsF);
+ /* skip . and .. since we added them first */
+ if(rc != 0)
+ return 0;
+
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
qstring.name = scratch_buf;
@@ -898,22 +899,22 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
switch ((int) file->f_pos) {
case 0:
- /*if (filldir(direntry, ".", 1, file->f_pos,
+ if (filldir(direntry, ".", 1, file->f_pos,
file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
- cERROR(1, ("Filldir for current dir failed "));
+ cERROR(1, ("Filldir for current dir failed"));
rc = -ENOMEM;
break;
}
- file->f_pos++; */
+ file->f_pos++;
case 1:
- /* if (filldir(direntry, "..", 2, file->f_pos,
+ if (filldir(direntry, "..", 2, file->f_pos,
file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for parent dir failed "));
rc = -ENOMEM;
break;
}
- file->f_pos++; */
- case 2:
+ file->f_pos++;
+ default:
/* 1) If search is active,
is in current search buffer?
if it before then restart search
@@ -927,7 +928,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
return rc;
}
}
- default:
if(file->private_data == NULL) {
rc = -EINVAL;
FreeXid(xid);
@@ -947,8 +947,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name = NULL; */
- /* BB account for . and .. in f_pos as special case */
-
rc = find_cifs_entry(xid,pTcon, file,
&current_entry,&num_to_fill);
if(rc) {
@@ -977,7 +975,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
num_to_fill, i));
break;
}
-
+ /* if buggy server returns . and .. late do
+ we want to check for that here? */
rc = cifs_filldir(current_entry, file,
filldir, direntry,tmp_buf);
file->f_pos++;
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 3938444d87b2..7754d641775e 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -62,9 +62,7 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -116,9 +114,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -223,9 +219,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -341,9 +335,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
diff --git a/fs/compat.c b/fs/compat.c
index 7f8e26ea427c..2e32bd340474 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1217,6 +1217,10 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
if (ret < 0)
goto out;
+ ret = security_file_permission(file, type == READ ? MAY_READ:MAY_WRITE);
+ if (ret)
+ goto out;
+
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 8ed9b06a9828..5638c8f9362f 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -504,7 +504,7 @@ static int populate_groups(struct config_group *group)
int ret = 0;
int i;
- if (group && group->default_groups) {
+ if (group->default_groups) {
/* FYI, we're faking mkdir here
* I'm not sure we need this semaphore, as we're called
* from our parent's mkdir. That holds our parent's
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 910a8ed74b5d..b05d1b218776 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -929,8 +929,7 @@ do_holes:
block_in_page += this_chunk_blocks;
dio->blocks_available -= this_chunk_blocks;
next_block:
- if (dio->block_in_file > dio->final_block_in_request)
- BUG();
+ BUG_ON(dio->block_in_file > dio->final_block_in_request);
if (dio->block_in_file == dio->final_block_in_request)
break;
}
diff --git a/fs/dquot.c b/fs/dquot.c
index 6b3886920939..81d87a413c68 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -590,8 +590,7 @@ we_slept:
atomic_dec(&dquot->dq_count);
#ifdef __DQUOT_PARANOIA
/* sanity check */
- if (!list_empty(&dquot->dq_free))
- BUG();
+ BUG_ON(!list_empty(&dquot->dq_free));
#endif
put_dquot_last(dquot);
spin_unlock(&dq_list_lock);
@@ -666,8 +665,7 @@ we_slept:
return NODQUOT;
}
#ifdef __DQUOT_PARANOIA
- if (!dquot->dq_sb) /* Has somebody invalidated entry under us? */
- BUG();
+ BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
#endif
return dquot;
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 242fe1a66ce5..1b4491cdd115 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -599,7 +599,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
switch (op) {
case EPOLL_CTL_ADD:
if (!epi) {
- epds.events |= POLLERR | POLLHUP | POLLRDHUP;
+ epds.events |= POLLERR | POLLHUP;
error = ep_insert(ep, &epds, tfile, fd);
} else
@@ -613,7 +613,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
break;
case EPOLL_CTL_MOD:
if (epi) {
- epds.events |= POLLERR | POLLHUP | POLLRDHUP;
+ epds.events |= POLLERR | POLLHUP;
error = ep_modify(ep, epi, &epds);
} else
error = -ENOENT;
diff --git a/fs/exec.c b/fs/exec.c
index 950ebd43cdc3..3a79d97ac234 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -561,7 +561,7 @@ static int exec_mmap(struct mm_struct *mm)
arch_pick_mmap_layout(mm);
if (old_mm) {
up_read(&old_mm->mmap_sem);
- if (active_mm != old_mm) BUG();
+ BUG_ON(active_mm != old_mm);
mmput(old_mm);
return 0;
}
@@ -665,9 +665,7 @@ static int de_thread(struct task_struct *tsk)
* and to assume its PID:
*/
if (!thread_group_leader(current)) {
- struct task_struct *parent;
struct dentry *proc_dentry1, *proc_dentry2;
- unsigned long ptrace;
/*
* Wait for the thread group leader to be a zombie.
@@ -678,6 +676,18 @@ static int de_thread(struct task_struct *tsk)
while (leader->exit_state != EXIT_ZOMBIE)
yield();
+ /*
+ * The only record we have of the real-time age of a
+ * process, regardless of execs it's done, is start_time.
+ * All the past CPU time is accumulated in signal_struct
+ * from sister threads now dead. But in this non-leader
+ * exec, nothing survives from the original leader thread,
+ * whose birth marks the true age of this process now.
+ * When we take on its identity by switching to its PID, we
+ * also take its birthdate (always earlier than our own).
+ */
+ current->start_time = leader->start_time;
+
spin_lock(&leader->proc_lock);
spin_lock(&current->proc_lock);
proc_dentry1 = proc_pid_unhash(current);
@@ -692,22 +702,6 @@ static int de_thread(struct task_struct *tsk)
* two threads with a switched PID, and release
* the former thread group leader:
*/
- ptrace = leader->ptrace;
- parent = leader->parent;
- if (unlikely(ptrace) && unlikely(parent == current)) {
- /*
- * Joker was ptracing his own group leader,
- * and now he wants to be his own parent!
- * We can't have that.
- */
- ptrace = 0;
- }
-
- ptrace_unlink(current);
- ptrace_unlink(leader);
- remove_parent(current);
- remove_parent(leader);
-
/* Become a process group leader with the old leader's pid.
* Note: The old leader also uses thispid until release_task
@@ -718,19 +712,15 @@ static int de_thread(struct task_struct *tsk)
attach_pid(current, PIDTYPE_PID, current->pid);
attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
attach_pid(current, PIDTYPE_SID, current->signal->session);
- list_add_tail(&current->tasks, &init_task.tasks);
+ list_add_tail_rcu(&current->tasks, &init_task.tasks);
- current->parent = current->real_parent = leader->real_parent;
- leader->parent = leader->real_parent = child_reaper;
current->group_leader = current;
- leader->group_leader = leader;
+ leader->group_leader = current;
- add_parent(current);
- add_parent(leader);
- if (ptrace) {
- current->ptrace = ptrace;
- __ptrace_link(current, parent);
- }
+ /* Reduce leader to a thread */
+ detach_pid(leader, PIDTYPE_PGID);
+ detach_pid(leader, PIDTYPE_SID);
+ list_del_init(&leader->tasks);
current->exit_signal = SIGCHLD;
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index aaf1da17b6d4..8c22aa9a7fbb 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -48,6 +48,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (!S_ISDIR(inode->i_mode))
flags &= ~EXT3_DIRSYNC_FL;
+ mutex_lock(&inode->i_mutex);
oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */
@@ -60,8 +61,10 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
* This test looks nicer. Thanks to Pauline Middelink
*/
if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
- if (!capable(CAP_LINUX_IMMUTABLE))
+ if (!capable(CAP_LINUX_IMMUTABLE)) {
+ mutex_unlock(&inode->i_mutex);
return -EPERM;
+ }
}
/*
@@ -69,14 +72,18 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
* the relevant capability.
*/
if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
- if (!capable(CAP_SYS_RESOURCE))
+ if (!capable(CAP_SYS_RESOURCE)) {
+ mutex_unlock(&inode->i_mutex);
return -EPERM;
+ }
}
handle = ext3_journal_start(inode, 1);
- if (IS_ERR(handle))
+ if (IS_ERR(handle)) {
+ mutex_unlock(&inode->i_mutex);
return PTR_ERR(handle);
+ }
if (IS_SYNC(inode))
handle->h_sync = 1;
err = ext3_reserve_inode_write(handle, inode, &iloc);
@@ -93,11 +100,14 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
err = ext3_mark_iloc_dirty(handle, inode, &iloc);
flags_err:
ext3_journal_stop(handle);
- if (err)
+ if (err) {
+ mutex_unlock(&inode->i_mutex);
return err;
+ }
if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
err = ext3_change_inode_journal_flag(inode, jflag);
+ mutex_unlock(&inode->i_mutex);
return err;
}
case EXT3_IOC_GETVERSION:
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 1041dab6de2f..8aac5334680d 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -213,7 +213,7 @@ static int setup_new_group_blocks(struct super_block *sb,
goto exit_bh;
}
lock_buffer(bh);
- memcpy(gdb->b_data, sbi->s_group_desc[i], bh->b_size);
+ memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
set_buffer_uptodate(gdb);
unlock_buffer(bh);
ext3_journal_dirty_metadata(handle, gdb);
@@ -767,6 +767,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
if (input->group != sbi->s_groups_count) {
ext3_warning(sb, __FUNCTION__,
"multiple resizers run on filesystem!");
+ unlock_super(sb);
err = -EBUSY;
goto exit_journal;
}
@@ -974,6 +975,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
ext3_warning(sb, __FUNCTION__,
"multiple resizers run on filesystem!");
+ unlock_super(sb);
err = -EBUSY;
goto exit_put;
}
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 2a2479196f96..d35cbc6bc112 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -453,8 +453,7 @@ static void send_sigio_to_task(struct task_struct *p,
/* Make sure we are called with one of the POLL_*
reasons, otherwise we could leak kernel stack into
userspace. */
- if ((reason & __SI_MASK) != __SI_POLL)
- BUG();
+ BUG_ON((reason & __SI_MASK) != __SI_POLL);
if (reason - POLL_IN >= NSIGPOLL)
si.si_band = ~0L;
else
diff --git a/fs/fifo.c b/fs/fifo.c
index 889f722ee36d..49035b174b48 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -15,30 +15,35 @@
#include <linux/fs.h>
#include <linux/pipe_fs_i.h>
-static void wait_for_partner(struct inode* inode, unsigned int* cnt)
+static void wait_for_partner(struct inode* inode, unsigned int *cnt)
{
int cur = *cnt;
- while(cur == *cnt) {
- pipe_wait(inode);
- if(signal_pending(current))
+
+ while (cur == *cnt) {
+ pipe_wait(inode->i_pipe);
+ if (signal_pending(current))
break;
}
}
static void wake_up_partner(struct inode* inode)
{
- wake_up_interruptible(PIPE_WAIT(*inode));
+ wake_up_interruptible(&inode->i_pipe->wait);
}
static int fifo_open(struct inode *inode, struct file *filp)
{
+ struct pipe_inode_info *pipe;
int ret;
- mutex_lock(PIPE_MUTEX(*inode));
- if (!inode->i_pipe) {
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
+ if (!pipe) {
ret = -ENOMEM;
- if(!pipe_new(inode))
+ pipe = alloc_pipe_info(inode);
+ if (!pipe)
goto err_nocleanup;
+ inode->i_pipe = pipe;
}
filp->f_version = 0;
@@ -53,18 +58,18 @@ static int fifo_open(struct inode *inode, struct file *filp)
* opened, even when there is no process writing the FIFO.
*/
filp->f_op = &read_fifo_fops;
- PIPE_RCOUNTER(*inode)++;
- if (PIPE_READERS(*inode)++ == 0)
+ pipe->r_counter++;
+ if (pipe->readers++ == 0)
wake_up_partner(inode);
- if (!PIPE_WRITERS(*inode)) {
+ if (!pipe->writers) {
if ((filp->f_flags & O_NONBLOCK)) {
/* suppress POLLHUP until we have
* seen a writer */
- filp->f_version = PIPE_WCOUNTER(*inode);
+ filp->f_version = pipe->w_counter;
} else
{
- wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
+ wait_for_partner(inode, &pipe->w_counter);
if(signal_pending(current))
goto err_rd;
}
@@ -78,16 +83,16 @@ static int fifo_open(struct inode *inode, struct file *filp)
* errno=ENXIO when there is no process reading the FIFO.
*/
ret = -ENXIO;
- if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
+ if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
goto err;
filp->f_op = &write_fifo_fops;
- PIPE_WCOUNTER(*inode)++;
- if (!PIPE_WRITERS(*inode)++)
+ pipe->w_counter++;
+ if (!pipe->writers++)
wake_up_partner(inode);
- if (!PIPE_READERS(*inode)) {
- wait_for_partner(inode, &PIPE_RCOUNTER(*inode));
+ if (!pipe->readers) {
+ wait_for_partner(inode, &pipe->r_counter);
if (signal_pending(current))
goto err_wr;
}
@@ -102,11 +107,11 @@ static int fifo_open(struct inode *inode, struct file *filp)
*/
filp->f_op = &rdwr_fifo_fops;
- PIPE_READERS(*inode)++;
- PIPE_WRITERS(*inode)++;
- PIPE_RCOUNTER(*inode)++;
- PIPE_WCOUNTER(*inode)++;
- if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
+ pipe->readers++;
+ pipe->writers++;
+ pipe->r_counter++;
+ pipe->w_counter++;
+ if (pipe->readers == 1 || pipe->writers == 1)
wake_up_partner(inode);
break;
@@ -116,27 +121,27 @@ static int fifo_open(struct inode *inode, struct file *filp)
}
/* Ok! */
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
return 0;
err_rd:
- if (!--PIPE_READERS(*inode))
- wake_up_interruptible(PIPE_WAIT(*inode));
+ if (!--pipe->readers)
+ wake_up_interruptible(&pipe->wait);
ret = -ERESTARTSYS;
goto err;
err_wr:
- if (!--PIPE_WRITERS(*inode))
- wake_up_interruptible(PIPE_WAIT(*inode));
+ if (!--pipe->writers)
+ wake_up_interruptible(&pipe->wait);
ret = -ERESTARTSYS;
goto err;
err:
- if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode))
+ if (!pipe->readers && !pipe->writers)
free_pipe_info(inode);
err_nocleanup:
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
return ret;
}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 76a0708ae978..049500847903 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -42,24 +42,21 @@
static inline void
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
{
- if (infp->vsi_fshino)
- BUG();
+ BUG_ON(infp->vsi_fshino);
infp->vsi_fshino = fshp->olt_fsino[0];
}
static inline void
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
{
- if (infp->vsi_iext)
- BUG();
+ BUG_ON(infp->vsi_iext);
infp->vsi_iext = ilistp->olt_iext[0];
}
static inline u_long
vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
{
- if (sbp->s_blocksize % bsize)
- BUG();
+ BUG_ON(sbp->s_blocksize % bsize);
return (block * (sbp->s_blocksize / bsize));
}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 23d1f52eb1b8..104a62dadb94 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -23,13 +23,11 @@ static kmem_cache_t *fuse_req_cachep;
static struct fuse_conn *fuse_get_conn(struct file *file)
{
- struct fuse_conn *fc;
- spin_lock(&fuse_lock);
- fc = file->private_data;
- if (fc && !fc->connected)
- fc = NULL;
- spin_unlock(&fuse_lock);
- return fc;
+ /*
+ * Lockless access is OK, because file->private data is set
+ * once during mount and is valid until the file is released.
+ */
+ return file->private_data;
}
static void fuse_request_init(struct fuse_req *req)
@@ -74,10 +72,8 @@ static void restore_sigs(sigset_t *oldset)
*/
void fuse_reset_request(struct fuse_req *req)
{
- int preallocated = req->preallocated;
BUG_ON(atomic_read(&req->count) != 1);
fuse_request_init(req);
- req->preallocated = preallocated;
}
static void __fuse_get_request(struct fuse_req *req)
@@ -92,80 +88,64 @@ static void __fuse_put_request(struct fuse_req *req)
atomic_dec(&req->count);
}
-static struct fuse_req *do_get_request(struct fuse_conn *fc)
+struct fuse_req *fuse_get_req(struct fuse_conn *fc)
{
struct fuse_req *req;
-
- spin_lock(&fuse_lock);
- BUG_ON(list_empty(&fc->unused_list));
- req = list_entry(fc->unused_list.next, struct fuse_req, list);
- list_del_init(&req->list);
- spin_unlock(&fuse_lock);
- fuse_request_init(req);
- req->preallocated = 1;
- req->in.h.uid = current->fsuid;
- req->in.h.gid = current->fsgid;
- req->in.h.pid = current->pid;
- return req;
-}
-
-/* This can return NULL, but only in case it's interrupted by a SIGKILL */
-struct fuse_req *fuse_get_request(struct fuse_conn *fc)
-{
- int intr;
sigset_t oldset;
+ int intr;
+ int err;
atomic_inc(&fc->num_waiting);
block_sigs(&oldset);
- intr = down_interruptible(&fc->outstanding_sem);
+ intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
restore_sigs(&oldset);
- if (intr) {
- atomic_dec(&fc->num_waiting);
- return NULL;
- }
- return do_get_request(fc);
-}
+ err = -EINTR;
+ if (intr)
+ goto out;
-/* Must be called with fuse_lock held */
-static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
-{
- if (req->preallocated) {
- atomic_dec(&fc->num_waiting);
- list_add(&req->list, &fc->unused_list);
- } else
- fuse_request_free(req);
+ req = fuse_request_alloc();
+ err = -ENOMEM;
+ if (!req)
+ goto out;
- /* If we are in debt decrease that first */
- if (fc->outstanding_debt)
- fc->outstanding_debt--;
- else
- up(&fc->outstanding_sem);
+ req->in.h.uid = current->fsuid;
+ req->in.h.gid = current->fsgid;
+ req->in.h.pid = current->pid;
+ req->waiting = 1;
+ return req;
+
+ out:
+ atomic_dec(&fc->num_waiting);
+ return ERR_PTR(err);
}
void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
{
if (atomic_dec_and_test(&req->count)) {
- spin_lock(&fuse_lock);
- fuse_putback_request(fc, req);
- spin_unlock(&fuse_lock);
+ if (req->waiting)
+ atomic_dec(&fc->num_waiting);
+ fuse_request_free(req);
}
}
-static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req)
-{
- if (atomic_dec_and_test(&req->count))
- fuse_putback_request(fc, req);
-}
-
-void fuse_release_background(struct fuse_req *req)
+/*
+ * Called with sbput_sem held for read (request_end) or write
+ * (fuse_put_super). By the time fuse_put_super() is finished, all
+ * inodes belonging to background requests must be released, so the
+ * iputs have to be done within the locked region.
+ */
+void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
{
iput(req->inode);
iput(req->inode2);
- if (req->file)
- fput(req->file);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
list_del(&req->bg_entry);
- spin_unlock(&fuse_lock);
+ if (fc->num_background == FUSE_MAX_BACKGROUND) {
+ fc->blocked = 0;
+ wake_up_all(&fc->blocked_waitq);
+ }
+ fc->num_background--;
+ spin_unlock(&fc->lock);
}
/*
@@ -184,24 +164,29 @@ void fuse_release_background(struct fuse_req *req)
* interrupted and put in the background, it will return with an error
* and hence never be reset and reused.
*
- * Called with fuse_lock, unlocks it
+ * Called with fc->lock, unlocks it
*/
static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{
list_del(&req->list);
req->state = FUSE_REQ_FINISHED;
if (!req->background) {
+ spin_unlock(&fc->lock);
wake_up(&req->waitq);
- fuse_put_request_locked(fc, req);
- spin_unlock(&fuse_lock);
+ fuse_put_request(fc, req);
} else {
void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
req->end = NULL;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
down_read(&fc->sbput_sem);
if (fc->mounted)
- fuse_release_background(req);
+ fuse_release_background(fc, req);
up_read(&fc->sbput_sem);
+
+ /* fput must go outside sbput_sem, otherwise it can deadlock */
+ if (req->file)
+ fput(req->file);
+
if (end)
end(fc, req);
else
@@ -242,6 +227,9 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req)
{
req->background = 1;
list_add(&req->bg_entry, &fc->background);
+ fc->num_background++;
+ if (fc->num_background == FUSE_MAX_BACKGROUND)
+ fc->blocked = 1;
if (req->inode)
req->inode = igrab(req->inode);
if (req->inode2)
@@ -250,16 +238,16 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req)
get_file(req->file);
}
-/* Called with fuse_lock held. Releases, and then reacquires it. */
+/* Called with fc->lock held. Releases, and then reacquires it. */
static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
{
sigset_t oldset;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
block_sigs(&oldset);
wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
restore_sigs(&oldset);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
return;
@@ -273,9 +261,9 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
locked state, there mustn't be any filesystem
operation (e.g. page fault), since that could lead
to deadlock */
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
wait_event(req->waitq, !req->locked);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
if (req->state == FUSE_REQ_PENDING) {
list_del(&req->list);
@@ -304,19 +292,14 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
req->in.h.unique = fc->reqctr;
req->in.h.len = sizeof(struct fuse_in_header) +
len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
- if (!req->preallocated) {
- /* If request is not preallocated (either FORGET or
- RELEASE), then still decrease outstanding_sem, so
- user can't open infinite number of files while not
- processing the RELEASE requests. However for
- efficiency do it without blocking, so if down()
- would block, just increase the debt instead */
- if (down_trylock(&fc->outstanding_sem))
- fc->outstanding_debt++;
- }
list_add_tail(&req->list, &fc->pending);
req->state = FUSE_REQ_PENDING;
+ if (!req->waiting) {
+ req->waiting = 1;
+ atomic_inc(&fc->num_waiting);
+ }
wake_up(&fc->waitq);
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
/*
@@ -325,7 +308,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
req->isreply = 1;
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (!fc->connected)
req->out.h.error = -ENOTCONN;
else if (fc->conn_error)
@@ -338,15 +321,16 @@ void request_send(struct fuse_conn *fc, struct fuse_req *req)
request_wait_answer(fc, req);
}
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
{
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
+ background_request(fc, req);
if (fc->connected) {
queue_request(fc, req);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
} else {
req->out.h.error = -ENOTCONN;
request_end(fc, req);
@@ -362,9 +346,6 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
{
req->isreply = 1;
- spin_lock(&fuse_lock);
- background_request(fc, req);
- spin_unlock(&fuse_lock);
request_send_nowait(fc, req);
}
@@ -373,16 +354,16 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
* anything that could cause a page-fault. If the request was already
* interrupted bail out.
*/
-static int lock_request(struct fuse_req *req)
+static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
{
int err = 0;
if (req) {
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (req->interrupted)
err = -ENOENT;
else
req->locked = 1;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
return err;
}
@@ -392,18 +373,19 @@ static int lock_request(struct fuse_req *req)
* requester thread is currently waiting for it to be unlocked, so
* wake it up.
*/
-static void unlock_request(struct fuse_req *req)
+static void unlock_request(struct fuse_conn *fc, struct fuse_req *req)
{
if (req) {
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
req->locked = 0;
if (req->interrupted)
wake_up(&req->waitq);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
}
struct fuse_copy_state {
+ struct fuse_conn *fc;
int write;
struct fuse_req *req;
const struct iovec *iov;
@@ -416,11 +398,12 @@ struct fuse_copy_state {
unsigned len;
};
-static void fuse_copy_init(struct fuse_copy_state *cs, int write,
- struct fuse_req *req, const struct iovec *iov,
- unsigned long nr_segs)
+static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc,
+ int write, struct fuse_req *req,
+ const struct iovec *iov, unsigned long nr_segs)
{
memset(cs, 0, sizeof(*cs));
+ cs->fc = fc;
cs->write = write;
cs->req = req;
cs->iov = iov;
@@ -450,7 +433,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
unsigned long offset;
int err;
- unlock_request(cs->req);
+ unlock_request(cs->fc, cs->req);
fuse_copy_finish(cs);
if (!cs->seglen) {
BUG_ON(!cs->nr_segs);
@@ -473,7 +456,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
cs->seglen -= cs->len;
cs->addr += cs->len;
- return lock_request(cs->req);
+ return lock_request(cs->fc, cs->req);
}
/* Do as much copy to/from userspace buffer as we can */
@@ -585,9 +568,9 @@ static void request_wait(struct fuse_conn *fc)
if (signal_pending(current))
break;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
schedule();
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&fc->waitq, &wait);
@@ -606,18 +589,21 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *off)
{
int err;
- struct fuse_conn *fc;
struct fuse_req *req;
struct fuse_in *in;
struct fuse_copy_state cs;
unsigned reqsize;
+ struct fuse_conn *fc = fuse_get_conn(file);
+ if (!fc)
+ return -EPERM;
restart:
- spin_lock(&fuse_lock);
- fc = file->private_data;
- err = -EPERM;
- if (!fc)
+ spin_lock(&fc->lock);
+ err = -EAGAIN;
+ if ((file->f_flags & O_NONBLOCK) && fc->connected &&
+ list_empty(&fc->pending))
goto err_unlock;
+
request_wait(fc);
err = -ENODEV;
if (!fc->connected)
@@ -641,14 +627,14 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
request_end(fc, req);
goto restart;
}
- spin_unlock(&fuse_lock);
- fuse_copy_init(&cs, 1, req, iov, nr_segs);
+ spin_unlock(&fc->lock);
+ fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);
err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
if (!err)
err = fuse_copy_args(&cs, in->numargs, in->argpages,
(struct fuse_arg *) in->args, 0);
fuse_copy_finish(&cs);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
req->locked = 0;
if (!err && req->interrupted)
err = -ENOENT;
@@ -663,12 +649,12 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
else {
req->state = FUSE_REQ_SENT;
list_move_tail(&req->list, &fc->processing);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
return reqsize;
err_unlock:
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
return err;
}
@@ -735,9 +721,9 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
struct fuse_copy_state cs;
struct fuse_conn *fc = fuse_get_conn(file);
if (!fc)
- return -ENODEV;
+ return -EPERM;
- fuse_copy_init(&cs, 0, NULL, iov, nr_segs);
+ fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs);
if (nbytes < sizeof(struct fuse_out_header))
return -EINVAL;
@@ -749,7 +735,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
oh.len != nbytes)
goto err_finish;
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
err = -ENOENT;
if (!fc->connected)
goto err_unlock;
@@ -760,9 +746,9 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
goto err_unlock;
if (req->interrupted) {
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
fuse_copy_finish(&cs);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
request_end(fc, req);
return -ENOENT;
}
@@ -770,12 +756,12 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
req->out.h = oh;
req->locked = 1;
cs.req = req;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
err = copy_out_args(&cs, &req->out, nbytes);
fuse_copy_finish(&cs);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
req->locked = 0;
if (!err) {
if (req->interrupted)
@@ -787,7 +773,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
return err ? err : nbytes;
err_unlock:
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
err_finish:
fuse_copy_finish(&cs);
return err;
@@ -804,18 +790,19 @@ static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
{
- struct fuse_conn *fc = fuse_get_conn(file);
unsigned mask = POLLOUT | POLLWRNORM;
-
+ struct fuse_conn *fc = fuse_get_conn(file);
if (!fc)
- return -ENODEV;
+ return POLLERR;
poll_wait(file, &fc->waitq, wait);
- spin_lock(&fuse_lock);
- if (!list_empty(&fc->pending))
- mask |= POLLIN | POLLRDNORM;
- spin_unlock(&fuse_lock);
+ spin_lock(&fc->lock);
+ if (!fc->connected)
+ mask = POLLERR;
+ else if (!list_empty(&fc->pending))
+ mask |= POLLIN | POLLRDNORM;
+ spin_unlock(&fc->lock);
return mask;
}
@@ -823,7 +810,7 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
/*
* Abort all requests on the given list (pending or processing)
*
- * This function releases and reacquires fuse_lock
+ * This function releases and reacquires fc->lock
*/
static void end_requests(struct fuse_conn *fc, struct list_head *head)
{
@@ -832,7 +819,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
req = list_entry(head->next, struct fuse_req, list);
req->out.h.error = -ECONNABORTED;
request_end(fc, req);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
}
@@ -863,10 +850,10 @@ static void end_io_requests(struct fuse_conn *fc)
req->end = NULL;
/* The end function will consume this reference */
__fuse_get_request(req);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
wait_event(req->waitq, !req->locked);
end(fc, req);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
}
}
@@ -893,35 +880,44 @@ static void end_io_requests(struct fuse_conn *fc)
*/
void fuse_abort_conn(struct fuse_conn *fc)
{
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (fc->connected) {
fc->connected = 0;
end_io_requests(fc);
end_requests(fc, &fc->pending);
end_requests(fc, &fc->processing);
wake_up_all(&fc->waitq);
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
static int fuse_dev_release(struct inode *inode, struct file *file)
{
- struct fuse_conn *fc;
-
- spin_lock(&fuse_lock);
- fc = file->private_data;
+ struct fuse_conn *fc = fuse_get_conn(file);
if (fc) {
+ spin_lock(&fc->lock);
fc->connected = 0;
end_requests(fc, &fc->pending);
end_requests(fc, &fc->processing);
- }
- spin_unlock(&fuse_lock);
- if (fc)
+ spin_unlock(&fc->lock);
+ fasync_helper(-1, file, 0, &fc->fasync);
kobject_put(&fc->kobj);
+ }
return 0;
}
+static int fuse_dev_fasync(int fd, struct file *file, int on)
+{
+ struct fuse_conn *fc = fuse_get_conn(file);
+ if (!fc)
+ return -EPERM;
+
+ /* No locking - fasync_helper does its own locking */
+ return fasync_helper(fd, file, on, &fc->fasync);
+}
+
const struct file_operations fuse_dev_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -931,6 +927,7 @@ const struct file_operations fuse_dev_operations = {
.writev = fuse_dev_writev,
.poll = fuse_dev_poll,
.release = fuse_dev_release,
+ .fasync = fuse_dev_fasync,
};
static struct miscdevice fuse_miscdevice = {
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 256355b80256..8d7546e832e8 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -117,8 +117,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
return 0;
fc = get_fuse_conn(inode);
- req = fuse_get_request(fc);
- if (!req)
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
return 0;
fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
@@ -188,9 +188,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
if (entry->d_name.len > FUSE_NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
- req = fuse_get_request(fc);
- if (!req)
- return ERR_PTR(-EINTR);
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return ERR_PTR(PTR_ERR(req));
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
@@ -244,15 +244,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
struct file *file;
int flags = nd->intent.open.flags - 1;
- err = -ENOSYS;
if (fc->no_create)
- goto out;
+ return -ENOSYS;
- err = -EINTR;
- req = fuse_get_request(fc);
- if (!req)
- goto out;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+ err = -ENOMEM;
ff = fuse_file_alloc();
if (!ff)
goto out_put_request;
@@ -314,7 +313,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
fuse_file_free(ff);
out_put_request:
fuse_put_request(fc, req);
- out:
return err;
}
@@ -375,9 +373,9 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
{
struct fuse_mknod_in inarg;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
@@ -407,9 +405,9 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
{
struct fuse_mkdir_in inarg;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
@@ -427,9 +425,9 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
{
struct fuse_conn *fc = get_fuse_conn(dir);
unsigned len = strlen(link) + 1;
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_SYMLINK;
req->in.numargs = 2;
@@ -444,9 +442,9 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
{
int err;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_UNLINK;
req->in.h.nodeid = get_node_id(dir);
@@ -476,9 +474,9 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
int err;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_RMDIR;
req->in.h.nodeid = get_node_id(dir);
@@ -504,9 +502,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
int err;
struct fuse_rename_in inarg;
struct fuse_conn *fc = get_fuse_conn(olddir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.newdir = get_node_id(newdir);
@@ -553,9 +551,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
struct fuse_link_in inarg;
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.oldnodeid = get_node_id(inode);
@@ -583,9 +581,9 @@ int fuse_do_getattr(struct inode *inode)
int err;
struct fuse_attr_out arg;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_GETATTR;
req->in.h.nodeid = get_node_id(inode);
@@ -673,9 +671,9 @@ static int fuse_access(struct inode *inode, int mask)
if (fc->no_access)
return 0;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.mask = mask;
@@ -780,9 +778,9 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
if (is_bad_inode(inode))
return -EIO;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
page = alloc_page(GFP_KERNEL);
if (!page) {
@@ -809,11 +807,11 @@ static char *read_link(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
+ struct fuse_req *req = fuse_get_req(fc);
char *link;
- if (!req)
- return ERR_PTR(-EINTR);
+ if (IS_ERR(req))
+ return ERR_PTR(PTR_ERR(req));
link = (char *) __get_free_page(GFP_KERNEL);
if (!link) {
@@ -933,9 +931,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
}
}
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
iattr_to_fattr(attr, &inarg);
@@ -995,9 +993,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
if (fc->no_setxattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -1035,9 +1033,9 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
if (fc->no_getxattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -1085,9 +1083,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
if (fc->no_listxattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -1131,9 +1129,9 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
if (fc->no_removexattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_REMOVEXATTR;
req->in.h.nodeid = get_node_id(inode);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 975f2697e866..fc342cf7c2cc 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -22,9 +22,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
struct fuse_req *req;
int err;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
@@ -184,9 +184,9 @@ static int fuse_flush(struct file *file)
if (fc->no_flush)
return 0;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
@@ -223,9 +223,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
return 0;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
@@ -297,9 +297,9 @@ static int fuse_readpage(struct file *file, struct page *page)
if (is_bad_inode(inode))
goto out;
- err = -EINTR;
- req = fuse_get_request(fc);
- if (!req)
+ req = fuse_get_req(fc);
+ err = PTR_ERR(req);
+ if (IS_ERR(req))
goto out;
req->out.page_zeroing = 1;
@@ -368,10 +368,10 @@ static int fuse_readpages_fill(void *_data, struct page *page)
(req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
req->pages[req->num_pages - 1]->index + 1 != page->index)) {
fuse_send_readpages(req, data->file, inode);
- data->req = req = fuse_get_request(fc);
- if (!req) {
+ data->req = req = fuse_get_req(fc);
+ if (IS_ERR(req)) {
unlock_page(page);
- return -EINTR;
+ return PTR_ERR(req);
}
}
req->pages[req->num_pages] = page;
@@ -392,13 +392,17 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
data.file = file;
data.inode = inode;
- data.req = fuse_get_request(fc);
- if (!data.req)
- return -EINTR;
+ data.req = fuse_get_req(fc);
+ if (IS_ERR(data.req))
+ return PTR_ERR(data.req);
err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
- if (!err)
- fuse_send_readpages(data.req, file, inode);
+ if (!err) {
+ if (data.req->num_pages)
+ fuse_send_readpages(data.req, file, inode);
+ else
+ fuse_put_request(fc, data.req);
+ }
return err;
}
@@ -451,9 +455,9 @@ static int fuse_commit_write(struct file *file, struct page *page,
if (is_bad_inode(inode))
return -EIO;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->num_pages = 1;
req->pages[0] = page;
@@ -528,9 +532,9 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
if (is_bad_inode(inode))
return -EIO;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
while (count) {
size_t nres;
@@ -561,8 +565,12 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
buf += nres;
if (nres != nbytes)
break;
- if (count)
- fuse_reset_request(req);
+ if (count) {
+ fuse_put_request(fc, req);
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ break;
+ }
}
fuse_put_request(fc, req);
if (res > 0) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index a16a04fcf41e..0474202cb5dc 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -18,8 +18,8 @@
/** Max number of pages that can be used in a single read request */
#define FUSE_MAX_PAGES_PER_REQ 32
-/** If more requests are outstanding, then the operation will block */
-#define FUSE_MAX_OUTSTANDING 10
+/** Maximum number of outstanding background requests */
+#define FUSE_MAX_BACKGROUND 10
/** It could be as large as PATH_MAX, but would that have any uses? */
#define FUSE_NAME_MAX 1024
@@ -131,8 +131,8 @@ struct fuse_conn;
* A request to the client
*/
struct fuse_req {
- /** This can be on either unused_list, pending processing or
- io lists in fuse_conn */
+ /** This can be on either pending processing or io lists in
+ fuse_conn */
struct list_head list;
/** Entry on the background list */
@@ -144,15 +144,12 @@ struct fuse_req {
/*
* The following bitfields are either set once before the
* request is queued or setting/clearing them is protected by
- * fuse_lock
+ * fuse_conn->lock
*/
/** True if the request has reply */
unsigned isreply:1;
- /** The request is preallocated */
- unsigned preallocated:1;
-
/** The request was interrupted */
unsigned interrupted:1;
@@ -162,6 +159,9 @@ struct fuse_req {
/** Data is being copied to/from the request */
unsigned locked:1;
+ /** Request is counted as "waiting" */
+ unsigned waiting:1;
+
/** State of the request */
enum fuse_req_state state;
@@ -213,6 +213,9 @@ struct fuse_req {
* unmounted.
*/
struct fuse_conn {
+ /** Lock protecting accessess to members of this structure */
+ spinlock_t lock;
+
/** The user id for this mount */
uid_t user_id;
@@ -244,19 +247,20 @@ struct fuse_conn {
interrupted request) */
struct list_head background;
- /** Controls the maximum number of outstanding requests */
- struct semaphore outstanding_sem;
+ /** Number of requests currently in the background */
+ unsigned num_background;
- /** This counts the number of outstanding requests if
- outstanding_sem would go negative */
- unsigned outstanding_debt;
+ /** Flag indicating if connection is blocked. This will be
+ the case before the INIT reply is received, and if there
+ are too many outstading backgrounds requests */
+ int blocked;
+
+ /** waitq for blocked connection */
+ wait_queue_head_t blocked_waitq;
/** RW semaphore for exclusion with fuse_put_super() */
struct rw_semaphore sbput_sem;
- /** The list of unused requests */
- struct list_head unused_list;
-
/** The next unique request id */
u64 reqctr;
@@ -318,6 +322,9 @@ struct fuse_conn {
/** kobject */
struct kobject kobj;
+
+ /** O_ASYNC requests */
+ struct fasync_struct *fasync;
};
static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -349,21 +356,6 @@ static inline u64 get_node_id(struct inode *inode)
extern const struct file_operations fuse_dev_operations;
/**
- * This is the single global spinlock which protects FUSE's structures
- *
- * The following data is protected by this lock:
- *
- * - the private_data field of the device file
- * - the s_fs_info field of the super block
- * - unused_list, pending, processing lists in fuse_conn
- * - background list in fuse_conn
- * - the unique request ID counter reqctr in fuse_conn
- * - the sb (super_block) field in fuse_conn
- * - the file (device file) field in fuse_conn
- */
-extern spinlock_t fuse_lock;
-
-/**
* Get a filled in inode
*/
struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
@@ -461,11 +453,11 @@ void fuse_reset_request(struct fuse_req *req);
/**
* Reserve a preallocated request
*/
-struct fuse_req *fuse_get_request(struct fuse_conn *fc);
+struct fuse_req *fuse_get_req(struct fuse_conn *fc);
/**
- * Decrement reference count of a request. If count goes to zero put
- * on unused list (preallocated) or free request (not preallocated).
+ * Decrement reference count of a request. If count goes to zero free
+ * the request.
*/
void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
@@ -487,7 +479,7 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
/**
* Release inodes and file associated with background request
*/
-void fuse_release_background(struct fuse_req *req);
+void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req);
/* Abort all requests */
void fuse_abort_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 879e6fba9480..7627022446b2 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -22,7 +22,6 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
MODULE_LICENSE("GPL");
-spinlock_t fuse_lock;
static kmem_cache_t *fuse_inode_cachep;
static struct subsystem connections_subsys;
@@ -207,15 +206,17 @@ static void fuse_put_super(struct super_block *sb)
down_write(&fc->sbput_sem);
while (!list_empty(&fc->background))
- fuse_release_background(list_entry(fc->background.next,
+ fuse_release_background(fc,
+ list_entry(fc->background.next,
struct fuse_req, bg_entry));
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
fc->mounted = 0;
fc->connected = 0;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
up_write(&fc->sbput_sem);
/* Flush all readers on this fs */
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
wake_up_all(&fc->waitq);
kobject_del(&fc->kobj);
kobject_put(&fc->kobj);
@@ -242,9 +243,9 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
struct fuse_statfs_out outarg;
int err;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&outarg, 0, sizeof(outarg));
req->in.numargs = 0;
@@ -369,15 +370,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
static void fuse_conn_release(struct kobject *kobj)
{
- struct fuse_conn *fc = get_fuse_conn_kobj(kobj);
-
- while (!list_empty(&fc->unused_list)) {
- struct fuse_req *req;
- req = list_entry(fc->unused_list.next, struct fuse_req, list);
- list_del(&req->list);
- fuse_request_free(req);
- }
- kfree(fc);
+ kfree(get_fuse_conn_kobj(kobj));
}
static struct fuse_conn *new_conn(void)
@@ -386,64 +379,25 @@ static struct fuse_conn *new_conn(void)
fc = kzalloc(sizeof(*fc), GFP_KERNEL);
if (fc) {
- int i;
+ spin_lock_init(&fc->lock);
init_waitqueue_head(&fc->waitq);
+ init_waitqueue_head(&fc->blocked_waitq);
INIT_LIST_HEAD(&fc->pending);
INIT_LIST_HEAD(&fc->processing);
INIT_LIST_HEAD(&fc->io);
- INIT_LIST_HEAD(&fc->unused_list);
INIT_LIST_HEAD(&fc->background);
- sema_init(&fc->outstanding_sem, 1); /* One for INIT */
init_rwsem(&fc->sbput_sem);
kobj_set_kset_s(fc, connections_subsys);
kobject_init(&fc->kobj);
atomic_set(&fc->num_waiting, 0);
- for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
- struct fuse_req *req = fuse_request_alloc();
- if (!req) {
- kobject_put(&fc->kobj);
- return NULL;
- }
- list_add(&req->list, &fc->unused_list);
- }
fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
fc->bdi.unplug_io_fn = default_unplug_io_fn;
fc->reqctr = 0;
+ fc->blocked = 1;
}
return fc;
}
-static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
-{
- struct fuse_conn *fc;
- int err;
-
- err = -EINVAL;
- if (file->f_op != &fuse_dev_operations)
- goto out_err;
-
- err = -ENOMEM;
- fc = new_conn();
- if (!fc)
- goto out_err;
-
- spin_lock(&fuse_lock);
- err = -EINVAL;
- if (file->private_data)
- goto out_unlock;
-
- kobject_get(&fc->kobj);
- file->private_data = fc;
- spin_unlock(&fuse_lock);
- return fc;
-
- out_unlock:
- spin_unlock(&fuse_lock);
- kobject_put(&fc->kobj);
- out_err:
- return ERR_PTR(err);
-}
-
static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
{
struct fuse_attr attr;
@@ -467,7 +421,6 @@ static struct super_operations fuse_super_operations = {
static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
{
- int i;
struct fuse_init_out *arg = &req->misc.init_out;
if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
@@ -486,22 +439,13 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->minor = arg->minor;
fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
}
-
- /* After INIT reply is received other requests can go
- out. So do (FUSE_MAX_OUTSTANDING - 1) number of
- up()s on outstanding_sem. The last up() is done in
- fuse_putback_request() */
- for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
- up(&fc->outstanding_sem);
-
fuse_put_request(fc, req);
+ fc->blocked = 0;
+ wake_up_all(&fc->blocked_waitq);
}
-static void fuse_send_init(struct fuse_conn *fc)
+static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
{
- /* This is called from fuse_read_super() so there's guaranteed
- to be exactly one request available */
- struct fuse_req *req = fuse_get_request(fc);
struct fuse_init_in *arg = &req->misc.init_in;
arg->major = FUSE_KERNEL_VERSION;
@@ -525,12 +469,9 @@ static void fuse_send_init(struct fuse_conn *fc)
static unsigned long long conn_id(void)
{
+ /* BKL is held for ->get_sb() */
static unsigned long long ctr = 1;
- unsigned long long val;
- spin_lock(&fuse_lock);
- val = ctr++;
- spin_unlock(&fuse_lock);
- return val;
+ return ctr++;
}
static int fuse_fill_super(struct super_block *sb, void *data, int silent)
@@ -540,6 +481,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
struct fuse_mount_data d;
struct file *file;
struct dentry *root_dentry;
+ struct fuse_req *init_req;
int err;
if (!parse_fuse_opt((char *) data, &d))
@@ -555,10 +497,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
if (!file)
return -EINVAL;
- fc = get_conn(file, sb);
- fput(file);
- if (IS_ERR(fc))
- return PTR_ERR(fc);
+ if (file->f_op != &fuse_dev_operations)
+ return -EINVAL;
+
+ fc = new_conn();
+ if (!fc)
+ return -ENOMEM;
fc->flags = d.flags;
fc->user_id = d.user_id;
@@ -579,27 +523,48 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
goto err;
}
+ init_req = fuse_request_alloc();
+ if (!init_req)
+ goto err_put_root;
+
err = kobject_set_name(&fc->kobj, "%llu", conn_id());
if (err)
- goto err_put_root;
+ goto err_free_req;
err = kobject_add(&fc->kobj);
if (err)
- goto err_put_root;
+ goto err_free_req;
+
+ /* Setting file->private_data can't race with other mount()
+ instances, since BKL is held for ->get_sb() */
+ err = -EINVAL;
+ if (file->private_data)
+ goto err_kobject_del;
sb->s_root = root_dentry;
- spin_lock(&fuse_lock);
fc->mounted = 1;
fc->connected = 1;
- spin_unlock(&fuse_lock);
+ kobject_get(&fc->kobj);
+ file->private_data = fc;
+ /*
+ * atomic_dec_and_test() in fput() provides the necessary
+ * memory barrier for file->private_data to be visible on all
+ * CPUs after this
+ */
+ fput(file);
- fuse_send_init(fc);
+ fuse_send_init(fc, init_req);
return 0;
+ err_kobject_del:
+ kobject_del(&fc->kobj);
+ err_free_req:
+ fuse_request_free(init_req);
err_put_root:
dput(root_dentry);
err:
+ fput(file);
kobject_put(&fc->kobj);
return err;
}
@@ -753,7 +718,6 @@ static int __init fuse_init(void)
printk("fuse init (API version %i.%i)\n",
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
- spin_lock_init(&fuse_lock);
res = fuse_fs_init();
if (res)
goto err;
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 8f07e8fbd03d..746abc9ecf70 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -466,8 +466,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
*p && *p != node; p = &(*p)->next_hash)
;
- if (!*p)
- BUG();
+ BUG_ON(!*p);
*p = node->next_hash;
node->tree->node_hash_cnt--;
}
@@ -622,8 +621,7 @@ void hfs_bnode_put(struct hfs_bnode *node)
dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
- if (!atomic_read(&node->refcnt))
- BUG();
+ BUG_ON(!atomic_read(&node->refcnt));
if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
return;
for (i = 0; i < tree->pages_per_bnode; i++) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index a67edfa34e9e..effa8991999c 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -269,8 +269,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
u8 *data, byte, m;
dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this);
- if (!node->this)
- BUG();
+ BUG_ON(!node->this);
tree = node->tree;
nidx = node->this;
node = hfs_bnode_find(tree, 0);
diff --git a/fs/inode.c b/fs/inode.c
index 32b7c3375021..3a2446a27d2c 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -172,8 +172,7 @@ static struct inode *alloc_inode(struct super_block *sb)
void destroy_inode(struct inode *inode)
{
- if (inode_has_buffers(inode))
- BUG();
+ BUG_ON(inode_has_buffers(inode));
security_inode_free(inode);
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
@@ -249,12 +248,9 @@ void clear_inode(struct inode *inode)
might_sleep();
invalidate_inode_buffers(inode);
- if (inode->i_data.nrpages)
- BUG();
- if (!(inode->i_state & I_FREEING))
- BUG();
- if (inode->i_state & I_CLEAR)
- BUG();
+ BUG_ON(inode->i_data.nrpages);
+ BUG_ON(!(inode->i_state & I_FREEING));
+ BUG_ON(inode->i_state & I_CLEAR);
wait_on_inode(inode);
DQUOT_DROP(inode);
if (inode->i_sb && inode->i_sb->s_op->clear_inode)
@@ -1054,8 +1050,7 @@ void generic_delete_inode(struct inode *inode)
hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock);
wake_up_inode(inode);
- if (inode->i_state != I_CLEAR)
- BUG();
+ BUG_ON(inode->i_state != I_CLEAR);
destroy_inode(inode);
}
diff --git a/fs/inotify.c b/fs/inotify.c
index 367c487c014b..1f50302849c5 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -538,7 +538,7 @@ void inotify_d_instantiate(struct dentry *entry, struct inode *inode)
WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
spin_lock(&entry->d_lock);
parent = entry->d_parent;
- if (inotify_inode_watched(parent->d_inode))
+ if (parent->d_inode && inotify_inode_watched(parent->d_inode))
entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
spin_unlock(&entry->d_lock);
}
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 7b77a9541125..ff2a872e80e7 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -35,8 +35,7 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
pid_t pid;
int ret = 0;
- if (c->gc_task)
- BUG();
+ BUG_ON(c->gc_task);
init_completion(&c->gc_thread_start);
init_completion(&c->gc_thread_exit);
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index d2b66bad7d50..3ef739120dff 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -650,7 +650,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
svc_wake_up(block->b_daemon);
}
-void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(void *data)
{
struct nlm_rqst *call = data;
diff --git a/fs/locks.c b/fs/locks.c
index dda83d6cd48b..efad798824dc 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2230,7 +2230,12 @@ void steal_locks(fl_owner_t from)
lock_kernel();
j = 0;
- rcu_read_lock();
+
+ /*
+ * We are not taking a ref to the file structures, so
+ * we need to acquire ->file_lock.
+ */
+ spin_lock(&files->file_lock);
fdt = files_fdtable(files);
for (;;) {
unsigned long set;
@@ -2248,7 +2253,7 @@ void steal_locks(fl_owner_t from)
set >>= 1;
}
}
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
unlock_kernel();
}
EXPORT_SYMBOL(steal_locks);
diff --git a/fs/namespace.c b/fs/namespace.c
index bf478addb852..2c5f1f80bdc2 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -899,11 +899,13 @@ static int do_change_type(struct nameidata *nd, int flag)
/*
* do loopback mount.
*/
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
{
struct nameidata old_nd;
struct vfsmount *mnt = NULL;
+ int recurse = flags & MS_REC;
int err = mount_is_safe(nd);
+
if (err)
return err;
if (!old_name || !*old_name)
@@ -937,6 +939,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
spin_unlock(&vfsmount_lock);
release_mounts(&umount_list);
}
+ mnt->mnt_flags = mnt_flags;
out:
up_write(&namespace_sem);
@@ -1350,7 +1353,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
data_page);
else if (flags & MS_BIND)
- retval = do_loopback(&nd, dev_name, flags & MS_REC);
+ retval = do_loopback(&nd, dev_name, flags, mnt_flags);
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
retval = do_change_type(&nd, flags);
else if (flags & MS_MOVE)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a23f34894167..cae74dd4c7f5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -128,15 +128,14 @@ struct inode_operations nfs4_dir_inode_operations = {
static int
nfs_opendir(struct inode *inode, struct file *filp)
{
- int res = 0;
+ int res;
dfprintk(VFS, "NFS: opendir(%s/%ld)\n",
inode->i_sb->s_id, inode->i_ino);
lock_kernel();
/* Call generic open code in order to cache credentials */
- if (!res)
- res = nfs_open(inode, filp);
+ res = nfs_open(inode, filp);
unlock_kernel();
return res;
}
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0f583cb16ddb..3c72b0c07283 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -112,10 +112,9 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
*/
ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
{
- struct dentry *dentry = iocb->ki_filp->f_dentry;
-
dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
- dentry->d_name.name, (long long) pos, nr_segs);
+ iocb->ki_filp->f_dentry->d_name.name,
+ (long long) pos, nr_segs);
return -EINVAL;
}
@@ -468,7 +467,6 @@ static const struct rpc_call_ops nfs_commit_direct_ops = {
static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
{
struct nfs_write_data *data = dreq->commit_data;
- struct rpc_task *task = &data->task;
data->inode = dreq->inode;
data->cred = dreq->ctx->cred;
@@ -489,7 +487,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
/* Note: task.tk_ops->rpc_release will free dreq->commit_data */
dreq->commit_data = NULL;
- dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
+ dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
lock_kernel();
rpc_execute(&data->task);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f1df2c8d9259..fade02c15e6e 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -534,10 +534,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
*/
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
{
- struct inode * inode = filp->f_mapping->host;
-
dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
- inode->i_sb->s_id, inode->i_ino,
+ filp->f_dentry->d_inode->i_sb->s_id,
+ filp->f_dentry->d_inode->i_ino,
fl->fl_type, fl->fl_flags);
/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2f7656b911b6..d0b991a92327 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -700,12 +700,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
/*
* Display superblock I/O counters
*/
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for_each_possible_cpu(cpu) {
struct nfs_iostats *stats;
- if (!cpu_possible(cpu))
- continue;
-
preempt_disable();
stats = per_cpu_ptr(nfss->io_stats, cpu);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 47ece1dd3c67..d86c0db7b1e8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1218,7 +1218,7 @@ out:
return status;
}
-static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
{
struct file *filp;
@@ -1227,8 +1227,10 @@ static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, st
struct nfs_open_context *ctx;
ctx = (struct nfs_open_context *)filp->private_data;
ctx->state = state;
- } else
- nfs4_close_state(state, nd->intent.open.flags);
+ return 0;
+ }
+ nfs4_close_state(state, nd->intent.open.flags);
+ return PTR_ERR(filp);
}
struct dentry *
@@ -1835,7 +1837,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
nfs_setattr_update_inode(state->inode, sattr);
}
if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
- nfs4_intent_set_file(nd, dentry, state);
+ status = nfs4_intent_set_file(nd, dentry, state);
else
nfs4_close_state(state, flags);
out:
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index cfe9ce881613..6e92b0fe5323 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -14,46 +14,46 @@
int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{
- struct svc_cred *cred = &rqstp->rq_cred;
+ struct svc_cred cred = rqstp->rq_cred;
int i;
int ret;
if (exp->ex_flags & NFSEXP_ALLSQUASH) {
- cred->cr_uid = exp->ex_anon_uid;
- cred->cr_gid = exp->ex_anon_gid;
- put_group_info(cred->cr_group_info);
- cred->cr_group_info = groups_alloc(0);
+ cred.cr_uid = exp->ex_anon_uid;
+ cred.cr_gid = exp->ex_anon_gid;
+ cred.cr_group_info = groups_alloc(0);
} else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
struct group_info *gi;
- if (!cred->cr_uid)
- cred->cr_uid = exp->ex_anon_uid;
- if (!cred->cr_gid)
- cred->cr_gid = exp->ex_anon_gid;
- gi = groups_alloc(cred->cr_group_info->ngroups);
+ if (!cred.cr_uid)
+ cred.cr_uid = exp->ex_anon_uid;
+ if (!cred.cr_gid)
+ cred.cr_gid = exp->ex_anon_gid;
+ gi = groups_alloc(cred.cr_group_info->ngroups);
if (gi)
- for (i = 0; i < cred->cr_group_info->ngroups; i++) {
- if (!GROUP_AT(cred->cr_group_info, i))
+ for (i = 0; i < cred.cr_group_info->ngroups; i++) {
+ if (!GROUP_AT(cred.cr_group_info, i))
GROUP_AT(gi, i) = exp->ex_anon_gid;
else
- GROUP_AT(gi, i) = GROUP_AT(cred->cr_group_info, i);
+ GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i);
}
- put_group_info(cred->cr_group_info);
- cred->cr_group_info = gi;
- }
+ cred.cr_group_info = gi;
+ } else
+ get_group_info(cred.cr_group_info);
- if (cred->cr_uid != (uid_t) -1)
- current->fsuid = cred->cr_uid;
+ if (cred.cr_uid != (uid_t) -1)
+ current->fsuid = cred.cr_uid;
else
current->fsuid = exp->ex_anon_uid;
- if (cred->cr_gid != (gid_t) -1)
- current->fsgid = cred->cr_gid;
+ if (cred.cr_gid != (gid_t) -1)
+ current->fsgid = cred.cr_gid;
else
current->fsgid = exp->ex_anon_gid;
- if (!cred->cr_group_info)
+ if (!cred.cr_group_info)
return -ENOMEM;
- ret = set_current_groups(cred->cr_group_info);
- if ((cred->cr_uid)) {
+ ret = set_current_groups(cred.cr_group_info);
+ put_group_info(cred.cr_group_info);
+ if ((cred.cr_uid)) {
cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
} else {
cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c340be0a3f59..4e0578121d9a 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -422,7 +422,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
goto out;
err = path_lookup(buf, 0, &nd);
- if (err) goto out;
+ if (err) goto out_no_path;
exp.h.flags = 0;
exp.ex_client = dom;
@@ -475,6 +475,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
out:
if (nd.dentry)
path_release(&nd);
+ out_no_path:
if (dom)
auth_domain_put(dom);
kfree(buf);
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 6d2dfed1de08..f61142afea44 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -682,7 +682,7 @@ static struct svc_procedure nfsd_procedures3[22] = {
PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1),
PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
- PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
+ PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE/4),
PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4),
PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 7391f4aabedb..edb107e61b91 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -710,9 +710,9 @@ calculate_posix_ace_count(struct nfs4_acl *n4acl)
/* Also, the remaining entries are for named users and
* groups, and come in threes (mask, allow, deny): */
if (n4acl->naces < 7)
- return -1;
+ return -EINVAL;
if ((n4acl->naces - 7) % 3)
- return -1;
+ return -EINVAL;
return 4 + (n4acl->naces - 7)/3;
}
}
@@ -790,7 +790,7 @@ nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
continue;
error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
- ace->access_mask, ace->whotype, ace->who) == -1;
+ ace->access_mask, ace->whotype, ace->who);
if (error < 0)
goto out;
@@ -866,7 +866,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
struct nfs4_ace *ace;
if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
- return -1;
+ return -ENOMEM;
ace->type = type;
ace->flag = flag;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c872bd07fc10..dbaf3f93f328 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -441,8 +441,9 @@ nfsd4_probe_callback(struct nfs4_client *clp)
goto out_clnt;
}
- /* the task holds a reference to the nfs4_client struct */
cb->cb_client = clnt;
+
+ /* the task holds a reference to the nfs4_client struct */
atomic_inc(&clp->cl_count);
msg.rpc_cred = nfsd4_lookupcred(clp,0);
@@ -460,13 +461,12 @@ nfsd4_probe_callback(struct nfs4_client *clp)
out_rpciod:
atomic_dec(&clp->cl_count);
rpciod_down();
+ cb->cb_client = NULL;
out_clnt:
rpc_shutdown_client(clnt);
- goto out_err;
out_err:
dprintk("NFSD: warning: no callback path to client %.*s\n",
(int)clp->cl_name.len, clp->cl_name.data);
- cb->cb_client = NULL;
}
static void
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6d63f1d9e5f5..b0e095ea0c03 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -288,8 +288,6 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
fh_put(current_fh);
status = exp_pseudoroot(rqstp->rq_client, current_fh,
&rqstp->rq_chandle);
- if (!status)
- status = nfserrno(nfsd_setuser(rqstp, current_fh->fh_export));
return status;
}
@@ -975,7 +973,7 @@ struct nfsd4_voidargs { int dummy; };
*/
static struct svc_procedure nfsd_procedures4[2] = {
PROC(null, void, void, void, RC_NOCACHE, 1),
- PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE)
+ PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE/4)
};
struct svc_version nfsd_version4 = {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 47ec112b266c..96c7578cbe1e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -147,6 +147,42 @@ get_nfs4_file(struct nfs4_file *fi)
kref_get(&fi->fi_ref);
}
+static int num_delegations;
+
+/*
+ * Open owner state (share locks)
+ */
+
+/* hash tables for nfs4_stateowner */
+#define OWNER_HASH_BITS 8
+#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
+#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
+
+#define ownerid_hashval(id) \
+ ((id) & OWNER_HASH_MASK)
+#define ownerstr_hashval(clientid, ownername) \
+ (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
+
+static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
+static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
+
+/* hash table for nfs4_file */
+#define FILE_HASH_BITS 8
+#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
+#define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
+/* hash table for (open)nfs4_stateid */
+#define STATEID_HASH_BITS 10
+#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
+#define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1)
+
+#define file_hashval(x) \
+ hash_ptr(x, FILE_HASH_BITS)
+#define stateid_hashval(owner_id, file_id) \
+ (((owner_id) + (file_id)) & STATEID_HASH_MASK)
+
+static struct list_head file_hashtbl[FILE_HASH_SIZE];
+static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
+
static struct nfs4_delegation *
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
{
@@ -155,9 +191,12 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
dprintk("NFSD alloc_init_deleg\n");
+ if (num_delegations > STATEID_HASH_SIZE * 4)
+ return NULL;
dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
if (dp == NULL)
return dp;
+ num_delegations++;
INIT_LIST_HEAD(&dp->dl_perfile);
INIT_LIST_HEAD(&dp->dl_perclnt);
INIT_LIST_HEAD(&dp->dl_recall_lru);
@@ -192,6 +231,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
dprintk("NFSD: freeing dp %p\n",dp);
put_nfs4_file(dp->dl_file);
kmem_cache_free(deleg_slab, dp);
+ num_delegations--;
}
}
@@ -330,22 +370,29 @@ put_nfs4_client(struct nfs4_client *clp)
}
static void
+shutdown_callback_client(struct nfs4_client *clp)
+{
+ struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+
+ /* shutdown rpc client, ending any outstanding recall rpcs */
+ if (clnt) {
+ clp->cl_callback.cb_client = NULL;
+ rpc_shutdown_client(clnt);
+ rpciod_down();
+ }
+}
+
+static void
expire_client(struct nfs4_client *clp)
{
struct nfs4_stateowner *sop;
struct nfs4_delegation *dp;
- struct nfs4_callback *cb = &clp->cl_callback;
- struct rpc_clnt *clnt = clp->cl_callback.cb_client;
struct list_head reaplist;
dprintk("NFSD: expire_client cl_count %d\n",
atomic_read(&clp->cl_count));
- /* shutdown rpc client, ending any outstanding recall rpcs */
- if (atomic_read(&cb->cb_set) == 1 && clnt) {
- rpc_shutdown_client(clnt);
- clnt = clp->cl_callback.cb_client = NULL;
- }
+ shutdown_callback_client(clp);
INIT_LIST_HEAD(&reaplist);
spin_lock(&recall_lock);
@@ -936,40 +983,6 @@ out:
return status;
}
-/*
- * Open owner state (share locks)
- */
-
-/* hash tables for nfs4_stateowner */
-#define OWNER_HASH_BITS 8
-#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
-#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
-
-#define ownerid_hashval(id) \
- ((id) & OWNER_HASH_MASK)
-#define ownerstr_hashval(clientid, ownername) \
- (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
-
-static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
-static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
-
-/* hash table for nfs4_file */
-#define FILE_HASH_BITS 8
-#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
-#define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
-/* hash table for (open)nfs4_stateid */
-#define STATEID_HASH_BITS 10
-#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
-#define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1)
-
-#define file_hashval(x) \
- hash_ptr(x, FILE_HASH_BITS)
-#define stateid_hashval(owner_id, file_id) \
- (((owner_id) + (file_id)) & STATEID_HASH_MASK)
-
-static struct list_head file_hashtbl[FILE_HASH_SIZE];
-static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
-
/* OPEN Share state helper functions */
static inline struct nfs4_file *
alloc_init_file(struct inode *ino)
@@ -1186,8 +1199,7 @@ move_to_close_lru(struct nfs4_stateowner *sop)
{
dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
- unhash_stateowner(sop);
- list_add_tail(&sop->so_close_lru, &close_lru);
+ list_move_tail(&sop->so_close_lru, &close_lru);
sop->so_time = get_seconds();
}
@@ -1916,8 +1928,7 @@ nfs4_laundromat(void)
}
dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
sop->so_id);
- list_del(&sop->so_close_lru);
- nfs4_put_stateowner(sop);
+ release_stateowner(sop);
}
if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
@@ -2495,36 +2506,27 @@ nfs4_transform_lock_offset(struct file_lock *lock)
lock->fl_end = OFFSET_MAX;
}
-static int
-nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
-{
- struct nfs4_stateowner *local = NULL;
- int status = 0;
-
- if (hashval >= LOCK_HASH_SIZE)
- goto out;
- list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) {
- if (local == sop) {
- status = 1;
- goto out;
- }
- }
-out:
- return status;
-}
-
+/* Hack!: For now, we're defining this just so we can use a pointer to it
+ * as a unique cookie to identify our (NFSv4's) posix locks. */
+static struct lock_manager_operations nfsd_posix_mng_ops = {
+};
static inline void
nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
{
- struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
- unsigned int hval = lockownerid_hashval(sop->so_id);
+ struct nfs4_stateowner *sop;
+ unsigned int hval;
- deny->ld_sop = NULL;
- if (nfs4_verify_lock_stateowner(sop, hval)) {
+ if (fl->fl_lmops == &nfsd_posix_mng_ops) {
+ sop = (struct nfs4_stateowner *) fl->fl_owner;
+ hval = lockownerid_hashval(sop->so_id);
kref_get(&sop->so_ref);
deny->ld_sop = sop;
deny->ld_clientid = sop->so_client->cl_clientid;
+ } else {
+ deny->ld_sop = NULL;
+ deny->ld_clientid.cl_boot = 0;
+ deny->ld_clientid.cl_id = 0;
}
deny->ld_start = fl->fl_start;
deny->ld_length = ~(u64)0;
@@ -2736,6 +2738,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
+ file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = lock->lk_offset;
if ((lock->lk_length == ~(u64)0) ||
@@ -2841,6 +2844,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
file_lock.fl_pid = current->tgid;
file_lock.fl_flags = FL_POSIX;
+ file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = lockt->lt_offset;
if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length))
@@ -2900,6 +2904,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
+ file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = locku->lu_offset;
if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
@@ -3211,15 +3216,8 @@ __nfs4_state_shutdown(void)
int i;
struct nfs4_client *clp = NULL;
struct nfs4_delegation *dp = NULL;
- struct nfs4_stateowner *sop = NULL;
struct list_head *pos, *next, reaplist;
- list_for_each_safe(pos, next, &close_lru) {
- sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
- list_del(&sop->so_close_lru);
- nfs4_put_stateowner(sop);
- }
-
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
while (!list_empty(&conf_id_hashtbl[i])) {
clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
@@ -3244,8 +3242,6 @@ __nfs4_state_shutdown(void)
}
cancel_delayed_work(&laundromat_work);
- flush_workqueue(laundry_wq);
- destroy_workqueue(laundry_wq);
nfsd4_shutdown_recdir();
nfs4_init = 0;
}
@@ -3253,6 +3249,8 @@ __nfs4_state_shutdown(void)
void
nfs4_state_shutdown(void)
{
+ cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
+ destroy_workqueue(laundry_wq);
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 03857fd81126..de3998f15f10 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -299,11 +299,10 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
buf, dummy32, &ace.who);
if (status)
goto out_nfserr;
- if (nfs4_acl_add_ace(*acl, ace.type, ace.flag,
- ace.access_mask, ace.whotype, ace.who) != 0) {
- status = -ENOMEM;
+ status = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+ ace.access_mask, ace.whotype, ace.who);
+ if (status)
goto out_nfserr;
- }
}
} else
*acl = NULL;
@@ -2085,27 +2084,20 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
WRITE32(eof);
WRITE32(maxcount);
ADJUST_ARGS();
- resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
-
+ resp->xbuf->head[0].iov_len = (char*)p
+ - (char*)resp->xbuf->head[0].iov_base;
resp->xbuf->page_len = maxcount;
- /* read zero bytes -> don't set up tail */
- if(!maxcount)
- return 0;
-
- /* set up page for remaining responses */
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+ /* Use rest of head for padding and remaining ops: */
+ resp->rqstp->rq_restailpage = 0;
+ resp->xbuf->tail[0].iov_base = p;
resp->xbuf->tail[0].iov_len = 0;
- resp->p = resp->xbuf->tail[0].iov_base;
- resp->end = resp->p + PAGE_SIZE/4;
-
if (maxcount&3) {
- *(resp->p)++ = 0;
+ RESERVE_SPACE(4);
+ WRITE32(0);
resp->xbuf->tail[0].iov_base += maxcount&3;
resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
+ ADJUST_ARGS();
}
return 0;
}
@@ -2142,21 +2134,20 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
WRITE32(maxcount);
ADJUST_ARGS();
- resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
+ resp->xbuf->head[0].iov_len = (char*)p
+ - (char*)resp->xbuf->head[0].iov_base;
+ resp->xbuf->page_len = maxcount;
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+ /* Use rest of head for padding and remaining ops: */
+ resp->rqstp->rq_restailpage = 0;
+ resp->xbuf->tail[0].iov_base = p;
resp->xbuf->tail[0].iov_len = 0;
- resp->p = resp->xbuf->tail[0].iov_base;
- resp->end = resp->p + PAGE_SIZE/4;
-
- resp->xbuf->page_len = maxcount;
if (maxcount&3) {
- *(resp->p)++ = 0;
+ RESERVE_SPACE(4);
+ WRITE32(0);
resp->xbuf->tail[0].iov_base += maxcount&3;
resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
+ ADJUST_ARGS();
}
return 0;
}
@@ -2166,7 +2157,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
{
int maxcount;
loff_t offset;
- u32 *page, *savep;
+ u32 *page, *savep, *tailbase;
ENCODE_HEAD;
if (nfserr)
@@ -2182,6 +2173,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
WRITE32(0);
ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
+ tailbase = p;
maxcount = PAGE_SIZE;
if (maxcount > readdir->rd_maxcount)
@@ -2226,14 +2218,12 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
*p++ = htonl(readdir->common.err == nfserr_eof);
resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- /* allocate a page for the tail */
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+ /* Use rest of head for padding and remaining ops: */
+ resp->rqstp->rq_restailpage = 0;
+ resp->xbuf->tail[0].iov_base = tailbase;
resp->xbuf->tail[0].iov_len = 0;
resp->p = resp->xbuf->tail[0].iov_base;
- resp->end = resp->p + PAGE_SIZE/4;
+ resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
return 0;
err_no_verf:
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 3e6b75cd90fd..06cd0db0f32b 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -553,7 +553,7 @@ static struct svc_procedure nfsd_procedures2[18] = {
PROC(none, void, void, none, RC_NOCACHE, ST),
PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT),
PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
- PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
+ PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE/4),
PROC(none, void, void, none, RC_NOCACHE, ST),
PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 31018333dc38..6aa92d0e6876 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -371,7 +371,6 @@ out_nfserr:
static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
{
ssize_t buflen;
- int error;
buflen = vfs_getxattr(dentry, key, NULL, 0);
if (buflen <= 0)
@@ -381,10 +380,7 @@ static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
if (!*buf)
return -ENOMEM;
- error = vfs_getxattr(dentry, key, *buf, buflen);
- if (error < 0)
- return error;
- return buflen;
+ return vfs_getxattr(dentry, key, *buf, buflen);
}
#endif
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index bff0f0d06867..21f38accd039 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -153,6 +153,7 @@ struct o2hb_region {
struct o2hb_bio_wait_ctxt {
atomic_t wc_num_reqs;
struct completion wc_io_complete;
+ int wc_error;
};
static void o2hb_write_timeout(void *arg)
@@ -186,6 +187,7 @@ static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc,
{
atomic_set(&wc->wc_num_reqs, num_ios);
init_completion(&wc->wc_io_complete);
+ wc->wc_error = 0;
}
/* Used in error paths too */
@@ -218,8 +220,10 @@ static int o2hb_bio_end_io(struct bio *bio,
{
struct o2hb_bio_wait_ctxt *wc = bio->bi_private;
- if (error)
+ if (error) {
mlog(ML_ERROR, "IO Error %d\n", error);
+ wc->wc_error = error;
+ }
if (bio->bi_size)
return 1;
@@ -390,6 +394,8 @@ static int o2hb_read_slots(struct o2hb_region *reg,
bail_and_wait:
o2hb_wait_on_io(reg, &wc);
+ if (wc.wc_error && !status)
+ status = wc.wc_error;
if (bios) {
for(i = 0; i < num_bios; i++)
@@ -790,20 +796,24 @@ static int o2hb_highest_node(unsigned long *nodes,
return highest;
}
-static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
+static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
{
int i, ret, highest_node, change = 0;
unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
struct bio *write_bio;
struct o2hb_bio_wait_ctxt write_wc;
- if (o2nm_configured_node_map(configured_nodes, sizeof(configured_nodes)))
- return;
+ ret = o2nm_configured_node_map(configured_nodes,
+ sizeof(configured_nodes));
+ if (ret) {
+ mlog_errno(ret);
+ return ret;
+ }
highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
if (highest_node >= O2NM_MAX_NODES) {
mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
- return;
+ return -EINVAL;
}
/* No sense in reading the slots of nodes that don't exist
@@ -813,7 +823,7 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
ret = o2hb_read_slots(reg, highest_node + 1);
if (ret < 0) {
mlog_errno(ret);
- return;
+ return ret;
}
/* With an up to date view of the slots, we can check that no
@@ -831,7 +841,7 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
ret = o2hb_issue_node_write(reg, &write_bio, &write_wc);
if (ret < 0) {
mlog_errno(ret);
- return;
+ return ret;
}
i = -1;
@@ -847,6 +857,15 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
*/
o2hb_wait_on_io(reg, &write_wc);
bio_put(write_bio);
+ if (write_wc.wc_error) {
+ /* Do not re-arm the write timeout on I/O error - we
+ * can't be sure that the new block ever made it to
+ * disk */
+ mlog(ML_ERROR, "Write error %d on device \"%s\"\n",
+ write_wc.wc_error, reg->hr_dev_name);
+ return write_wc.wc_error;
+ }
+
o2hb_arm_write_timeout(reg);
/* let the person who launched us know when things are steady */
@@ -854,6 +873,8 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
if (atomic_dec_and_test(&reg->hr_steady_iterations))
wake_up(&o2hb_steady_queue);
}
+
+ return 0;
}
/* Subtract b from a, storing the result in a. a *must* have a larger
@@ -913,7 +934,10 @@ static int o2hb_thread(void *data)
* likely to time itself out. */
do_gettimeofday(&before_hb);
- o2hb_do_disk_heartbeat(reg);
+ i = 0;
+ do {
+ ret = o2hb_do_disk_heartbeat(reg);
+ } while (ret && ++i < 2);
do_gettimeofday(&after_hb);
elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
index c3764f4744ee..74ca4e5f9765 100644
--- a/fs/ocfs2/dlm/userdlm.c
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -139,6 +139,10 @@ static void user_ast(void *opaque)
return;
}
+ mlog_bug_on_msg(lockres->l_requested == LKM_IVMODE,
+ "Lockres %s, requested ivmode. flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
+
/* we're downconverting. */
if (lockres->l_requested < lockres->l_level) {
if (lockres->l_requested <=
@@ -229,23 +233,42 @@ static void user_unlock_ast(void *opaque, enum dlm_status status)
mlog(0, "UNLOCK AST called on lock %s\n", lockres->l_name);
- if (status != DLM_NORMAL)
+ if (status != DLM_NORMAL && status != DLM_CANCELGRANT)
mlog(ML_ERROR, "Dlm returns status %d\n", status);
spin_lock(&lockres->l_lock);
- if (lockres->l_flags & USER_LOCK_IN_TEARDOWN)
+ /* The teardown flag gets set early during the unlock process,
+ * so test the cancel flag to make sure that this ast isn't
+ * for a concurrent cancel. */
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN
+ && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) {
lockres->l_level = LKM_IVMODE;
- else {
+ } else if (status == DLM_CANCELGRANT) {
+ mlog(0, "Lock %s, cancel fails, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
+ /* We tried to cancel a convert request, but it was
+ * already granted. Don't clear the busy flag - the
+ * ast should've done this already. */
+ BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+ lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+ goto out_noclear;
+ } else {
+ BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+ /* Cancel succeeded, we want to re-queue */
+ mlog(0, "Lock %s, cancel succeeds, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
lockres->l_requested = LKM_IVMODE; /* cancel an
* upconvert
* request. */
lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
/* we want the unblock thread to look at it again
* now. */
- __user_dlm_queue_lockres(lockres);
+ if (lockres->l_flags & USER_LOCK_BLOCKED)
+ __user_dlm_queue_lockres(lockres);
}
lockres->l_flags &= ~USER_LOCK_BUSY;
+out_noclear:
spin_unlock(&lockres->l_lock);
wake_up(&lockres->l_event);
@@ -268,13 +291,26 @@ static void user_dlm_unblock_lock(void *opaque)
spin_lock(&lockres->l_lock);
- BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
- BUG_ON(!(lockres->l_flags & USER_LOCK_QUEUED));
+ mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED),
+ "Lockres %s, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
- /* notice that we don't clear USER_LOCK_BLOCKED here. That's
- * for user_ast to do. */
+ /* notice that we don't clear USER_LOCK_BLOCKED here. If it's
+ * set, we want user_ast clear it. */
lockres->l_flags &= ~USER_LOCK_QUEUED;
+ /* It's valid to get here and no longer be blocked - if we get
+ * several basts in a row, we might be queued by the first
+ * one, the unblock thread might run and clear the queued
+ * flag, and finally we might get another bast which re-queues
+ * us before our ast for the downconvert is called. */
+ if (!(lockres->l_flags & USER_LOCK_BLOCKED)) {
+ mlog(0, "Lockres %s, flags 0x%x: queued but not blocking\n",
+ lockres->l_name, lockres->l_flags);
+ spin_unlock(&lockres->l_lock);
+ goto drop_ref;
+ }
+
if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
mlog(0, "lock is in teardown so we do nothing\n");
spin_unlock(&lockres->l_lock);
@@ -282,7 +318,9 @@ static void user_dlm_unblock_lock(void *opaque)
}
if (lockres->l_flags & USER_LOCK_BUSY) {
- mlog(0, "BUSY flag detected...\n");
+ mlog(0, "Cancel lock %s, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
+
if (lockres->l_flags & USER_LOCK_IN_CANCEL) {
spin_unlock(&lockres->l_lock);
goto drop_ref;
@@ -296,14 +334,7 @@ static void user_dlm_unblock_lock(void *opaque)
LKM_CANCEL,
user_unlock_ast,
lockres);
- if (status == DLM_CANCELGRANT) {
- /* If we got this, then the ast was fired
- * before we could cancel. We cleanup our
- * state, and restart the function. */
- spin_lock(&lockres->l_lock);
- lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
- spin_unlock(&lockres->l_lock);
- } else if (status != DLM_NORMAL)
+ if (status != DLM_NORMAL)
user_log_dlm_error("dlmunlock", status, lockres);
goto drop_ref;
}
@@ -581,6 +612,14 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres)
mlog(0, "asked to destroy %s\n", lockres->l_name);
spin_lock(&lockres->l_lock);
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+ mlog(0, "Lock is already torn down\n");
+ spin_unlock(&lockres->l_lock);
+ return 0;
+ }
+
+ lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
+
while (lockres->l_flags & USER_LOCK_BUSY) {
spin_unlock(&lockres->l_lock);
@@ -606,7 +645,6 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres)
lockres->l_flags &= ~USER_LOCK_ATTACHED;
lockres->l_flags |= USER_LOCK_BUSY;
- lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
spin_unlock(&lockres->l_lock);
mlog(0, "unlocking lockres %s\n", lockres->l_name);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 34e903a6a46b..581eb451a41a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -260,6 +260,17 @@ static int ocfs2_truncate_file(struct inode *inode,
if (new_i_size == le64_to_cpu(fe->i_size))
goto bail;
+ /* This forces other nodes to sync and drop their pages. Do
+ * this even if we have a truncate without allocation change -
+ * ocfs2 cluster sizes can be much greater than page size, so
+ * we have to truncate them anyway. */
+ status = ocfs2_data_lock(inode, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_data_unlock(inode, 1);
+
if (le32_to_cpu(fe->i_clusters) ==
ocfs2_clusters_for_bytes(osb->sb, new_i_size)) {
mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n",
@@ -272,14 +283,6 @@ static int ocfs2_truncate_file(struct inode *inode,
goto bail;
}
- /* This forces other nodes to sync and drop their pages */
- status = ocfs2_data_lock(inode, 1);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
- }
- ocfs2_data_unlock(inode, 1);
-
/* alright, we're going to need to do a full blown alloc size
* change. Orphan the inode so that recovery can complete the
* truncate if necessary. This does the task of marking
diff --git a/fs/open.c b/fs/open.c
index c32c89d6d8db..53ec28c36777 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -331,7 +331,10 @@ out:
asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
{
- return do_sys_ftruncate(fd, length, 1);
+ long ret = do_sys_ftruncate(fd, length, 1);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
/* LFS versions of truncate are only needed on 32 bit machines */
@@ -343,7 +346,10 @@ asmlinkage long sys_truncate64(const char __user * path, loff_t length)
asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
{
- return do_sys_ftruncate(fd, length, 0);
+ long ret = do_sys_ftruncate(fd, length, 0);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
#endif
@@ -1093,20 +1099,30 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
asmlinkage long sys_open(const char __user *filename, int flags, int mode)
{
+ long ret;
+
if (force_o_largefile())
flags |= O_LARGEFILE;
- return do_sys_open(AT_FDCWD, filename, flags, mode);
+ ret = do_sys_open(AT_FDCWD, filename, flags, mode);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
EXPORT_SYMBOL_GPL(sys_open);
asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
int mode)
{
+ long ret;
+
if (force_o_largefile())
flags |= O_LARGEFILE;
- return do_sys_open(dfd, filename, flags, mode);
+ ret = do_sys_open(dfd, filename, flags, mode);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
EXPORT_SYMBOL_GPL(sys_openat);
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index af0cb4b9e784..45ae7dd3c650 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -331,7 +331,9 @@ void delete_partition(struct gendisk *disk, int part)
devfs_remove("%s/part%d", disk->devfs_name, part);
if (p->holder_dir)
kobject_unregister(p->holder_dir);
- kobject_unregister(&p->kobj);
+ kobject_uevent(&p->kobj, KOBJ_REMOVE);
+ kobject_del(&p->kobj);
+ kobject_put(&p->kobj);
}
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
@@ -357,7 +359,10 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
p->kobj.parent = &disk->kobj;
p->kobj.ktype = &ktype_part;
- kobject_register(&p->kobj);
+ kobject_init(&p->kobj);
+ kobject_add(&p->kobj);
+ if (!disk->part_uevent_suppress)
+ kobject_uevent(&p->kobj, KOBJ_ADD);
partition_sysfs_add_subdir(p);
disk->part[part-1] = p;
}
@@ -367,6 +372,7 @@ static char *make_block_name(struct gendisk *disk)
char *name;
static char *block_str = "block:";
int size;
+ char *s;
size = strlen(block_str) + strlen(disk->disk_name) + 1;
name = kmalloc(size, GFP_KERNEL);
@@ -374,6 +380,10 @@ static char *make_block_name(struct gendisk *disk)
return NULL;
strcpy(name, block_str);
strcat(name, disk->disk_name);
+ /* ewww... some of these buggers have / in name... */
+ s = strchr(name, '/');
+ if (s)
+ *s = '!';
return name;
}
@@ -395,6 +405,8 @@ void register_disk(struct gendisk *disk)
{
struct block_device *bdev;
char *s;
+ int i;
+ struct hd_struct *p;
int err;
strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
@@ -406,13 +418,12 @@ void register_disk(struct gendisk *disk)
return;
disk_sysfs_symlinks(disk);
disk_sysfs_add_subdirs(disk);
- kobject_uevent(&disk->kobj, KOBJ_ADD);
/* No minors to use for partitions */
if (disk->minors == 1) {
if (disk->devfs_name[0] != '\0')
devfs_add_disk(disk);
- return;
+ goto exit;
}
/* always add handle for the whole disk */
@@ -420,16 +431,32 @@ void register_disk(struct gendisk *disk)
/* No such device (e.g., media were just removed) */
if (!get_capacity(disk))
- return;
+ goto exit;
bdev = bdget_disk(disk, 0);
if (!bdev)
- return;
+ goto exit;
+ /* scan partition table, but suppress uevents */
bdev->bd_invalidated = 1;
- if (blkdev_get(bdev, FMODE_READ, 0) < 0)
- return;
+ disk->part_uevent_suppress = 1;
+ err = blkdev_get(bdev, FMODE_READ, 0);
+ disk->part_uevent_suppress = 0;
+ if (err < 0)
+ goto exit;
blkdev_put(bdev);
+
+exit:
+ /* announce disk after possible partitions are already created */
+ kobject_uevent(&disk->kobj, KOBJ_ADD);
+
+ /* announce possible partitions */
+ for (i = 1; i < disk->minors; i++) {
+ p = disk->part[i-1];
+ if (!p || !p->nr_sects)
+ continue;
+ kobject_uevent(&p->kobj, KOBJ_ADD);
+ }
}
int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
diff --git a/fs/pipe.c b/fs/pipe.c
index 109a102c150d..7fefb10db8d9 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -36,7 +36,7 @@
*/
/* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct inode * inode)
+void pipe_wait(struct pipe_inode_info *pipe)
{
DEFINE_WAIT(wait);
@@ -44,11 +44,14 @@ void pipe_wait(struct inode * inode)
* Pipes are system-local resources, so sleeping on them
* is considered a noninteractive wait:
*/
- prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE);
- mutex_unlock(PIPE_MUTEX(*inode));
+ prepare_to_wait(&pipe->wait, &wait,
+ TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE);
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
schedule();
- finish_wait(PIPE_WAIT(*inode), &wait);
- mutex_lock(PIPE_MUTEX(*inode));
+ finish_wait(&pipe->wait, &wait);
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
}
static int
@@ -91,49 +94,56 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
return 0;
}
-static void anon_pipe_buf_release(struct pipe_inode_info *info, struct pipe_buffer *buf)
+static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
struct page *page = buf->page;
+ buf->flags &= ~PIPE_BUF_FLAG_STOLEN;
+
/*
* If nobody else uses this page, and we don't already have a
* temporary page, let's keep track of it as a one-deep
- * allocation cache
- */
- if (page_count(page) == 1 && !info->tmp_page) {
- info->tmp_page = page;
- return;
- }
-
- /*
- * Otherwise just release our reference to it
+ * allocation cache. (Otherwise just release our reference to it)
*/
- page_cache_release(page);
+ if (page_count(page) == 1 && !pipe->tmp_page)
+ pipe->tmp_page = page;
+ else
+ page_cache_release(page);
}
-static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf)
+static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
return kmap(buf->page);
}
-static void anon_pipe_buf_unmap(struct pipe_inode_info *info, struct pipe_buffer *buf)
+static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
kunmap(buf->page);
}
-static int anon_pipe_buf_steal(struct pipe_inode_info *info,
+static int anon_pipe_buf_steal(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
- buf->stolen = 1;
+ buf->flags |= PIPE_BUF_FLAG_STOLEN;
return 0;
}
+static void anon_pipe_buf_get(struct pipe_inode_info *info,
+ struct pipe_buffer *buf)
+{
+ page_cache_get(buf->page);
+}
+
static struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
.map = anon_pipe_buf_map,
.unmap = anon_pipe_buf_unmap,
.release = anon_pipe_buf_release,
.steal = anon_pipe_buf_steal,
+ .get = anon_pipe_buf_get,
};
static ssize_t
@@ -141,7 +151,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
unsigned long nr_segs, loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info;
+ struct pipe_inode_info *pipe;
int do_wakeup;
ssize_t ret;
struct iovec *iov = (struct iovec *)_iov;
@@ -154,13 +164,13 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
do_wakeup = 0;
ret = 0;
- mutex_lock(PIPE_MUTEX(*inode));
- info = inode->i_pipe;
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
for (;;) {
- int bufs = info->nrbufs;
+ int bufs = pipe->nrbufs;
if (bufs) {
- int curbuf = info->curbuf;
- struct pipe_buffer *buf = info->bufs + curbuf;
+ int curbuf = pipe->curbuf;
+ struct pipe_buffer *buf = pipe->bufs + curbuf;
struct pipe_buf_operations *ops = buf->ops;
void *addr;
size_t chars = buf->len;
@@ -169,16 +179,17 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
if (chars > total_len)
chars = total_len;
- addr = ops->map(filp, info, buf);
+ addr = ops->map(filp, pipe, buf);
if (IS_ERR(addr)) {
if (!ret)
ret = PTR_ERR(addr);
break;
}
error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
- ops->unmap(info, buf);
+ ops->unmap(pipe, buf);
if (unlikely(error)) {
- if (!ret) ret = -EFAULT;
+ if (!ret)
+ ret = -EFAULT;
break;
}
ret += chars;
@@ -186,10 +197,10 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
buf->len -= chars;
if (!buf->len) {
buf->ops = NULL;
- ops->release(info, buf);
+ ops->release(pipe, buf);
curbuf = (curbuf + 1) & (PIPE_BUFFERS-1);
- info->curbuf = curbuf;
- info->nrbufs = --bufs;
+ pipe->curbuf = curbuf;
+ pipe->nrbufs = --bufs;
do_wakeup = 1;
}
total_len -= chars;
@@ -198,9 +209,9 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
}
if (bufs) /* More to do? */
continue;
- if (!PIPE_WRITERS(*inode))
+ if (!pipe->writers)
break;
- if (!PIPE_WAITING_WRITERS(*inode)) {
+ if (!pipe->waiting_writers) {
/* syscall merging: Usually we must not sleep
* if O_NONBLOCK is set, or if we got some data.
* But if a writer sleeps in kernel space, then
@@ -214,20 +225,22 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
}
}
if (signal_pending(current)) {
- if (!ret) ret = -ERESTARTSYS;
+ if (!ret)
+ ret = -ERESTARTSYS;
break;
}
if (do_wakeup) {
- wake_up_interruptible_sync(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
- pipe_wait(inode);
+ pipe_wait(pipe);
}
- mutex_unlock(PIPE_MUTEX(*inode));
- /* Signal writers asynchronously that there is more room. */
+ mutex_unlock(&inode->i_mutex);
+
+ /* Signal writers asynchronously that there is more room. */
if (do_wakeup) {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
if (ret > 0)
file_accessed(filp);
@@ -238,6 +251,7 @@ static ssize_t
pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = count };
+
return pipe_readv(filp, &iov, 1, ppos);
}
@@ -246,7 +260,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
unsigned long nr_segs, loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info;
+ struct pipe_inode_info *pipe;
ssize_t ret;
int do_wakeup;
struct iovec *iov = (struct iovec *)_iov;
@@ -260,10 +274,10 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
do_wakeup = 0;
ret = 0;
- mutex_lock(PIPE_MUTEX(*inode));
- info = inode->i_pipe;
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
- if (!PIPE_READERS(*inode)) {
+ if (!pipe->readers) {
send_sig(SIGPIPE, current, 0);
ret = -EPIPE;
goto out;
@@ -271,23 +285,25 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
/* We try to merge small writes */
chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */
- if (info->nrbufs && chars != 0) {
- int lastbuf = (info->curbuf + info->nrbufs - 1) & (PIPE_BUFFERS-1);
- struct pipe_buffer *buf = info->bufs + lastbuf;
+ if (pipe->nrbufs && chars != 0) {
+ int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
+ (PIPE_BUFFERS-1);
+ struct pipe_buffer *buf = pipe->bufs + lastbuf;
struct pipe_buf_operations *ops = buf->ops;
int offset = buf->offset + buf->len;
+
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
void *addr;
int error;
- addr = ops->map(filp, info, buf);
+ addr = ops->map(filp, pipe, buf);
if (IS_ERR(addr)) {
error = PTR_ERR(addr);
goto out;
}
error = pipe_iov_copy_from_user(offset + addr, iov,
chars);
- ops->unmap(info, buf);
+ ops->unmap(pipe, buf);
ret = error;
do_wakeup = 1;
if (error)
@@ -302,16 +318,18 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
for (;;) {
int bufs;
- if (!PIPE_READERS(*inode)) {
+
+ if (!pipe->readers) {
send_sig(SIGPIPE, current, 0);
- if (!ret) ret = -EPIPE;
+ if (!ret)
+ ret = -EPIPE;
break;
}
- bufs = info->nrbufs;
+ bufs = pipe->nrbufs;
if (bufs < PIPE_BUFFERS) {
- int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS-1);
- struct pipe_buffer *buf = info->bufs + newbuf;
- struct page *page = info->tmp_page;
+ int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS-1);
+ struct pipe_buffer *buf = pipe->bufs + newbuf;
+ struct page *page = pipe->tmp_page;
int error;
if (!page) {
@@ -320,9 +338,9 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
ret = ret ? : -ENOMEM;
break;
}
- info->tmp_page = page;
+ pipe->tmp_page = page;
}
- /* Always wakeup, even if the copy fails. Otherwise
+ /* Always wake up, even if the copy fails. Otherwise
* we lock up (O_NONBLOCK-)readers that sleep due to
* syscall merging.
* FIXME! Is this really true?
@@ -335,7 +353,8 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
error = pipe_iov_copy_from_user(kmap(page), iov, chars);
kunmap(page);
if (unlikely(error)) {
- if (!ret) ret = -EFAULT;
+ if (!ret)
+ ret = -EFAULT;
break;
}
ret += chars;
@@ -345,8 +364,8 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
buf->ops = &anon_pipe_buf_ops;
buf->offset = 0;
buf->len = chars;
- info->nrbufs = ++bufs;
- info->tmp_page = NULL;
+ pipe->nrbufs = ++bufs;
+ pipe->tmp_page = NULL;
total_len -= chars;
if (!total_len)
@@ -355,27 +374,29 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
if (bufs < PIPE_BUFFERS)
continue;
if (filp->f_flags & O_NONBLOCK) {
- if (!ret) ret = -EAGAIN;
+ if (!ret)
+ ret = -EAGAIN;
break;
}
if (signal_pending(current)) {
- if (!ret) ret = -ERESTARTSYS;
+ if (!ret)
+ ret = -ERESTARTSYS;
break;
}
if (do_wakeup) {
- wake_up_interruptible_sync(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
do_wakeup = 0;
}
- PIPE_WAITING_WRITERS(*inode)++;
- pipe_wait(inode);
- PIPE_WAITING_WRITERS(*inode)--;
+ pipe->waiting_writers++;
+ pipe_wait(pipe);
+ pipe->waiting_writers--;
}
out:
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
if (do_wakeup) {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
}
if (ret > 0)
file_update_time(filp);
@@ -387,6 +408,7 @@ pipe_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+
return pipe_writev(filp, &iov, 1, ppos);
}
@@ -397,7 +419,8 @@ bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
}
static ssize_t
-bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
+bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
+ loff_t *ppos)
{
return -EBADF;
}
@@ -407,21 +430,22 @@ pipe_ioctl(struct inode *pino, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info;
+ struct pipe_inode_info *pipe;
int count, buf, nrbufs;
switch (cmd) {
case FIONREAD:
- mutex_lock(PIPE_MUTEX(*inode));
- info = inode->i_pipe;
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
count = 0;
- buf = info->curbuf;
- nrbufs = info->nrbufs;
+ buf = pipe->curbuf;
+ nrbufs = pipe->nrbufs;
while (--nrbufs >= 0) {
- count += info->bufs[buf].len;
+ count += pipe->bufs[buf].len;
buf = (buf+1) & (PIPE_BUFFERS-1);
}
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
+
return put_user(count, (int __user *)arg);
default:
return -EINVAL;
@@ -434,17 +458,17 @@ pipe_poll(struct file *filp, poll_table *wait)
{
unsigned int mask;
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info = inode->i_pipe;
+ struct pipe_inode_info *pipe = inode->i_pipe;
int nrbufs;
- poll_wait(filp, PIPE_WAIT(*inode), wait);
+ poll_wait(filp, &pipe->wait, wait);
/* Reading only -- no need for acquiring the semaphore. */
- nrbufs = info->nrbufs;
+ nrbufs = pipe->nrbufs;
mask = 0;
if (filp->f_mode & FMODE_READ) {
mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
- if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode))
+ if (!pipe->writers && filp->f_version != pipe->w_counter)
mask |= POLLHUP;
}
@@ -454,7 +478,7 @@ pipe_poll(struct file *filp, poll_table *wait)
* Most Unices do not set POLLERR for FIFOs but on Linux they
* behave exactly like pipes for poll().
*/
- if (!PIPE_READERS(*inode))
+ if (!pipe->readers)
mask |= POLLERR;
}
@@ -464,17 +488,21 @@ pipe_poll(struct file *filp, poll_table *wait)
static int
pipe_release(struct inode *inode, int decr, int decw)
{
- mutex_lock(PIPE_MUTEX(*inode));
- PIPE_READERS(*inode) -= decr;
- PIPE_WRITERS(*inode) -= decw;
- if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
+ struct pipe_inode_info *pipe;
+
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
+ pipe->readers -= decr;
+ pipe->writers -= decw;
+
+ if (!pipe->readers && !pipe->writers) {
free_pipe_info(inode);
} else {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -485,9 +513,9 @@ pipe_read_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- mutex_lock(PIPE_MUTEX(*inode));
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
+ mutex_unlock(&inode->i_mutex);
if (retval < 0)
return retval;
@@ -502,9 +530,9 @@ pipe_write_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- mutex_lock(PIPE_MUTEX(*inode));
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
+ mutex_unlock(&inode->i_mutex);
if (retval < 0)
return retval;
@@ -517,16 +545,17 @@ static int
pipe_rdwr_fasync(int fd, struct file *filp, int on)
{
struct inode *inode = filp->f_dentry->d_inode;
+ struct pipe_inode_info *pipe = inode->i_pipe;
int retval;
- mutex_lock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
+ retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
if (retval >= 0)
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
+ retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
if (retval < 0)
return retval;
@@ -565,9 +594,9 @@ pipe_read_open(struct inode *inode, struct file *filp)
{
/* We could have perhaps used atomic_t, but this and friends
below are the only places. So it doesn't seem worthwhile. */
- mutex_lock(PIPE_MUTEX(*inode));
- PIPE_READERS(*inode)++;
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ inode->i_pipe->readers++;
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -575,9 +604,9 @@ pipe_read_open(struct inode *inode, struct file *filp)
static int
pipe_write_open(struct inode *inode, struct file *filp)
{
- mutex_lock(PIPE_MUTEX(*inode));
- PIPE_WRITERS(*inode)++;
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ inode->i_pipe->writers++;
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -585,12 +614,12 @@ pipe_write_open(struct inode *inode, struct file *filp)
static int
pipe_rdwr_open(struct inode *inode, struct file *filp)
{
- mutex_lock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
if (filp->f_mode & FMODE_READ)
- PIPE_READERS(*inode)++;
+ inode->i_pipe->readers++;
if (filp->f_mode & FMODE_WRITE)
- PIPE_WRITERS(*inode)++;
- mutex_unlock(PIPE_MUTEX(*inode));
+ inode->i_pipe->writers++;
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -673,37 +702,38 @@ static struct file_operations rdwr_pipe_fops = {
.fasync = pipe_rdwr_fasync,
};
-void free_pipe_info(struct inode *inode)
+struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
+{
+ struct pipe_inode_info *pipe;
+
+ pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+ if (pipe) {
+ init_waitqueue_head(&pipe->wait);
+ pipe->r_counter = pipe->w_counter = 1;
+ pipe->inode = inode;
+ }
+
+ return pipe;
+}
+
+void __free_pipe_info(struct pipe_inode_info *pipe)
{
int i;
- struct pipe_inode_info *info = inode->i_pipe;
- inode->i_pipe = NULL;
for (i = 0; i < PIPE_BUFFERS; i++) {
- struct pipe_buffer *buf = info->bufs + i;
+ struct pipe_buffer *buf = pipe->bufs + i;
if (buf->ops)
- buf->ops->release(info, buf);
+ buf->ops->release(pipe, buf);
}
- if (info->tmp_page)
- __free_page(info->tmp_page);
- kfree(info);
+ if (pipe->tmp_page)
+ __free_page(pipe->tmp_page);
+ kfree(pipe);
}
-struct inode* pipe_new(struct inode* inode)
+void free_pipe_info(struct inode *inode)
{
- struct pipe_inode_info *info;
-
- info = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
- if (!info)
- goto fail_page;
- inode->i_pipe = info;
-
- init_waitqueue_head(PIPE_WAIT(*inode));
- PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
-
- return inode;
-fail_page:
- return NULL;
+ __free_pipe_info(inode->i_pipe);
+ inode->i_pipe = NULL;
}
static struct vfsmount *pipe_mnt __read_mostly;
@@ -711,6 +741,7 @@ static int pipefs_delete_dentry(struct dentry *dentry)
{
return 1;
}
+
static struct dentry_operations pipefs_dentry_operations = {
.d_delete = pipefs_delete_dentry,
};
@@ -718,13 +749,17 @@ static struct dentry_operations pipefs_dentry_operations = {
static struct inode * get_pipe_inode(void)
{
struct inode *inode = new_inode(pipe_mnt->mnt_sb);
+ struct pipe_inode_info *pipe;
if (!inode)
goto fail_inode;
- if(!pipe_new(inode))
+ pipe = alloc_pipe_info(inode);
+ if (!pipe)
goto fail_iput;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+ inode->i_pipe = pipe;
+
+ pipe->readers = pipe->writers = 1;
inode->i_fop = &rdwr_pipe_fops;
/*
@@ -739,10 +774,12 @@ static struct inode * get_pipe_inode(void)
inode->i_gid = current->fsgid;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_blksize = PAGE_SIZE;
+
return inode;
fail_iput:
iput(inode);
+
fail_inode:
return NULL;
}
@@ -755,7 +792,7 @@ int do_pipe(int *fd)
struct inode * inode;
struct file *f1, *f2;
int error;
- int i,j;
+ int i, j;
error = -ENFILE;
f1 = get_empty_filp();
@@ -788,6 +825,7 @@ int do_pipe(int *fd)
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
if (!dentry)
goto close_f12_inode_i_j;
+
dentry->d_op = &pipefs_dentry_operations;
d_add(dentry, inode);
f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
@@ -811,6 +849,7 @@ int do_pipe(int *fd)
fd_install(j, f2);
fd[0] = i;
fd[1] = j;
+
return 0;
close_f12_inode_i_j:
@@ -835,8 +874,9 @@ no_files:
* d_name - pipe: will go nicely and kill the special-casing in procfs.
*/
-static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static struct super_block *
+pipefs_get_sb(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
{
return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
}
@@ -850,6 +890,7 @@ static struct file_system_type pipe_fs_type = {
static int __init init_pipe_fs(void)
{
int err = register_filesystem(&pipe_fs_type);
+
if (!err) {
pipe_mnt = kern_mount(&pipe_fs_type);
if (IS_ERR(pipe_mnt)) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a3a3eecef689..6cc77dc3f3ff 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -297,16 +297,20 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
files = get_files_struct(task);
if (files) {
- rcu_read_lock();
+ /*
+ * We are not taking a ref to the file structure, so we must
+ * hold ->file_lock.
+ */
+ spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (file) {
*mnt = mntget(file->f_vfsmnt);
*dentry = dget(file->f_dentry);
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
return 0;
}
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
}
return -ENOENT;
@@ -1523,7 +1527,12 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
if (!files)
goto out_unlock;
inode->i_mode = S_IFLNK;
- rcu_read_lock();
+
+ /*
+ * We are not taking a ref to the file structure, so we must
+ * hold ->file_lock.
+ */
+ spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (!file)
goto out_unlock2;
@@ -1531,7 +1540,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
inode->i_mode |= S_IRUSR | S_IXUSR;
if (file->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
inode->i_op = &proc_pid_link_inode_operations;
inode->i_size = 64;
@@ -1541,7 +1550,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
return NULL;
out_unlock2:
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
out_unlock:
iput(inode);
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 7efa73d44c9a..20d4b2237fce 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -103,8 +103,8 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
size_t buflen, loff_t *fpos)
{
ssize_t acc = 0, tmp;
- size_t tsz, nr_bytes;
- u64 start;
+ size_t tsz;
+ u64 start, nr_bytes;
struct vmcore *curr_m = NULL;
if (buflen == 0 || *fpos >= vmcore_size)
diff --git a/fs/read_write.c b/fs/read_write.c
index 6256ca81a718..5bc0e9234f9d 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -202,7 +202,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
goto Einval;
inode = file->f_dentry->d_inode;
- if (inode->i_flock && MANDATORY_LOCK(inode)) {
+ if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
int retval = locks_mandatory_area(
read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
inode, file, pos, count);
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 58c418fbca2c..97ae1b92bc47 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -408,8 +408,9 @@ int reiserfs_cache_default_acl(struct inode *inode)
acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
reiserfs_read_unlock_xattrs(inode->i_sb);
reiserfs_read_unlock_xattr_i(inode);
- ret = acl ? 1 : 0;
- posix_acl_release(acl);
+ ret = (acl && !IS_ERR(acl));
+ if (ret)
+ posix_acl_release(acl);
}
return ret;
diff --git a/fs/select.c b/fs/select.c
index 071660fa7b01..a8109baa5e46 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -310,8 +310,9 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
fd_set __user *exp, s64 *timeout)
{
fd_set_bits fds;
- char *bits;
- int ret, size, max_fdset;
+ void *bits;
+ int ret, max_fdset;
+ unsigned int size;
struct fdtable *fdt;
/* Allocate small arguments on the stack to save memory and be faster */
long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
@@ -333,20 +334,21 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
* since we used fdset we need to allocate memory in units of
* long-words.
*/
- ret = -ENOMEM;
size = FDS_BYTES(n);
- if (6*size < SELECT_STACK_ALLOC)
- bits = stack_fds;
- else
+ bits = stack_fds;
+ if (size > sizeof(stack_fds) / 6) {
+ /* Not enough space in on-stack array; must use kmalloc */
+ ret = -ENOMEM;
bits = kmalloc(6 * size, GFP_KERNEL);
- if (!bits)
- goto out_nofds;
- fds.in = (unsigned long *) bits;
- fds.out = (unsigned long *) (bits + size);
- fds.ex = (unsigned long *) (bits + 2*size);
- fds.res_in = (unsigned long *) (bits + 3*size);
- fds.res_out = (unsigned long *) (bits + 4*size);
- fds.res_ex = (unsigned long *) (bits + 5*size);
+ if (!bits)
+ goto out_nofds;
+ }
+ fds.in = bits;
+ fds.out = bits + size;
+ fds.ex = bits + 2*size;
+ fds.res_in = bits + 3*size;
+ fds.res_out = bits + 4*size;
+ fds.res_ex = bits + 5*size;
if ((ret = get_fd_set(n, inp, fds.in)) ||
(ret = get_fd_set(n, outp, fds.out)) ||
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index c56bd99a9701..ed9a24d19d7d 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -178,11 +178,9 @@ smb_writepage(struct page *page, struct writeback_control *wbc)
unsigned offset = PAGE_CACHE_SIZE;
int err;
- if (!mapping)
- BUG();
+ BUG_ON(!mapping);
inode = mapping->host;
- if (!inode)
- BUG();
+ BUG_ON(!inode);
end_index = inode->i_size >> PAGE_CACHE_SHIFT;
diff --git a/fs/splice.c b/fs/splice.c
index 7c2bbf18d7a7..a46ddd28561e 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -9,11 +9,12 @@
* that transfers data buffers to or from a pipe buffer.
*
* Named by Larry McVoy, original implementation from Linus, extended by
- * Jens to support splicing to files and fixing the initial implementation
- * bugs.
+ * Jens to support splicing to files, network, direct splicing, etc and
+ * fixing lots of bugs.
*
- * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
- * Copyright (C) 2005 Linus Torvalds <torvalds@osdl.org>
+ * Copyright (C) 2005-2006 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org>
+ * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu>
*
*/
#include <linux/fs.h>
@@ -22,40 +23,62 @@
#include <linux/pipe_fs_i.h>
#include <linux/mm_inline.h>
#include <linux/swap.h>
+#include <linux/writeback.h>
+#include <linux/buffer_head.h>
#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uio.h>
+
+struct partial_page {
+ unsigned int offset;
+ unsigned int len;
+};
/*
- * Passed to the actors
+ * Passed to splice_to_pipe
*/
-struct splice_desc {
- unsigned int len, total_len; /* current and remaining length */
+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 */
- struct file *file; /* file to read/write */
- loff_t pos; /* file position */
+ struct pipe_buf_operations *ops;/* ops associated with output pipe */
};
+/*
+ * Attempt to steal a page from a pipe buffer. This should perhaps go into
+ * a vm helper function, it's already simplified quite a bit by the
+ * addition of remove_mapping(). If success is returned, the caller may
+ * attempt to reuse this page for another destination.
+ */
static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
struct pipe_buffer *buf)
{
struct page *page = buf->page;
+ struct address_space *mapping = page_mapping(page);
+
+ lock_page(page);
- WARN_ON(!PageLocked(page));
WARN_ON(!PageUptodate(page));
- if (!remove_mapping(page_mapping(page), page))
- return 1;
+ /*
+ * At least for ext2 with nobh option, we need to wait on writeback
+ * completing on this page, since we'll remove it from the pagecache.
+ * Otherwise truncate wont wait on the page, allowing the disk
+ * blocks to be reused by someone else before we actually wrote our
+ * data to them. fs corruption ensues.
+ */
+ wait_on_page_writeback(page);
- if (PageLRU(page)) {
- struct zone *zone = page_zone(page);
+ if (PagePrivate(page))
+ try_to_release_page(page, mapping_gfp_mask(mapping));
- spin_lock_irq(&zone->lru_lock);
- BUG_ON(!PageLRU(page));
- __ClearPageLRU(page);
- del_page_from_lru(zone, page);
- spin_unlock_irq(&zone->lru_lock);
+ if (!remove_mapping(mapping, page)) {
+ unlock_page(page);
+ return 1;
}
- buf->stolen = 1;
+ buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU;
return 0;
}
@@ -64,7 +87,7 @@ static void page_cache_pipe_buf_release(struct pipe_inode_info *info,
{
page_cache_release(buf->page);
buf->page = NULL;
- buf->stolen = 0;
+ buf->flags &= ~(PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU);
}
static void *page_cache_pipe_buf_map(struct file *file,
@@ -72,93 +95,142 @@ static void *page_cache_pipe_buf_map(struct file *file,
struct pipe_buffer *buf)
{
struct page *page = buf->page;
-
- lock_page(page);
+ int err;
if (!PageUptodate(page)) {
- unlock_page(page);
- return ERR_PTR(-EIO);
- }
+ lock_page(page);
+
+ /*
+ * Page got truncated/unhashed. This will cause a 0-byte
+ * splice, if this is the first page.
+ */
+ if (!page->mapping) {
+ err = -ENODATA;
+ goto error;
+ }
+
+ /*
+ * Uh oh, read-error from disk.
+ */
+ if (!PageUptodate(page)) {
+ err = -EIO;
+ goto error;
+ }
- if (!page->mapping) {
+ /*
+ * Page is ok afterall, fall through to mapping.
+ */
unlock_page(page);
- return ERR_PTR(-ENODATA);
}
- return kmap(buf->page);
+ return kmap(page);
+error:
+ unlock_page(page);
+ return ERR_PTR(err);
}
static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info,
struct pipe_buffer *buf)
{
- if (!buf->stolen)
- unlock_page(buf->page);
kunmap(buf->page);
}
+static void *user_page_pipe_buf_map(struct file *file,
+ struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ return kmap(buf->page);
+}
+
+static void user_page_pipe_buf_unmap(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ kunmap(buf->page);
+}
+
+static void page_cache_pipe_buf_get(struct pipe_inode_info *info,
+ struct pipe_buffer *buf)
+{
+ page_cache_get(buf->page);
+}
+
static struct pipe_buf_operations page_cache_pipe_buf_ops = {
.can_merge = 0,
.map = page_cache_pipe_buf_map,
.unmap = page_cache_pipe_buf_unmap,
.release = page_cache_pipe_buf_release,
.steal = page_cache_pipe_buf_steal,
+ .get = page_cache_pipe_buf_get,
+};
+
+static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ return 1;
+}
+
+static struct pipe_buf_operations user_page_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = user_page_pipe_buf_map,
+ .unmap = user_page_pipe_buf_unmap,
+ .release = page_cache_pipe_buf_release,
+ .steal = user_page_pipe_buf_steal,
+ .get = page_cache_pipe_buf_get,
};
-static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
- int nr_pages, unsigned long offset,
- unsigned long len)
+/*
+ * Pipe output worker. This sets up our pipe format with the page cache
+ * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+ */
+static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd)
{
- struct pipe_inode_info *info;
- int ret, do_wakeup, i;
+ int ret, do_wakeup, page_nr;
ret = 0;
do_wakeup = 0;
- i = 0;
+ page_nr = 0;
- mutex_lock(PIPE_MUTEX(*inode));
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
- info = inode->i_pipe;
for (;;) {
- int bufs;
-
- if (!PIPE_READERS(*inode)) {
+ if (!pipe->readers) {
send_sig(SIGPIPE, current, 0);
if (!ret)
ret = -EPIPE;
break;
}
- bufs = info->nrbufs;
- if (bufs < PIPE_BUFFERS) {
- int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1);
- struct pipe_buffer *buf = info->bufs + newbuf;
- struct page *page = pages[i++];
- unsigned long this_len;
-
- this_len = PAGE_CACHE_SIZE - offset;
- if (this_len > len)
- this_len = len;
-
- buf->page = page;
- buf->offset = offset;
- buf->len = this_len;
- buf->ops = &page_cache_pipe_buf_ops;
- info->nrbufs = ++bufs;
- do_wakeup = 1;
-
- ret += this_len;
- len -= this_len;
- offset = 0;
- if (!--nr_pages)
- break;
- if (!len)
+ if (pipe->nrbufs < PIPE_BUFFERS) {
+ int newbuf = (pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS - 1);
+ struct pipe_buffer *buf = pipe->bufs + newbuf;
+
+ buf->page = spd->pages[page_nr];
+ buf->offset = spd->partial[page_nr].offset;
+ buf->len = spd->partial[page_nr].len;
+ buf->ops = spd->ops;
+ pipe->nrbufs++;
+ page_nr++;
+ ret += buf->len;
+
+ if (pipe->inode)
+ do_wakeup = 1;
+
+ if (!--spd->nr_pages)
break;
- if (bufs < PIPE_BUFFERS)
+ if (pipe->nrbufs < PIPE_BUFFERS)
continue;
break;
}
+ if (spd->flags & SPLICE_F_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
@@ -166,137 +238,264 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
}
if (do_wakeup) {
- wake_up_interruptible_sync(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO,
- POLL_IN);
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
do_wakeup = 0;
}
- PIPE_WAITING_WRITERS(*inode)++;
- pipe_wait(inode);
- PIPE_WAITING_WRITERS(*inode)--;
+ pipe->waiting_writers++;
+ pipe_wait(pipe);
+ pipe->waiting_writers--;
}
- mutex_unlock(PIPE_MUTEX(*inode));
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
if (do_wakeup) {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
}
- while (i < nr_pages)
- page_cache_release(pages[i++]);
+ while (page_nr < spd->nr_pages)
+ page_cache_release(spd->pages[page_nr++]);
return ret;
}
-static int __generic_file_splice_read(struct file *in, struct inode *pipe,
- size_t len)
+static int
+__generic_file_splice_read(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
{
struct address_space *mapping = in->f_mapping;
- unsigned int offset, nr_pages;
- struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS];
+ unsigned int loff, nr_pages;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
struct page *page;
- pgoff_t index, pidx;
- int i, j;
-
- index = in->f_pos >> PAGE_CACHE_SHIFT;
- offset = in->f_pos & ~PAGE_CACHE_MASK;
- nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ pgoff_t index, end_index;
+ loff_t isize;
+ size_t total_len;
+ int error, page_nr;
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .partial = partial,
+ .flags = flags,
+ .ops = &page_cache_pipe_buf_ops,
+ };
+
+ index = *ppos >> PAGE_CACHE_SHIFT;
+ loff = *ppos & ~PAGE_CACHE_MASK;
+ nr_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (nr_pages > PIPE_BUFFERS)
nr_pages = PIPE_BUFFERS;
/*
- * initiate read-ahead on this page range
+ * Initiate read-ahead on this page range. however, don't call into
+ * read-ahead if this is a non-zero offset (we are likely doing small
+ * chunk splice and the page is already there) for a single page.
*/
- do_page_cache_readahead(mapping, in, index, nr_pages);
+ if (!loff || nr_pages > 1)
+ page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
/*
- * Get as many pages from the page cache as possible..
- * Start IO on the page cache entries we create (we
- * can assume that any pre-existing ones we find have
- * already had IO started on them).
+ * Now fill in the holes:
*/
- i = find_get_pages(mapping, index, nr_pages, pages);
+ error = 0;
+ total_len = 0;
/*
- * common case - we found all pages and they are contiguous,
- * kick them off
+ * Lookup the (hopefully) full range of pages we need.
*/
- if (i && (pages[i - 1]->index == index + i - 1))
- goto splice_them;
+ spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
/*
- * fill shadow[] with pages at the right locations, so we only
- * have to fill holes
+ * If find_get_pages_contig() returned fewer pages than we needed,
+ * allocate the rest.
*/
- memset(shadow, 0, i * sizeof(struct page *));
- for (j = 0, pidx = index; j < i; pidx++, j++)
- shadow[pages[j]->index - pidx] = pages[j];
+ index += spd.nr_pages;
+ while (spd.nr_pages < nr_pages) {
+ /*
+ * Page could be there, find_get_pages_contig() breaks on
+ * the first hole.
+ */
+ page = find_get_page(mapping, index);
+ if (!page) {
+ /*
+ * page didn't exist, allocate one.
+ */
+ page = page_cache_alloc_cold(mapping);
+ if (!page)
+ break;
+
+ error = add_to_page_cache_lru(page, mapping, index,
+ mapping_gfp_mask(mapping));
+ if (unlikely(error)) {
+ page_cache_release(page);
+ break;
+ }
+ /*
+ * add_to_page_cache() locks the page, unlock it
+ * to avoid convoluting the logic below even more.
+ */
+ unlock_page(page);
+ }
+
+ pages[spd.nr_pages++] = page;
+ index++;
+ }
/*
- * now fill in the holes
+ * Now loop over the map and see if we need to start IO on any
+ * pages, fill in the partial map, etc.
*/
- for (i = 0, pidx = index; i < nr_pages; pidx++, i++) {
- int error;
+ index = *ppos >> PAGE_CACHE_SHIFT;
+ nr_pages = spd.nr_pages;
+ spd.nr_pages = 0;
+ for (page_nr = 0; page_nr < nr_pages; page_nr++) {
+ unsigned int this_len;
- if (shadow[i])
- continue;
+ if (!len)
+ break;
/*
- * no page there, look one up / create it
+ * this_len is the max we'll use from this page
*/
- page = find_or_create_page(mapping, pidx,
- mapping_gfp_mask(mapping));
- if (!page)
- break;
+ this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff);
+ page = pages[page_nr];
- if (PageUptodate(page))
- unlock_page(page);
- else {
- error = mapping->a_ops->readpage(in, page);
+ /*
+ * If the page isn't uptodate, we may need to start io on it
+ */
+ if (!PageUptodate(page)) {
+ /*
+ * If in nonblock mode then dont block on waiting
+ * for an in-flight io page
+ */
+ if (flags & SPLICE_F_NONBLOCK)
+ break;
+
+ lock_page(page);
+
+ /*
+ * page was truncated, stop here. if this isn't the
+ * first page, we'll just complete what we already
+ * added
+ */
+ if (!page->mapping) {
+ unlock_page(page);
+ break;
+ }
+ /*
+ * page was already under io and is now done, great
+ */
+ if (PageUptodate(page)) {
+ unlock_page(page);
+ goto fill_it;
+ }
+ /*
+ * need to read in the page
+ */
+ error = mapping->a_ops->readpage(in, page);
if (unlikely(error)) {
- page_cache_release(page);
+ /*
+ * We really should re-lookup the page here,
+ * but it complicates things a lot. Instead
+ * lets just do what we already stored, and
+ * we'll get it the next time we are called.
+ */
+ if (error == AOP_TRUNCATED_PAGE)
+ error = 0;
+
break;
}
- }
- shadow[i] = page;
- }
- if (!i) {
- for (i = 0; i < nr_pages; i++) {
- if (shadow[i])
- page_cache_release(shadow[i]);
+ /*
+ * i_size must be checked after ->readpage().
+ */
+ 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) {
+ 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;
+ }
}
- return 0;
+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++;
}
- memcpy(pages, shadow, i * sizeof(struct page *));
-
/*
- * Now we splice them into the pipe..
+ * Release any pages at the end, if we quit early. 'i' is how far
+ * we got, 'nr_pages' is how many pages are in the map.
*/
-splice_them:
- return move_to_pipe(pipe, pages, i, offset, len);
+ while (page_nr < nr_pages)
+ page_cache_release(pages[page_nr++]);
+
+ if (spd.nr_pages)
+ return splice_to_pipe(pipe, &spd);
+
+ return error;
}
-ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
- size_t len, unsigned int flags)
+/**
+ * generic_file_splice_read - splice data from file to a pipe
+ * @in: file to splice from
+ * @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.
+ */
+ssize_t generic_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;
ret = 0;
spliced = 0;
+
while (len) {
- ret = __generic_file_splice_read(in, pipe, len);
+ ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
- if (ret <= 0)
+ if (ret < 0)
break;
+ else if (!ret) {
+ if (spliced)
+ break;
+ if (flags & SPLICE_F_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ }
- in->f_pos += ret;
+ *ppos += ret;
len -= ret;
spliced += ret;
}
@@ -307,38 +506,38 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
return ret;
}
+EXPORT_SYMBOL(generic_file_splice_read);
+
/*
- * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage().
+ * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos'
+ * using sendpage(). Return the number of bytes sent.
*/
static int pipe_to_sendpage(struct pipe_inode_info *info,
struct pipe_buffer *buf, struct splice_desc *sd)
{
struct file *file = sd->file;
loff_t pos = sd->pos;
- unsigned int offset;
ssize_t ret;
void *ptr;
+ int more;
/*
- * sub-optimal, but we are limited by the pipe ->map. we don't
+ * Sub-optimal, but we are limited by the pipe ->map. We don't
* need a kmap'ed buffer here, we just want to make sure we
* have the page pinned if the pipe page originates from the
- * page cache
+ * page cache.
*/
ptr = buf->ops->map(file, info, buf);
if (IS_ERR(ptr))
return PTR_ERR(ptr);
- offset = pos & ~PAGE_CACHE_MASK;
+ more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
- ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos,
- sd->len < sd->total_len);
+ ret = file->f_op->sendpage(file, buf->page, buf->offset, sd->len,
+ &pos, more);
buf->ops->unmap(info, buf);
- if (ret == sd->len)
- return 0;
-
- return -EIO;
+ return ret;
}
/*
@@ -354,24 +553,27 @@ static int pipe_to_sendpage(struct pipe_inode_info *info,
* - Destination page does not exist, we can add the pipe page to
* the page cache and avoid the copy.
*
- * For now we just do the slower thing and always copy pages over, it's
- * easier than migrating pages from the pipe to the target file. For the
- * case of doing file | file splicing, the migrate approach had some LRU
- * nastiness...
+ * If asked to move pages to the output file (SPLICE_F_MOVE is set in
+ * sd->flags), we attempt to migrate pages from the pipe to the output
+ * file address space page cache. This is possible if no one else has
+ * the pipe page referenced outside of the pipe and page cache. If
+ * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
+ * a new page in the output file page cache and fill/dirty that.
*/
static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
struct splice_desc *sd)
{
struct file *file = sd->file;
struct address_space *mapping = file->f_mapping;
- unsigned int offset;
+ gfp_t gfp_mask = mapping_gfp_mask(mapping);
+ unsigned int offset, this_len;
struct page *page;
pgoff_t index;
char *src;
int ret;
/*
- * after this, page will be locked and unmapped
+ * make sure the data in this buffer is uptodate
*/
src = buf->ops->map(file, info, buf);
if (IS_ERR(src))
@@ -380,32 +582,54 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
index = sd->pos >> PAGE_CACHE_SHIFT;
offset = sd->pos & ~PAGE_CACHE_MASK;
+ this_len = sd->len;
+ if (this_len + offset > PAGE_CACHE_SIZE)
+ this_len = PAGE_CACHE_SIZE - offset;
+
/*
- * reuse buf page, if SPLICE_F_MOVE is set
+ * Reuse buf page, if SPLICE_F_MOVE is set.
*/
if (sd->flags & SPLICE_F_MOVE) {
+ /*
+ * If steal succeeds, buf->page is now pruned from the vm
+ * side (LRU and page cache) and we can reuse it. The page
+ * will also be looked on successful return.
+ */
if (buf->ops->steal(info, buf))
goto find_page;
page = buf->page;
- if (add_to_page_cache_lru(page, mapping, index,
- mapping_gfp_mask(mapping)))
+ if (add_to_page_cache(page, mapping, index, gfp_mask))
goto find_page;
+
+ if (!(buf->flags & PIPE_BUF_FLAG_LRU))
+ lru_cache_add(page);
} else {
find_page:
- ret = -ENOMEM;
- page = find_or_create_page(mapping, index,
- mapping_gfp_mask(mapping));
- if (!page)
- goto out;
+ page = find_lock_page(mapping, index);
+ if (!page) {
+ ret = -ENOMEM;
+ page = page_cache_alloc_cold(mapping);
+ if (unlikely(!page))
+ goto out_nomem;
+
+ /*
+ * This will also lock the page
+ */
+ ret = add_to_page_cache_lru(page, mapping, index,
+ gfp_mask);
+ if (unlikely(ret))
+ goto out;
+ }
/*
- * If the page is uptodate, it is also locked. If it isn't
- * uptodate, we can mark it uptodate if we are filling the
- * full page. Otherwise we need to read it in first...
+ * We get here with the page locked. If the page is also
+ * uptodate, we don't need to do more. If it isn't, we
+ * may need to bring it in if we are not going to overwrite
+ * the full page.
*/
if (!PageUptodate(page)) {
- if (sd->len < PAGE_CACHE_SIZE) {
+ if (this_len < PAGE_CACHE_SIZE) {
ret = mapping->a_ops->readpage(file, page);
if (unlikely(ret))
goto out;
@@ -414,7 +638,7 @@ find_page:
if (!PageUptodate(page)) {
/*
- * page got invalidated, repeat
+ * Page got invalidated, repeat.
*/
if (!page->mapping) {
unlock_page(page);
@@ -424,48 +648,58 @@ find_page:
ret = -EIO;
goto out;
}
- } else {
- WARN_ON(!PageLocked(page));
+ } else
SetPageUptodate(page);
- }
}
}
- ret = mapping->a_ops->prepare_write(file, page, 0, sd->len);
- if (ret)
+ ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto find_page;
+ } else if (ret)
goto out;
- if (!buf->stolen) {
+ if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) {
char *dst = kmap_atomic(page, KM_USER0);
- memcpy(dst + offset, src + buf->offset, sd->len);
+ memcpy(dst + offset, src + buf->offset, this_len);
flush_dcache_page(page);
kunmap_atomic(dst, KM_USER0);
}
- ret = mapping->a_ops->commit_write(file, page, 0, sd->len);
- if (ret < 0)
+ ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto find_page;
+ } else if (ret)
goto out;
- set_page_dirty(page);
- ret = write_one_page(page, 0);
+ /*
+ * Return the number of bytes written.
+ */
+ ret = this_len;
+ mark_page_accessed(page);
+ balance_dirty_pages_ratelimited(mapping);
out:
- if (ret < 0)
- unlock_page(page);
- if (!buf->stolen)
+ if (!(buf->flags & PIPE_BUF_FLAG_STOLEN))
page_cache_release(page);
+
+ unlock_page(page);
+out_nomem:
buf->ops->unmap(info, buf);
return ret;
}
-typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
- struct splice_desc *);
-
-static ssize_t move_from_pipe(struct inode *inode, struct file *out,
- size_t len, unsigned int flags,
- splice_actor *actor)
+/*
+ * 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.
+ */
+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)
{
- struct pipe_inode_info *info;
int ret, do_wakeup, err;
struct splice_desc sd;
@@ -475,58 +709,66 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,
sd.total_len = len;
sd.flags = flags;
sd.file = out;
- sd.pos = out->f_pos;
+ sd.pos = *ppos;
- mutex_lock(PIPE_MUTEX(*inode));
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
- info = inode->i_pipe;
for (;;) {
- int bufs = info->nrbufs;
-
- if (bufs) {
- int curbuf = info->curbuf;
- struct pipe_buffer *buf = info->bufs + curbuf;
+ if (pipe->nrbufs) {
+ struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
struct pipe_buf_operations *ops = buf->ops;
sd.len = buf->len;
if (sd.len > sd.total_len)
sd.len = sd.total_len;
- err = actor(info, buf, &sd);
- if (err) {
+ err = actor(pipe, buf, &sd);
+ if (err <= 0) {
if (!ret && err != -ENODATA)
ret = err;
break;
}
- ret += sd.len;
- buf->offset += sd.len;
- buf->len -= sd.len;
+ ret += err;
+ buf->offset += err;
+ buf->len -= err;
+
+ sd.len -= err;
+ sd.pos += err;
+ sd.total_len -= err;
+ if (sd.len)
+ continue;
+
if (!buf->len) {
buf->ops = NULL;
- ops->release(info, buf);
- curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1);
- info->curbuf = curbuf;
- info->nrbufs = --bufs;
- do_wakeup = 1;
+ ops->release(pipe, buf);
+ pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
+ pipe->nrbufs--;
+ if (pipe->inode)
+ do_wakeup = 1;
}
- sd.pos += sd.len;
- sd.total_len -= sd.len;
if (!sd.total_len)
break;
}
- if (bufs)
+ if (pipe->nrbufs)
continue;
- if (!PIPE_WRITERS(*inode))
+ if (!pipe->writers)
break;
- if (!PIPE_WAITING_WRITERS(*inode)) {
+ if (!pipe->waiting_writers) {
if (ret)
break;
}
+ if (flags & SPLICE_F_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
@@ -534,108 +776,487 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,
}
if (do_wakeup) {
- wake_up_interruptible_sync(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT);
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
do_wakeup = 0;
}
- pipe_wait(inode);
+ pipe_wait(pipe);
}
- mutex_unlock(PIPE_MUTEX(*inode));
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
if (do_wakeup) {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
- mutex_lock(&out->f_mapping->host->i_mutex);
- out->f_pos = sd.pos;
- mutex_unlock(&out->f_mapping->host->i_mutex);
return ret;
-
}
-ssize_t generic_file_splice_write(struct inode *inode, struct file *out,
- size_t len, unsigned int flags)
+/**
+ * generic_file_splice_write - splice data from a pipe to a file
+ * @pipe: pipe info
+ * @out: file to write to
+ * @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.
+ *
+ */
+ssize_t
+generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
{
- return move_from_pipe(inode, out, len, flags, pipe_to_file);
+ struct address_space *mapping = out->f_mapping;
+ ssize_t ret;
+
+ ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+ if (ret > 0) {
+ struct inode *inode = mapping->host;
+
+ *ppos += ret;
+
+ /*
+ * If file or inode is SYNC and we actually wrote some data,
+ * sync it.
+ */
+ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+ int err;
+
+ mutex_lock(&inode->i_mutex);
+ err = generic_osync_inode(inode, mapping,
+ OSYNC_METADATA|OSYNC_DATA);
+ mutex_unlock(&inode->i_mutex);
+
+ if (err)
+ ret = err;
+ }
+ }
+
+ return ret;
}
-ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
- size_t len, unsigned int flags)
+EXPORT_SYMBOL(generic_file_splice_write);
+
+/**
+ * generic_splice_sendpage - splice data from a pipe to a socket
+ * @inode: pipe inode
+ * @out: socket to write to
+ * @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.
+ *
+ */
+ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
{
- return move_from_pipe(inode, out, len, flags, pipe_to_sendpage);
+ return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage);
}
-EXPORT_SYMBOL(generic_file_splice_write);
-EXPORT_SYMBOL(generic_file_splice_read);
+EXPORT_SYMBOL(generic_splice_sendpage);
-static long do_splice_from(struct inode *pipe, struct file *out, size_t len,
- unsigned int flags)
+/*
+ * Attempt to initiate a splice from pipe to file.
+ */
+static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
{
- loff_t pos;
int ret;
- if (!out->f_op || !out->f_op->splice_write)
+ if (unlikely(!out->f_op || !out->f_op->splice_write))
return -EINVAL;
- if (!(out->f_mode & FMODE_WRITE))
+ if (unlikely(!(out->f_mode & FMODE_WRITE)))
return -EBADF;
- pos = out->f_pos;
- ret = rw_verify_area(WRITE, out, &pos, len);
+ ret = rw_verify_area(WRITE, out, ppos, len);
if (unlikely(ret < 0))
return ret;
- return out->f_op->splice_write(pipe, out, len, flags);
+ return out->f_op->splice_write(pipe, out, ppos, len, flags);
}
-static long do_splice_to(struct file *in, struct inode *pipe, size_t len,
+/*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+static long do_splice_to(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
- loff_t pos, isize, left;
+ loff_t isize, left;
int ret;
- if (!in->f_op || !in->f_op->splice_read)
+ if (unlikely(!in->f_op || !in->f_op->splice_read))
return -EINVAL;
- if (!(in->f_mode & FMODE_READ))
+ if (unlikely(!(in->f_mode & FMODE_READ)))
return -EBADF;
- pos = in->f_pos;
- ret = rw_verify_area(READ, in, &pos, len);
+ ret = rw_verify_area(READ, in, ppos, len);
if (unlikely(ret < 0))
return ret;
isize = i_size_read(in->f_mapping->host);
- if (unlikely(in->f_pos >= isize))
+ if (unlikely(*ppos >= isize))
return 0;
- left = isize - in->f_pos;
- if (left < len)
+ left = isize - *ppos;
+ if (unlikely(left < len))
len = left;
- return in->f_op->splice_read(in, pipe, len, flags);
+ 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)
+{
+ struct pipe_inode_info *pipe;
+ long ret, bytes;
+ loff_t out_off;
+ umode_t i_mode;
+ int i;
+
+ /*
+ * We require the input being a regular file, as we don't want to
+ * randomly drop data for eg socket -> socket splicing. Use the
+ * piped splicing for that!
+ */
+ i_mode = in->f_dentry->d_inode->i_mode;
+ if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
+ return -EINVAL;
+
+ /*
+ * neither in nor out is a pipe, setup an internal pipe attached to
+ * 'out' and transfer the wanted data from 'in' to 'out' through that
+ */
+ pipe = current->splice_pipe;
+ if (unlikely(!pipe)) {
+ pipe = alloc_pipe_info(NULL);
+ if (!pipe)
+ return -ENOMEM;
+
+ /*
+ * We don't have an immediate reader, but we'll read the stuff
+ * out of the pipe right after the splice_to_pipe(). So set
+ * PIPE_READERS appropriately.
+ */
+ pipe->readers = 1;
+
+ current->splice_pipe = pipe;
+ }
+
+ /*
+ * Do the splice.
+ */
+ ret = 0;
+ bytes = 0;
+ out_off = 0;
+
+ while (len) {
+ size_t read_len, max_read_len;
+
+ /*
+ * Do at most PIPE_BUFFERS pages worth of transfer:
+ */
+ max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
+
+ ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
+ if (unlikely(ret < 0))
+ goto out_release;
+
+ read_len = ret;
+
+ /*
+ * 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))
+ 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;
+ }
+
+ pipe->nrbufs = pipe->curbuf = 0;
+
+ return bytes;
+
+out_release:
+ /*
+ * If we did an incomplete transfer we must release
+ * the pipe buffers in question:
+ */
+ for (i = 0; i < PIPE_BUFFERS; i++) {
+ struct pipe_buffer *buf = pipe->bufs + i;
+
+ if (buf->ops) {
+ buf->ops->release(pipe, buf);
+ buf->ops = NULL;
+ }
+ }
+ pipe->nrbufs = pipe->curbuf = 0;
+
+ /*
+ * If we transferred some data, return the number of bytes:
+ */
+ if (bytes > 0)
+ return bytes;
+
+ return ret;
}
-static long do_splice(struct file *in, struct file *out, size_t len,
- unsigned int flags)
+EXPORT_SYMBOL(do_splice_direct);
+
+/*
+ * Determine where to splice to/from.
+ */
+static long do_splice(struct file *in, loff_t __user *off_in,
+ struct file *out, loff_t __user *off_out,
+ size_t len, unsigned int flags)
{
- struct inode *pipe;
+ struct pipe_inode_info *pipe;
+ loff_t offset, *off;
+ long ret;
+
+ pipe = in->f_dentry->d_inode->i_pipe;
+ if (pipe) {
+ if (off_in)
+ return -ESPIPE;
+ if (off_out) {
+ if (out->f_op->llseek == no_llseek)
+ return -EINVAL;
+ if (copy_from_user(&offset, off_out, sizeof(loff_t)))
+ return -EFAULT;
+ off = &offset;
+ } else
+ off = &out->f_pos;
+
+ ret = do_splice_from(pipe, out, off, len, flags);
+
+ if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+ ret = -EFAULT;
+
+ return ret;
+ }
+
+ pipe = out->f_dentry->d_inode->i_pipe;
+ if (pipe) {
+ if (off_out)
+ return -ESPIPE;
+ if (off_in) {
+ if (in->f_op->llseek == no_llseek)
+ return -EINVAL;
+ if (copy_from_user(&offset, off_in, sizeof(loff_t)))
+ return -EFAULT;
+ off = &offset;
+ } else
+ off = &in->f_pos;
- pipe = in->f_dentry->d_inode;
- if (pipe->i_pipe)
- return do_splice_from(pipe, out, len, flags);
+ ret = do_splice_to(in, off, pipe, len, flags);
- pipe = out->f_dentry->d_inode;
- if (pipe->i_pipe)
- return do_splice_to(in, pipe, len, flags);
+ if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+ ret = -EFAULT;
+
+ return ret;
+ }
return -EINVAL;
}
-asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags)
+/*
+ * Map an iov into an array of pages and offset/length tupples. With the
+ * partial_page structure, we can map several non-contiguous ranges into
+ * our ones pages[] map instead of splitting that operation into pieces.
+ * Could easily be exported as a generic helper for other users, in which
+ * case one would probably want to add a 'max_nr_pages' parameter as well.
+ */
+static int get_iovec_page_array(const struct iovec __user *iov,
+ unsigned int nr_vecs, struct page **pages,
+ struct partial_page *partial)
+{
+ int buffers = 0, error = 0;
+
+ /*
+ * It's ok to take the mmap_sem for reading, even
+ * across a "get_user()".
+ */
+ down_read(&current->mm->mmap_sem);
+
+ while (nr_vecs) {
+ unsigned long off, npages;
+ void __user *base;
+ size_t len;
+ int i;
+
+ /*
+ * 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;
+ error = -EFAULT;
+ if (unlikely(!base))
+ break;
+
+ /*
+ * Get this base offset and number of pages, then map
+ * in the user pages.
+ */
+ off = (unsigned long) base & ~PAGE_MASK;
+ npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if (npages > PIPE_BUFFERS - buffers)
+ npages = PIPE_BUFFERS - buffers;
+
+ error = get_user_pages(current, current->mm,
+ (unsigned long) base, npages, 0, 0,
+ &pages[buffers], NULL);
+
+ if (unlikely(error <= 0))
+ break;
+
+ /*
+ * Fill this contiguous range into the partial page map.
+ */
+ for (i = 0; i < error; i++) {
+ const int plen = min_t(size_t, len, PAGE_SIZE) - off;
+
+ partial[buffers].offset = off;
+ partial[buffers].len = plen;
+
+ off = 0;
+ len -= plen;
+ buffers++;
+ }
+
+ /*
+ * We didn't complete this iov, stop here since it probably
+ * means we have to move some of this into a pipe to
+ * be able to continue.
+ */
+ if (len)
+ break;
+
+ /*
+ * Don't continue if we mapped fewer pages than we asked for,
+ * or if we mapped the max number of pages that we have
+ * room for.
+ */
+ if (error < npages || buffers == PIPE_BUFFERS)
+ break;
+
+ nr_vecs--;
+ iov++;
+ }
+
+ up_read(&current->mm->mmap_sem);
+
+ if (buffers)
+ return buffers;
+
+ return error;
+}
+
+/*
+ * 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)
+{
+ struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .partial = partial,
+ .flags = flags,
+ .ops = &user_page_pipe_buf_ops,
+ };
+
+ if (unlikely(!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);
+ if (spd.nr_pages <= 0)
+ return spd.nr_pages;
+
+ return splice_to_pipe(pipe, &spd);
+}
+
+asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
+{
+ struct file *file;
+ long error;
+ int fput;
+
+ error = -EBADF;
+ file = fget_light(fd, &fput);
+ if (file) {
+ if (file->f_mode & FMODE_WRITE)
+ error = do_vmsplice(file, iov, nr_segs, flags);
+
+ fput_light(file, fput);
+ }
+
+ return error;
+}
+
+asmlinkage long sys_splice(int fd_in, loff_t __user *off_in,
+ int fd_out, loff_t __user *off_out,
+ size_t len, unsigned int flags)
{
long error;
struct file *in, *out;
@@ -645,13 +1266,15 @@ asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags)
return 0;
error = -EBADF;
- in = fget_light(fdin, &fput_in);
+ in = fget_light(fd_in, &fput_in);
if (in) {
if (in->f_mode & FMODE_READ) {
- out = fget_light(fdout, &fput_out);
+ out = fget_light(fd_out, &fput_out);
if (out) {
if (out->f_mode & FMODE_WRITE)
- error = do_splice(in, out, len, flags);
+ error = do_splice(in, off_in,
+ out, off_out,
+ len, flags);
fput_light(out, fput_out);
}
}
@@ -661,3 +1284,192 @@ asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags)
return error;
}
+
+/*
+ * Link contents of ipipe to opipe.
+ */
+static int link_pipe(struct pipe_inode_info *ipipe,
+ struct pipe_inode_info *opipe,
+ size_t len, unsigned int flags)
+{
+ struct pipe_buffer *ibuf, *obuf;
+ int ret, do_wakeup, i, ipipe_first;
+
+ ret = do_wakeup = ipipe_first = 0;
+
+ /*
+ * Potential ABBA deadlock, work around it by ordering lock
+ * grabbing by inode address. Otherwise two different processes
+ * could deadlock (one doing tee from A -> B, the other from B -> A).
+ */
+ if (ipipe->inode < opipe->inode) {
+ ipipe_first = 1;
+ mutex_lock(&ipipe->inode->i_mutex);
+ mutex_lock(&opipe->inode->i_mutex);
+ } else {
+ mutex_lock(&opipe->inode->i_mutex);
+ mutex_lock(&ipipe->inode->i_mutex);
+ }
+
+ for (i = 0;; i++) {
+ if (!opipe->readers) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+ break;
+ }
+ if (ipipe->nrbufs - i) {
+ ibuf = ipipe->bufs + ((ipipe->curbuf + i) & (PIPE_BUFFERS - 1));
+
+ /*
+ * If we have room, fill this buffer
+ */
+ if (opipe->nrbufs < PIPE_BUFFERS) {
+ int nbuf = (opipe->curbuf + opipe->nrbufs) & (PIPE_BUFFERS - 1);
+
+ /*
+ * Get a reference to this pipe buffer,
+ * so we can copy the contents over.
+ */
+ ibuf->ops->get(ipipe, ibuf);
+
+ obuf = opipe->bufs + nbuf;
+ *obuf = *ibuf;
+
+ if (obuf->len > len)
+ obuf->len = len;
+
+ opipe->nrbufs++;
+ do_wakeup = 1;
+ ret += obuf->len;
+ len -= obuf->len;
+
+ if (!len)
+ break;
+ if (opipe->nrbufs < PIPE_BUFFERS)
+ continue;
+ }
+
+ /*
+ * We have input available, but no output room.
+ * If we already copied data, return that. If we
+ * need to drop the opipe lock, it must be ordered
+ * last to avoid deadlocks.
+ */
+ if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&opipe->wait))
+ wake_up_interruptible(&opipe->wait);
+ kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN);
+ do_wakeup = 0;
+ }
+
+ opipe->waiting_writers++;
+ pipe_wait(opipe);
+ opipe->waiting_writers--;
+ continue;
+ }
+
+ /*
+ * No input buffers, do the usual checks for available
+ * writers and blocking and wait if necessary
+ */
+ if (!ipipe->writers)
+ break;
+ if (!ipipe->waiting_writers) {
+ if (ret)
+ break;
+ }
+ /*
+ * pipe_wait() drops the ipipe mutex. To avoid deadlocks
+ * with another process, we can only safely do that if
+ * the ipipe lock is ordered last.
+ */
+ if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ if (waitqueue_active(&ipipe->wait))
+ wake_up_interruptible_sync(&ipipe->wait);
+ kill_fasync(&ipipe->fasync_writers, SIGIO, POLL_OUT);
+
+ pipe_wait(ipipe);
+ }
+
+ mutex_unlock(&ipipe->inode->i_mutex);
+ mutex_unlock(&opipe->inode->i_mutex);
+
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&opipe->wait))
+ wake_up_interruptible(&opipe->wait);
+ kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN);
+ }
+
+ return ret;
+}
+
+/*
+ * This is a tee(1) implementation that works on pipes. It doesn't copy
+ * any data, it simply references the 'in' pages on the 'out' pipe.
+ * The 'flags' used are the SPLICE_F_* variants, currently the only
+ * applicable one is SPLICE_F_NONBLOCK.
+ */
+static long do_tee(struct file *in, struct file *out, size_t len,
+ unsigned int flags)
+{
+ struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe;
+ struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe;
+
+ /*
+ * Link ipipe to the two output pipes, consuming as we go along.
+ */
+ if (ipipe && opipe)
+ return link_pipe(ipipe, opipe, len, flags);
+
+ return -EINVAL;
+}
+
+asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags)
+{
+ struct file *in;
+ int error, fput_in;
+
+ if (unlikely(!len))
+ return 0;
+
+ error = -EBADF;
+ in = fget_light(fdin, &fput_in);
+ if (in) {
+ if (in->f_mode & FMODE_READ) {
+ int fput_out;
+ struct file *out = fget_light(fdout, &fput_out);
+
+ if (out) {
+ if (out->f_mode & FMODE_WRITE)
+ error = do_tee(in, out, len, flags);
+ fput_light(out, fput_out);
+ }
+ }
+ fput_light(in, fput_in);
+ }
+
+ return error;
+}
diff --git a/fs/sync.c b/fs/sync.c
index 8616006d2094..aab5ffe77e9f 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -61,7 +61,7 @@
* will be available after a crash.
*/
asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
- int flags)
+ unsigned int flags)
{
int ret;
struct file *file;
@@ -126,7 +126,7 @@ out:
* `endbyte' is inclusive
*/
int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
- int flags)
+ unsigned int flags)
{
int ret;
struct address_space *mapping;
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index f26880a4785e..610b5bdbe75b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -43,6 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
memset(sd, 0, sizeof(*sd));
atomic_set(&sd->s_count, 1);
+ atomic_set(&sd->s_event, 0);
INIT_LIST_HEAD(&sd->s_children);
list_add(&sd->s_sibling, &parent_sd->s_children);
sd->s_element = element;
@@ -50,7 +51,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
return sd;
}
-/**
+/*
*
* Return -EEXIST if there is already a sysfs element with the same name for
* the same parent.
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 830f76fa098c..cf3786625bfa 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -6,6 +6,7 @@
#include <linux/fsnotify.h>
#include <linux/kobject.h>
#include <linux/namei.h>
+#include <linux/poll.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -57,6 +58,7 @@ struct sysfs_buffer {
struct sysfs_ops * ops;
struct semaphore sem;
int needs_read_fill;
+ int event;
};
@@ -72,6 +74,7 @@ struct sysfs_buffer {
*/
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_ops * ops = buffer->ops;
@@ -83,6 +86,7 @@ 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);
buffer->needs_read_fill = 0;
BUG_ON(count > (ssize_t)PAGE_SIZE);
@@ -183,7 +187,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
return -ENOMEM;
if (count >= PAGE_SIZE)
- count = PAGE_SIZE;
+ count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
return error ? -EFAULT : count;
@@ -348,12 +352,84 @@ static int sysfs_release(struct inode * inode, struct file * filp)
return 0;
}
+/* Sysfs attribute files are pollable. The idea is that you read
+ * the content and then you use 'poll' or 'select' to wait for
+ * the content to change. When the content changes (assuming the
+ * manager for the kobject supports notification), poll will
+ * return POLLERR|POLLPRI, and select will return the fd whether
+ * it is waiting for read, write, or exceptions.
+ * Once poll/select indicates that the value has changed, you
+ * need to close and re-open the file, as simply seeking and reading
+ * again will not get new data, or reset the state of 'poll'.
+ * Reminder: this only works for attributes which actively support
+ * it, and it is not possible to test an attribute from userspace
+ * to see if it supports poll (Nether 'poll' or 'select' return
+ * an appropriate error code). When in doubt, set a suitable timeout value.
+ */
+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_dentry->d_parent);
+ struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
+ int res = 0;
+
+ poll_wait(filp, &kobj->poll, wait);
+
+ if (buffer->event != atomic_read(&sd->s_event)) {
+ res = POLLERR|POLLPRI;
+ buffer->needs_read_fill = 1;
+ }
+
+ return res;
+}
+
+
+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;
+}
+
+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);
+ wake_up_interruptible(&k->poll);
+ dput(de);
+ }
+}
+EXPORT_SYMBOL_GPL(sysfs_notify);
+
const struct file_operations sysfs_file_operations = {
.read = sysfs_read_file,
.write = sysfs_write_file,
.llseek = generic_file_llseek,
.open = sysfs_open_file,
.release = sysfs_release,
+ .poll = sysfs_poll,
};
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4c29ac41ac3e..f0b347bd12ca 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -175,8 +175,7 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
struct bin_attribute * bin_attr;
struct sysfs_symlink * sl;
- if (!sd || !sd->s_element)
- BUG();
+ BUG_ON(!sd || !sd->s_element);
switch (sd->s_type) {
case SYSFS_DIR:
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 32958a7c50e9..3651ffb5ec09 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -11,6 +11,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern void sysfs_hash_and_remove(struct dentry * dir, 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 *);
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 8c66e9270dd6..d7074341ee87 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -253,8 +253,7 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
lock_page(page);
err = mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
+ BUG_ON(err);
de->inode = 0;
err = dir_commit_chunk(page, from, to);
dir_put_page(page);
@@ -353,8 +352,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
lock_page(page);
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
+ BUG_ON(err);
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
err = dir_commit_chunk(page, from, to);
dir_put_page(page);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 81e0e8459af1..2983afd5e7fd 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -312,12 +312,10 @@ static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head
err = 0;
bh = inode_getblk(inode, block, &err, &phys, &new);
- if (bh)
- BUG();
+ BUG_ON(bh);
if (err)
goto abort;
- if (!phys)
- BUG();
+ BUG_ON(!phys);
if (new)
set_buffer_new(bh_result);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 6cbbd165c60d..4d191ef39b67 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -870,12 +870,14 @@ xfs_page_state_convert(
pgoff_t end_index, last_index, tlast;
ssize_t size, len;
int flags, err, iomap_valid = 0, uptodate = 1;
- int page_dirty, count = 0, trylock_flag = 0;
+ int page_dirty, count = 0;
+ int trylock = 0;
int all_bh = unmapped;
- /* wait for other IO threads? */
- if (startio && (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking))
- trylock_flag |= BMAPI_TRYLOCK;
+ if (startio) {
+ if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking)
+ trylock |= BMAPI_TRYLOCK;
+ }
/* Is this page beyond the end of the file? */
offset = i_size_read(inode);
@@ -956,15 +958,13 @@ xfs_page_state_convert(
if (buffer_unwritten(bh)) {
type = IOMAP_UNWRITTEN;
- flags = BMAPI_WRITE|BMAPI_IGNSTATE;
+ flags = BMAPI_WRITE | BMAPI_IGNSTATE;
} else if (buffer_delay(bh)) {
type = IOMAP_DELAY;
- flags = BMAPI_ALLOCATE;
- if (!startio)
- flags |= trylock_flag;
+ flags = BMAPI_ALLOCATE | trylock;
} else {
type = IOMAP_NEW;
- flags = BMAPI_WRITE|BMAPI_MMAP;
+ flags = BMAPI_WRITE | BMAPI_MMAP;
}
if (!iomap_valid) {
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 9fb0312665ca..26fed0756f01 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -182,7 +182,7 @@ free_address(
{
a_list_t *aentry;
- aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC & ~__GFP_HIGH);
+ aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
if (likely(aentry)) {
spin_lock(&as_lock);
aentry->next = as_free_head;
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 85997b1205f5..c847416f6d10 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -69,7 +69,6 @@ __xfs_file_read(
return rval;
}
-
STATIC ssize_t
xfs_file_aio_read(
struct kiocb *iocb,
@@ -90,7 +89,6 @@ xfs_file_aio_read_invis(
return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
}
-
STATIC inline ssize_t
__xfs_file_write(
struct kiocb *iocb,
@@ -113,7 +111,6 @@ __xfs_file_write(
return rval;
}
-
STATIC ssize_t
xfs_file_aio_write(
struct kiocb *iocb,
@@ -134,7 +131,6 @@ xfs_file_aio_write_invis(
return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
}
-
STATIC inline ssize_t
__xfs_file_readv(
struct file *file,
@@ -179,7 +175,6 @@ xfs_file_readv_invis(
return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
}
-
STATIC inline ssize_t
__xfs_file_writev(
struct file *file,
@@ -204,7 +199,6 @@ __xfs_file_writev(
return rval;
}
-
STATIC ssize_t
xfs_file_writev(
struct file *file,
@@ -228,7 +222,7 @@ xfs_file_writev_invis(
STATIC ssize_t
xfs_file_sendfile(
struct file *filp,
- loff_t *ppos,
+ loff_t *pos,
size_t count,
read_actor_t actor,
void *target)
@@ -236,10 +230,84 @@ xfs_file_sendfile(
vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
ssize_t rval;
- VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
+ VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_sendfile_invis(
+ struct file *filp,
+ loff_t *pos,
+ size_t count,
+ read_actor_t actor,
+ void *target)
+{
+ vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read(
+ struct file *infilp,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read_invis(
+ struct file *infilp,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval);
return rval;
}
+STATIC ssize_t
+xfs_file_splice_write(
+ struct pipe_inode_info *pipe,
+ struct file *outfilp,
+ loff_t *ppos,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write_invis(
+ struct pipe_inode_info *pipe,
+ struct file *outfilp,
+ loff_t *ppos,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval);
+ return rval;
+}
STATIC int
xfs_file_open(
@@ -251,13 +319,10 @@ xfs_file_open(
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG;
-
- ASSERT(vp);
VOP_OPEN(vp, NULL, error);
return -error;
}
-
STATIC int
xfs_file_release(
struct inode *inode,
@@ -271,7 +336,6 @@ xfs_file_release(
return -error;
}
-
STATIC int
xfs_file_fsync(
struct file *filp,
@@ -285,21 +349,11 @@ xfs_file_fsync(
if (datasync)
flags |= FSYNC_DATA;
-
- ASSERT(vp);
VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
return -error;
}
-/*
- * xfs_file_readdir maps to VOP_READDIR().
- * We need to build a uio, cred, ...
- */
-
-#define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
-
#ifdef CONFIG_XFS_DMAPI
-
STATIC struct page *
xfs_vm_nopage(
struct vm_area_struct *area,
@@ -319,10 +373,8 @@ xfs_vm_nopage(
return filemap_nopage(area, address, type);
}
-
#endif /* CONFIG_XFS_DMAPI */
-
STATIC int
xfs_file_readdir(
struct file *filp,
@@ -330,7 +382,7 @@ xfs_file_readdir(
filldir_t filldir)
{
int error = 0;
- vnode_t *vp;
+ vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
uio_t uio;
iovec_t iov;
int eof = 0;
@@ -340,9 +392,6 @@ xfs_file_readdir(
xfs_off_t start_offset, curr_offset;
xfs_dirent_t *dbp = NULL;
- vp = vn_from_inode(filp->f_dentry->d_inode);
- ASSERT(vp);
-
/* Try fairly hard to get memory */
do {
if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
@@ -387,7 +436,7 @@ xfs_file_readdir(
}
size -= dbp->d_reclen;
curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
- dbp = nextdp(dbp);
+ dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
}
}
done:
@@ -402,7 +451,6 @@ done:
return -error;
}
-
STATIC int
xfs_file_mmap(
struct file *filp,
@@ -457,11 +505,10 @@ xfs_file_ioctl_invis(
unsigned int cmd,
unsigned long arg)
{
- int error;
struct inode *inode = filp->f_dentry->d_inode;
vnode_t *vp = vn_from_inode(inode);
+ int error;
- ASSERT(vp);
VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
VMODIFY(vp);
@@ -537,6 +584,8 @@ const struct file_operations xfs_file_operations = {
.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,
#ifdef CONFIG_COMPAT
.compat_ioctl = xfs_file_compat_ioctl,
@@ -558,7 +607,9 @@ const struct file_operations xfs_invis_file_operations = {
.writev = xfs_file_writev_invis,
.aio_read = xfs_file_aio_read_invis,
.aio_write = xfs_file_aio_write_invis,
- .sendfile = xfs_file_sendfile,
+ .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,
#ifdef CONFIG_COMPAT
.compat_ioctl = xfs_file_compat_invis_ioctl,
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 149237304fb6..2e2e275c786f 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -673,8 +673,7 @@ xfs_vn_setattr(
if (ia_valid & ATTR_ATIME) {
vattr.va_mask |= XFS_AT_ATIME;
vattr.va_atime = attr->ia_atime;
- if (ia_valid & ATTR_ATIME_SET)
- inode->i_atime = attr->ia_atime;
+ inode->i_atime = attr->ia_atime;
}
if (ia_valid & ATTR_MTIME) {
vattr.va_mask |= XFS_AT_MTIME;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 1fe09f2d6519..e9fe43d74768 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -103,6 +103,7 @@
*/
#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 */
#else
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 84ddf1893894..67efe3308980 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -301,36 +301,23 @@ xfs_sendfile(
void *target,
cred_t *credp)
{
+ xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
- xfs_fsize_t n;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- vnode_t *vp;
-
- ip = XFS_BHVTOI(bdp);
- vp = BHV_TO_VNODE(bdp);
- mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls);
-
- n = XFS_MAXIOFFSET(mp) - *offset;
- if ((n <= 0) || (count == 0))
- return 0;
-
- if (n < count)
- count = n;
-
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
+ if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
(!(ioflags & IO_INVIS))) {
vrwlock_t locktype = VRWLOCK_READ;
int error;
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count,
+ 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);
@@ -340,12 +327,98 @@ xfs_sendfile(
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,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t count,
+ int flags,
+ int ioflags,
+ 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(ip->i_mount))
+ 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))) {
+ vrwlock_t locktype = VRWLOCK_READ;
+ int error;
+
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+ *ppos, count,
+ FILP_DELAY_FLAG(infilp), &locktype);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return -error;
+ }
+ }
+ xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
+ pipe, count, *ppos, ioflags);
+ ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret);
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return ret;
+}
+
+ssize_t
+xfs_splice_write(
+ bhv_desc_t *bdp,
+ struct pipe_inode_info *pipe,
+ struct file *outfilp,
+ loff_t *ppos,
+ size_t count,
+ int flags,
+ int ioflags,
+ cred_t *credp)
+{
+ xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ xfs_mount_t *mp = ip->i_mount;
+ ssize_t ret;
+
+ XFS_STATS_INC(xs_write_calls);
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -EIO;
+
+ xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+ if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
+ (!(ioflags & IO_INVIS))) {
+ vrwlock_t locktype = VRWLOCK_WRITE;
+ int error;
+
+ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
+ *ppos, count,
+ FILP_DELAY_FLAG(outfilp), &locktype);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ return -error;
+ }
+ }
+ xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
+ pipe, count, *ppos, ioflags);
+ ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
+ if (ret > 0)
+ XFS_STATS_ADD(xs_write_bytes, ret);
+
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return ret;
}
@@ -363,7 +436,7 @@ xfs_zero_last_block(
xfs_fsize_t end_size)
{
xfs_fileoff_t last_fsb;
- xfs_mount_t *mp;
+ xfs_mount_t *mp = io->io_mount;
int nimaps;
int zero_offset;
int zero_len;
@@ -373,8 +446,6 @@ xfs_zero_last_block(
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
- mp = io->io_mount;
-
zero_offset = XFS_B_FSB_OFFSET(mp, isize);
if (zero_offset == 0) {
/*
@@ -405,10 +476,9 @@ xfs_zero_last_block(
* don't deadlock when the buffer cache calls back to us.
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
- loff = XFS_FSB_TO_B(mp, last_fsb);
+ loff = XFS_FSB_TO_B(mp, last_fsb);
zero_len = mp->m_sb.sb_blocksize - zero_offset;
-
error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
@@ -441,7 +511,7 @@ xfs_zero_eof(
xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb;
xfs_extlen_t buf_len_fsb;
- xfs_mount_t *mp;
+ xfs_mount_t *mp = io->io_mount;
int nimaps;
int error = 0;
xfs_bmbt_irec_t imap;
@@ -450,8 +520,6 @@ xfs_zero_eof(
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
ASSERT(offset > isize);
- mp = io->io_mount;
-
/*
* First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially.
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 38864a88d42d..8f4539952350 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -60,6 +60,8 @@ struct xfs_iomap;
#define XFS_IOMAP_ALLOC_ENTER 25
#define XFS_IOMAP_ALLOC_MAP 26
#define XFS_IOMAP_UNWRITTEN 27
+#define XFS_SPLICE_READ_ENTER 28
+#define XFS_SPLICE_WRITE_ENTER 29
extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
void *, size_t, loff_t, int);
extern void xfs_inval_cached_trace(struct xfs_iocore *,
@@ -78,6 +80,7 @@ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
extern int xfs_bdstrat_cb(struct xfs_buf *);
+extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t, xfs_fsize_t);
@@ -90,7 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
loff_t *, int, size_t, read_actor_t,
void *, struct cred *);
-
-extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, int, int,
+ struct cred *);
+extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
+ struct file *, loff_t *, size_t, int, int,
+ struct cred *);
#endif /* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 1884300417e3..68f4793e8a11 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -67,7 +67,8 @@ mempool_t *xfs_ioend_pool;
STATIC struct xfs_mount_args *
xfs_args_allocate(
- struct super_block *sb)
+ struct super_block *sb,
+ int silent)
{
struct xfs_mount_args *args;
@@ -80,8 +81,8 @@ xfs_args_allocate(
args->flags |= XFSMNT_DIRSYNC;
if (sb->s_flags & MS_SYNCHRONOUS)
args->flags |= XFSMNT_WSYNC;
-
- /* Default to 32 bit inodes on Linux all the time */
+ if (silent)
+ args->flags |= XFSMNT_QUIET;
args->flags |= XFSMNT_32BITINODES;
return args;
@@ -719,7 +720,7 @@ xfs_fs_remount(
char *options)
{
vfs_t *vfsp = vfs_from_sb(sb);
- struct xfs_mount_args *args = xfs_args_allocate(sb);
+ struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
int error;
VFS_PARSEARGS(vfsp, options, args, 1, error);
@@ -825,7 +826,7 @@ xfs_fs_fill_super(
{
vnode_t *rootvp;
struct vfs *vfsp = vfs_allocate(sb);
- struct xfs_mount_args *args = xfs_args_allocate(sb);
+ struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
struct kstatfs statvfs;
int error, error2;
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 06f5845e9568..2a8e16c22353 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -173,6 +173,12 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
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 *);
+typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
+ struct file *, loff_t *, size_t, int, int,
+ struct cred *);
typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
int, unsigned int, void __user *);
typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -231,6 +237,8 @@ typedef struct vnodeops {
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;
vop_getattr_t vop_getattr;
vop_setattr_t vop_setattr;
@@ -276,6 +284,10 @@ typedef struct vnodeops {
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \
rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
+#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \
+ rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
+#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \
+ rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
#define VOP_BMAP(vp,of,sz,rw,b,n,rv) \
rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
#define VOP_OPEN(vp, cr, rv) \
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 73c1e5e80c07..7fb5eca9bd50 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve(
{
int error;
xfs_mount_t *mp;
- uint delblks, blkflags;
+ uint delblks, blkflags, prjflags = 0;
xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve(
}
}
if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
- if ((XFS_IS_GQUOTA_ON(ip->i_mount) &&
- ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) ||
- (XFS_IS_PQUOTA_ON(ip->i_mount) &&
- ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
+ if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
+ ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+ prjflags = XFS_QMOPT_ENOSPC;
+
+ if (prjflags ||
+ (XFS_IS_GQUOTA_ON(ip->i_mount) &&
+ ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
delblksgdq = gdqp;
if (delblks) {
ASSERT(ip->i_gdquot);
@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve(
if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
- flags | blkflags)))
+ flags | blkflags | prjflags)))
return (error);
/*
@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve(
ASSERT(unresudq || unresgdq);
if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
- flags | blkflags)))
+ flags | blkflags | prjflags)))
return (error);
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index d8e131ec0aa8..9168918db252 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots(
}
}
+STATIC int
+xfs_quota_error(uint flags)
+{
+ if (flags & XFS_QMOPT_ENOSPC)
+ return ENOSPC;
+ return EDQUOT;
+}
+
/*
* This reserves disk blocks and inodes against a dquot.
* Flags indicate if the dquot is to be locked here and also
* if the blk reservation is for RT or regular blocks.
* Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
- * Returns EDQUOT if quota is exceeded.
*/
STATIC int
xfs_trans_dqresv(
@@ -666,19 +673,15 @@ xfs_trans_dqresv(
*/
if (hardlimit > 0ULL &&
(hardlimit <= nblks + *resbcountp)) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
}
if (softlimit > 0ULL &&
(softlimit <= nblks + *resbcountp)) {
- /*
- * If timer or warnings has expired,
- * return EDQUOT
- */
if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
}
}
@@ -695,16 +698,12 @@ xfs_trans_dqresv(
if (!softlimit)
softlimit = q->qi_isoftlimit;
if (hardlimit > 0ULL && count >= hardlimit) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
} else if (softlimit > 0ULL && count >= softlimit) {
- /*
- * If timer or warnings has expired,
- * return EDQUOT
- */
if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
}
}
@@ -751,13 +750,14 @@ error_return:
/*
- * Given a dquot(s), make disk block and/or inode reservations against them.
+ * Given dquot(s), make disk block and/or inode reservations against them.
* The fact that this does the reservation against both the usr and
- * grp quotas is important, because this follows a both-or-nothing
+ * grp/prj quotas is important, because this follows a both-or-nothing
* approach.
*
* flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
* XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
+ * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota.
* XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
* XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
* dquots are unlocked on return, if they were not locked by caller.
@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots(
long ninos,
uint flags)
{
- int resvd;
+ int resvd = 0, error;
- if (! XFS_IS_QUOTA_ON(mp))
- return (0);
+ if (!XFS_IS_QUOTA_ON(mp))
+ return 0;
if (tp && tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp);
ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
- resvd = 0;
if (udqp) {
- if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
- return (EDQUOT);
+ error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
+ (flags & ~XFS_QMOPT_ENOSPC));
+ if (error)
+ return error;
resvd = 1;
}
if (gdqp) {
- if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
+ error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
+ if (error) {
/*
* can't do it, so backout previous reservation
*/
@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots(
xfs_trans_dqresv(tp, mp, udqp,
-nblks, -ninos, flags);
}
- return (EDQUOT);
+ return error;
}
}
/*
* Didn't change anything critical, so, no need to log
*/
- return (0);
+ return 0;
}
@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots(
* Lock the dquot and change the reservation if we can.
* This doesn't change the actual usage, just the reservation.
* The inode sent in is locked.
- *
- * Returns 0 on success, EDQUOT or other errors otherwise
*/
STATIC int
xfs_trans_reserve_quota_nblks(
@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks(
xfs_inode_t *ip,
long nblks,
long ninos,
- uint type)
+ uint flags)
{
int error;
if (!XFS_IS_QUOTA_ON(mp))
- return (0);
+ return 0;
+ if (XFS_IS_PQUOTA_ON(mp))
+ flags |= XFS_QMOPT_ENOSPC;
ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
- ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
- (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);
+ ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+ XFS_TRANS_DQ_RES_RTBLKS ||
+ (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+ XFS_TRANS_DQ_RES_BLKS);
/*
* Reserve nblks against these dquots, with trans as the mediator.
@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks(
error = xfs_trans_reserve_quota_bydquots(tp, mp,
ip->i_udquot, ip->i_gdquot,
nblks, ninos,
- type);
- return (error);
+ flags);
+ return error;
}
/*
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index d384e489705f..26939d364bc4 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4719,18 +4719,17 @@ xfs_bmapi(
/*
* Make a transaction-less quota reservation for
* delayed allocation blocks. This number gets
- * adjusted later.
- * We return EDQUOT if we haven't allocated
- * blks already inside this loop;
+ * adjusted later. We return if we haven't
+ * allocated blocks already inside this loop.
*/
- if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+ if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
mp, NULL, ip, (long)alen, 0,
rt ? XFS_QMOPT_RES_RTBLKS :
- XFS_QMOPT_RES_REGBLKS)) {
+ XFS_QMOPT_RES_REGBLKS))) {
if (n == 0) {
*nmap = 0;
ASSERT(cur == NULL);
- return XFS_ERROR(EDQUOT);
+ return error;
}
break;
}
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index f83399c89ce3..8e0d73d9ccc4 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -353,10 +353,11 @@ xfs_check_nostate_extents(
xfs_extnum_t num);
/*
- * Call xfs_bmap_do_search_extents() to search for the extent
- * record containing block bno. If in multi-level in-core extent
- * allocation mode, find and extract the target extent buffer,
- * otherwise just use the direct extent list.
+ * Search the extent records for the entry containing block bno.
+ * If bno lies in a hole, point to the next entry. If bno lies
+ * past eof, *eofp will be set, and *prevp will contain the last
+ * entry (null if none). Else, *lastxp will be set to the index
+ * of the found entry; *gotp will contain the entry.
*/
xfs_bmbt_rec_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 022fff62085b..5b7eb81453be 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -68,6 +68,7 @@ struct xfs_mount_args {
* enforcement */
#define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit
* enforcement */
+#define XFSMNT_QUIET 0x00000080 /* don't report mount errors */
#define XFSMNT_NOALIGN 0x00000200 /* don't allocate at
* stripe boundaries*/
#define XFSMNT_RETERR 0x00000400 /* return error to user */
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 26b8e709a569..bc43163456ef 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -186,4 +186,7 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args)
+#define xfs_fs_mount_cmn_err(f, fmt, args...) \
+ ((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
+
#endif /* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 4eeb856183b1..deddbd03c166 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -158,9 +158,10 @@ xfs_ialloc_ag_alloc(
*/
agi = XFS_BUF_TO_AGI(agbp);
newino = be32_to_cpu(agi->agi_newino);
- if(likely(newino != NULLAGINO)) {
- args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
- XFS_IALLOC_BLOCKS(args.mp);
+ args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
+ XFS_IALLOC_BLOCKS(args.mp);
+ if (likely(newino != NULLAGINO &&
+ (args.agbno < be32_to_cpu(agi->agi_length)))) {
args.fsbno = XFS_AGB_TO_FSB(args.mp,
be32_to_cpu(agi->agi_seqno), args.agbno);
args.type = XFS_ALLOCTYPE_THIS_BNO;
@@ -182,8 +183,8 @@ xfs_ialloc_ag_alloc(
* Set the alignment for the allocation.
* If stripe alignment is turned on then align at stripe unit
* boundary.
- * If the cluster size is smaller than a filesystem block
- * then we're doing I/O for inodes in filesystem block size
+ * If the cluster size is smaller than a filesystem block
+ * then we're doing I/O for inodes in filesystem block size
* pieces, so don't need alignment anyway.
*/
isaligned = 0;
@@ -192,7 +193,7 @@ xfs_ialloc_ag_alloc(
args.alignment = args.mp->m_dalign;
isaligned = 1;
} else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
- args.mp->m_sb.sb_inoalignmt >=
+ args.mp->m_sb.sb_inoalignmt >=
XFS_B_TO_FSBT(args.mp,
XFS_INODE_CLUSTER_SIZE(args.mp)))
args.alignment = args.mp->m_sb.sb_inoalignmt;
@@ -220,7 +221,7 @@ xfs_ialloc_ag_alloc(
if ((error = xfs_alloc_vextent(&args)))
return error;
}
-
+
/*
* If stripe alignment is turned on, then try again with cluster
* alignment.
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index bb33113eef9f..b53854325266 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -421,7 +421,10 @@ finish_inode:
ip->i_chash = chlnew;
chlnew->chl_ip = ip;
chlnew->chl_blkno = ip->i_blkno;
+ if (ch->ch_list)
+ ch->ch_list->chl_prev = chlnew;
chlnew->chl_next = ch->ch_list;
+ chlnew->chl_prev = NULL;
ch->ch_list = chlnew;
chlnew = NULL;
}
@@ -723,23 +726,15 @@ xfs_iextract(
ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
ASSERT(ip->i_chash != NULL);
chm=NULL;
- for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
- if (chl->chl_blkno == ip->i_blkno) {
- if (chm == NULL) {
- /* first item on the list */
- ch->ch_list = chl->chl_next;
- } else {
- chm->chl_next = chl->chl_next;
- }
- kmem_zone_free(xfs_chashlist_zone, chl);
- break;
- } else {
- ASSERT(chl->chl_ip != ip);
- chm = chl;
- }
- }
- ASSERT_ALWAYS(chl != NULL);
- } else {
+ chl = ip->i_chash;
+ if (chl->chl_prev)
+ chl->chl_prev->chl_next = chl->chl_next;
+ else
+ ch->ch_list = chl->chl_next;
+ if (chl->chl_next)
+ chl->chl_next->chl_prev = chl->chl_prev;
+ kmem_zone_free(xfs_chashlist_zone, chl);
+ } else {
/* delete one inode from a non-empty list */
iq = ip->i_cnext;
iq->i_cprev = ip->i_cprev;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 48146bdc6bdd..94b60dd03801 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2732,16 +2732,29 @@ xfs_iunpin(
ASSERT(atomic_read(&ip->i_pincount) > 0);
if (atomic_dec_and_test(&ip->i_pincount)) {
- vnode_t *vp = XFS_ITOV_NULL(ip);
+ /*
+ * If the inode is currently being reclaimed, the
+ * linux inode _and_ the xfs vnode may have been
+ * freed so we cannot reference either of them safely.
+ * Hence we should not try to do anything to them
+ * if the xfs inode is currently in the reclaim
+ * path.
+ *
+ * However, we still need to issue the unpin wakeup
+ * call as the inode reclaim may be blocked waiting for
+ * the inode to become unpinned.
+ */
+ if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
+ vnode_t *vp = XFS_ITOV_NULL(ip);
- /* make sync come back and flush this inode */
- if (vp) {
- struct inode *inode = vn_to_inode(vp);
+ /* make sync come back and flush this inode */
+ if (vp) {
+ struct inode *inode = vn_to_inode(vp);
- if (!(inode->i_state & I_NEW))
- mark_inode_dirty_sync(inode);
+ if (!(inode->i_state & I_NEW))
+ mark_inode_dirty_sync(inode);
+ }
}
-
wake_up(&ip->i_ipin_wait);
}
}
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 39ef9c36ea55..3b544db1790b 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -189,6 +189,7 @@ typedef struct xfs_ihash {
*/
typedef struct xfs_chashlist {
struct xfs_chashlist *chl_next;
+ struct xfs_chashlist *chl_prev;
struct xfs_inode *chl_ip;
xfs_daddr_t chl_blkno; /* starting block number of
* the cluster */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 72e7e78bfff8..c0b1c2906880 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -213,7 +213,8 @@ xfs_mount_free(
STATIC int
xfs_mount_validate_sb(
xfs_mount_t *mp,
- xfs_sb_t *sbp)
+ xfs_sb_t *sbp,
+ int flags)
{
/*
* If the log device and data device have the
@@ -223,33 +224,29 @@ xfs_mount_validate_sb(
* a volume filesystem in a non-volume manner.
*/
if (sbp->sb_magicnum != XFS_SB_MAGIC) {
- cmn_err(CE_WARN, "XFS: bad magic number");
+ xfs_fs_mount_cmn_err(flags, "bad magic number");
return XFS_ERROR(EWRONGFS);
}
if (!XFS_SB_GOOD_VERSION(sbp)) {
- cmn_err(CE_WARN, "XFS: bad version");
+ xfs_fs_mount_cmn_err(flags, "bad version");
return XFS_ERROR(EWRONGFS);
}
if (unlikely(
sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
- cmn_err(CE_WARN,
- "XFS: filesystem is marked as having an external log; "
- "specify logdev on the\nmount command line.");
- XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)",
- XFS_ERRLEVEL_HIGH, mp, sbp);
- return XFS_ERROR(EFSCORRUPTED);
+ xfs_fs_mount_cmn_err(flags,
+ "filesystem is marked as having an external log; "
+ "specify logdev on the\nmount command line.");
+ return XFS_ERROR(EINVAL);
}
if (unlikely(
sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
- cmn_err(CE_WARN,
- "XFS: filesystem is marked as having an internal log; "
- "don't specify logdev on\nthe mount command line.");
- XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)",
- XFS_ERRLEVEL_HIGH, mp, sbp);
- return XFS_ERROR(EFSCORRUPTED);
+ xfs_fs_mount_cmn_err(flags,
+ "filesystem is marked as having an internal log; "
+ "do not specify logdev on\nthe mount command line.");
+ return XFS_ERROR(EINVAL);
}
/*
@@ -273,10 +270,8 @@ xfs_mount_validate_sb(
(sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) ||
(sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
(sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
- (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) {
- cmn_err(CE_WARN, "XFS: SB sanity check 1 failed");
- XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)",
- XFS_ERRLEVEL_LOW, mp, sbp);
+ (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
+ xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
return XFS_ERROR(EFSCORRUPTED);
}
@@ -289,9 +284,7 @@ xfs_mount_validate_sb(
(xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
- cmn_err(CE_WARN, "XFS: SB sanity check 2 failed");
- XFS_ERROR_REPORT("xfs_mount_validate_sb(4)",
- XFS_ERRLEVEL_LOW, mp);
+ xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
return XFS_ERROR(EFSCORRUPTED);
}
@@ -307,15 +300,13 @@ xfs_mount_validate_sb(
(sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
(sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
#endif
- cmn_err(CE_WARN,
- "XFS: File system is too large to be mounted on this system.");
+ xfs_fs_mount_cmn_err(flags,
+ "file system too large to be mounted on this system.");
return XFS_ERROR(E2BIG);
}
if (unlikely(sbp->sb_inprogress)) {
- cmn_err(CE_WARN, "XFS: file system busy");
- XFS_ERROR_REPORT("xfs_mount_validate_sb(5)",
- XFS_ERRLEVEL_LOW, mp);
+ xfs_fs_mount_cmn_err(flags, "file system busy");
return XFS_ERROR(EFSCORRUPTED);
}
@@ -323,8 +314,8 @@ xfs_mount_validate_sb(
* Version 1 directory format has never worked on Linux.
*/
if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
- cmn_err(CE_WARN,
- "XFS: Attempted to mount file system using version 1 directory format");
+ xfs_fs_mount_cmn_err(flags,
+ "file system using version 1 directory format");
return XFS_ERROR(ENOSYS);
}
@@ -332,11 +323,11 @@ xfs_mount_validate_sb(
* Until this is fixed only page-sized or smaller data blocks work.
*/
if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
- cmn_err(CE_WARN,
- "XFS: Attempted to mount file system with blocksize %d bytes",
+ xfs_fs_mount_cmn_err(flags,
+ "file system with blocksize %d bytes",
sbp->sb_blocksize);
- cmn_err(CE_WARN,
- "XFS: Only page-sized (%ld) or less blocksizes currently work.",
+ xfs_fs_mount_cmn_err(flags,
+ "only pagesize (%ld) or less will currently work.",
PAGE_SIZE);
return XFS_ERROR(ENOSYS);
}
@@ -484,7 +475,7 @@ xfs_xlatesb(
* Does the initial read of the superblock.
*/
int
-xfs_readsb(xfs_mount_t *mp)
+xfs_readsb(xfs_mount_t *mp, int flags)
{
unsigned int sector_size;
unsigned int extra_flags;
@@ -506,7 +497,7 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) {
- cmn_err(CE_WARN, "XFS: SB read failed");
+ xfs_fs_mount_cmn_err(flags, "SB read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail;
}
@@ -520,9 +511,9 @@ xfs_readsb(xfs_mount_t *mp)
sbp = XFS_BUF_TO_SBP(bp);
xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
- error = xfs_mount_validate_sb(mp, &(mp->m_sb));
+ error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
if (error) {
- cmn_err(CE_WARN, "XFS: SB validate failed");
+ xfs_fs_mount_cmn_err(flags, "SB validate failed");
goto fail;
}
@@ -530,8 +521,8 @@ xfs_readsb(xfs_mount_t *mp)
* We must be able to do sector-sized and sector-aligned IO.
*/
if (sector_size > mp->m_sb.sb_sectsize) {
- cmn_err(CE_WARN,
- "XFS: device supports only %u byte sectors (not %u)",
+ xfs_fs_mount_cmn_err(flags,
+ "device supports only %u byte sectors (not %u)",
sector_size, mp->m_sb.sb_sectsize);
error = ENOSYS;
goto fail;
@@ -548,7 +539,7 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) {
- cmn_err(CE_WARN, "XFS: SB re-read failed");
+ xfs_fs_mount_cmn_err(flags, "SB re-read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail;
}
@@ -678,7 +669,7 @@ xfs_mountfs(
int error = 0;
if (mp->m_sb_bp == NULL) {
- if ((error = xfs_readsb(mp))) {
+ if ((error = xfs_readsb(mp, mfsi_flags))) {
return error;
}
}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 66cbee79864e..668ad23fd37c 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -510,9 +510,12 @@ xfs_preferred_iosize(xfs_mount_t *mp)
*/
#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */
#define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */
+/* XFS_MFSI_RRINODES */
#define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */
/* log recovery */
#define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */
+/* XFS_MFSI_CONVERT_SUNIT */
+#define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */
/*
* Macros for getting from mount to vfs and back.
@@ -581,7 +584,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
uint, int);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
-extern int xfs_readsb(xfs_mount_t *mp);
+extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 4f6a034de7f7..7fbef974bce6 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */
#define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */
#define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */
-#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */
+#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */
#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */
-#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */
#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */
+#define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */
/*
* flags to xfs_trans_mod_dquot to indicate which field needs to be
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 504d2a80747a..f0e09ca14139 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -442,6 +442,9 @@ xfs_mount(
p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+ if (args->flags & XFSMNT_QUIET)
+ flags |= XFS_MFSI_QUIET;
+
/*
* Open real time and log devices - order is important.
*/
@@ -492,7 +495,7 @@ xfs_mount(
error = xfs_start_flags(vfsp, args, mp);
if (error)
goto error1;
- error = xfs_readsb(mp);
+ error = xfs_readsb(mp, flags);
if (error)
goto error1;
error = xfs_finish_flags(vfsp, args, mp);
@@ -1697,8 +1700,9 @@ xfs_parseargs(
int dsunit, dswidth, vol_dsunit, vol_dswidth;
int iosize;
- args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
args->flags |= XFSMNT_IDELETE;
+ args->flags |= XFSMNT_BARRIER;
+ args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
if (!options)
goto done;
@@ -1947,8 +1951,6 @@ xfs_showargs(
seq_printf(m, "," MNTOPT_IKEEP);
if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
seq_printf(m, "," MNTOPT_LARGEIO);
- if (mp->m_flags & XFS_MOUNT_BARRIER)
- seq_printf(m, "," MNTOPT_BARRIER);
if (!(vfsp->vfs_flag & VFS_32BITINODES))
seq_printf(m, "," MNTOPT_64BITINODE);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de49601919c1..fa71b305ba5c 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -4649,6 +4649,10 @@ vnodeops_t xfs_vnodeops = {
#ifdef HAVE_SENDFILE
.vop_sendfile = xfs_sendfile,
#endif
+#ifdef HAVE_SPLICE
+ .vop_splice_read = xfs_splice_read,
+ .vop_splice_write = xfs_splice_write,
+#endif
.vop_write = xfs_write,
.vop_ioctl = xfs_ioctl,
.vop_getattr = xfs_getattr,
diff --git a/include/asm-alpha/numnodes.h b/include/asm-alpha/numnodes.h
deleted file mode 100644
index cd425827e4f3..000000000000
--- a/include/asm-alpha/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 128 Nodes - Marvel */
-#define NODES_SHIFT 7
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
new file mode 100644
index 000000000000..f28636d61e39
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
@@ -0,0 +1,104 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * MultiMedia Card Interface (MCI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_MCI_H
+#define AT91RM9200_MCI_H
+
+#define AT91_MCI_CR 0x00 /* Control Register */
+#define AT91_MCI_MCIEN (1 << 0) /* Multi-Media Interface Enable */
+#define AT91_MCI_MCIDIS (1 << 1) /* Multi-Media Interface Disable */
+#define AT91_MCI_PWSEN (1 << 2) /* Power Save Mode Enable */
+#define AT91_MCI_PWSDIS (1 << 3) /* Power Save Mode Disable */
+#define AT91_MCI_SWRST (1 << 7) /* Software Reset */
+
+#define AT91_MCI_MR 0x04 /* Mode Register */
+#define AT91_MCI_CLKDIV (0xff << 0) /* Clock Divider */
+#define AT91_MCI_PWSDIV (3 << 8) /* Power Saving Divider */
+#define AT91_MCI_PDCPADV (1 << 14) /* PDC Padding Value */
+#define AT91_MCI_PDCMODE (1 << 15) /* PDC-orientated Mode */
+#define AT91_MCI_BLKLEN (0xfff << 18) /* Data Block Length */
+
+#define AT91_MCI_DTOR 0x08 /* Data Timeout Register */
+#define AT91_MCI_DTOCYC (0xf << 0) /* Data Timeout Cycle Number */
+#define AT91_MCI_DTOMUL (7 << 4) /* Data Timeout Multiplier */
+#define AT91_MCI_DTOMUL_1 (0 << 4)
+#define AT91_MCI_DTOMUL_16 (1 << 4)
+#define AT91_MCI_DTOMUL_128 (2 << 4)
+#define AT91_MCI_DTOMUL_256 (3 << 4)
+#define AT91_MCI_DTOMUL_1K (4 << 4)
+#define AT91_MCI_DTOMUL_4K (5 << 4)
+#define AT91_MCI_DTOMUL_64K (6 << 4)
+#define AT91_MCI_DTOMUL_1M (7 << 4)
+
+#define AT91_MCI_SDCR 0x0c /* SD Card Register */
+#define AT91_MCI_SDCSEL (0xf << 0) /* SD Card Selector */
+#define AT91_MCI_SDCBUS (1 << 7) /* 1-bit or 4-bit bus */
+
+#define AT91_MCI_ARGR 0x10 /* Argument Register */
+
+#define AT91_MCI_CMDR 0x14 /* Command Register */
+#define AT91_MCI_CMDNB (0x3f << 0) /* Command Number */
+#define AT91_MCI_RSPTYP (3 << 6) /* Response Type */
+#define AT91_MCI_RSPTYP_NONE (0 << 6)
+#define AT91_MCI_RSPTYP_48 (1 << 6)
+#define AT91_MCI_RSPTYP_136 (2 << 6)
+#define AT91_MCI_SPCMD (7 << 8) /* Special Command */
+#define AT91_MCI_SPCMD_NONE (0 << 8)
+#define AT91_MCI_SPCMD_INIT (1 << 8)
+#define AT91_MCI_SPCMD_SYNC (2 << 8)
+#define AT91_MCI_SPCMD_ICMD (4 << 8)
+#define AT91_MCI_SPCMD_IRESP (5 << 8)
+#define AT91_MCI_OPDCMD (1 << 11) /* Open Drain Command */
+#define AT91_MCI_MAXLAT (1 << 12) /* Max Latency for Command to Response */
+#define AT91_MCI_TRCMD (3 << 16) /* Transfer Command */
+#define AT91_MCI_TRCMD_NONE (0 << 16)
+#define AT91_MCI_TRCMD_START (1 << 16)
+#define AT91_MCI_TRCMD_STOP (2 << 16)
+#define AT91_MCI_TRDIR (1 << 18) /* Transfer Direction */
+#define AT91_MCI_TRTYP (3 << 19) /* Transfer Type */
+#define AT91_MCI_TRTYP_BLOCK (0 << 19)
+#define AT91_MCI_TRTYP_MULTIPLE (1 << 19)
+#define AT91_MCI_TRTYP_STREAM (2 << 19)
+
+#define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */
+#define AT91_MCR_RDR 0x30 /* Receive Data Register */
+#define AT91_MCR_TDR 0x34 /* Transmit Data Register */
+
+#define AT91_MCI_SR 0x40 /* Status Register */
+#define AT91_MCI_CMDRDY (1 << 0) /* Command Ready */
+#define AT91_MCI_RXRDY (1 << 1) /* Receiver Ready */
+#define AT91_MCI_TXRDY (1 << 2) /* Transmit Ready */
+#define AT91_MCI_BLKE (1 << 3) /* Data Block Ended */
+#define AT91_MCI_DTIP (1 << 4) /* Data Transfer in Progress */
+#define AT91_MCI_NOTBUSY (1 << 5) /* Data Not Busy */
+#define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */
+#define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */
+#define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */
+#define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */
+#define AT91_MCI_RINDE (1 << 16) /* Response Index Error */
+#define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */
+#define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */
+#define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */
+#define AT91_MCI_RTOE (1 << 20) /* Reponse Time-out Error */
+#define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */
+#define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */
+#define AT91_MCI_OVRE (1 << 30) /* Overrun */
+#define AT91_MCI_UNRE (1 << 31) /* Underrun */
+
+#define AT91_MCI_IER 0x44 /* Interrupt Enable Register */
+#define AT91_MCI_IDR 0x48 /* Interrupt Disable Register */
+#define AT91_MCI_IMR 0x4c /* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
index 2e7d1139a799..4fdef13d01d4 100644
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ b/include/asm-arm/arch-at91rm9200/board.h
@@ -38,6 +38,8 @@ extern unsigned long at91_master_clock;
extern int at91_serial_map[AT91_NR_UART];
extern int at91_console_port;
+#include <linux/mtd/partitions.h>
+
/* USB Device */
struct at91_udc_data {
u8 vbus_pin; /* high == host powering us */
@@ -77,4 +79,26 @@ struct at91_usbh_data {
};
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
+ /* NAND / SmartMedia */
+struct at91_nand_data {
+ u8 enable_pin; /* chip enable */
+ u8 det_pin; /* card detect */
+ u8 rdy_pin; /* ready/busy */
+ u8 ale; /* address line number connected to ALE */
+ u8 cle; /* address line number connected to CLE */
+ struct mtd_partition* (*partition_info)(int, int*);
+};
+extern void __init at91_add_device_nand(struct at91_nand_data *data);
+
+ /* I2C*/
+void __init at91_add_device_i2c(void);
+
+ /* RTC */
+void __init at91_add_device_rtc(void);
+
+ /* LEDs */
+extern u8 at91_leds_cpu;
+extern u8 at91_leds_timer;
+extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
+
#endif
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
index 2646c01f8e97..59e6f44d3a0d 100644
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ b/include/asm-arm/arch-at91rm9200/hardware.h
@@ -65,6 +65,9 @@
/* SmartMedia */
#define AT91_SMARTMEDIA_BASE 0x40000000 /* NCS3: Smartmedia physical base address */
+/* Compact Flash */
+#define AT91_CF_BASE 0x50000000 /* NCS4-NCS6: Compact Flash physical base address */
+
/* Multi-Master Memory controller */
#define AT91_UHP_BASE 0x00300000 /* USB Host controller */
diff --git a/include/asm-arm/arch-cl7500/hardware.h b/include/asm-arm/arch-cl7500/hardware.h
index 2339b764f69f..1adfd18e6154 100644
--- a/include/asm-arm/arch-cl7500/hardware.h
+++ b/include/asm-arm/arch-cl7500/hardware.h
@@ -53,16 +53,12 @@
#define SCREEN_END 0xdfc00000
#define SCREEN_BASE 0xdf800000
-#define FLUSH_BASE 0xdf000000
-
#define VIDC_BASE (void __iomem *)0xe0400000
#define IOMD_BASE IOMEM(0xe0200000)
#define IOC_BASE IOMEM(0xe0200000)
#define FLOPPYDMA_BASE IOMEM(0xe002a000)
#define PCIO_BASE IOMEM(0xe0010000)
-#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
-
#define vidc_writel(val) __raw_writel(val, VIDC_BASE)
/* in/out bias for the ISA slot region */
diff --git a/include/asm-arm/arch-cl7500/memory.h b/include/asm-arm/arch-cl7500/memory.h
index 34f40a6cec30..3178140e24ca 100644
--- a/include/asm-arm/arch-cl7500/memory.h
+++ b/include/asm-arm/arch-cl7500/memory.h
@@ -26,4 +26,10 @@
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS 0x00000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-ebsa110/debug-macro.S b/include/asm-arm/arch-ebsa110/debug-macro.S
index f61cadabe0ec..9213bfe4831d 100644
--- a/include/asm-arm/arch-ebsa110/debug-macro.S
+++ b/include/asm-arm/arch-ebsa110/debug-macro.S
@@ -18,4 +18,4 @@
#define UART_SHIFT 2
#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.h>
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ebsa110/hardware.h b/include/asm-arm/arch-ebsa110/hardware.h
index 4e41c2358f4e..3ce864def41e 100644
--- a/include/asm-arm/arch-ebsa110/hardware.h
+++ b/include/asm-arm/arch-ebsa110/hardware.h
@@ -57,9 +57,6 @@
/*
* RAM definitions
*/
-#define FLUSH_BASE_PHYS 0x40000000
-#define FLUSH_BASE 0xdf000000
-
#define UNCACHEABLE_ADDR 0xff000000 /* IRQ_STAT */
#endif
diff --git a/include/asm-arm/arch-ebsa110/memory.h b/include/asm-arm/arch-ebsa110/memory.h
index 02f144520c10..c7c500e176d0 100644
--- a/include/asm-arm/arch-ebsa110/memory.h
+++ b/include/asm-arm/arch-ebsa110/memory.h
@@ -28,4 +28,10 @@
#define __virt_to_bus(x) (x)
#define __bus_to_virt(x) (x)
+/*
+ * Cache flushing area - SRAM
+ */
+#define FLUSH_BASE_PHYS 0x40000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h
index 66b19c7fd908..ae5b775eb0b7 100644
--- a/include/asm-arm/arch-ebsa110/uncompress.h
+++ b/include/asm-arm/arch-ebsa110/uncompress.h
@@ -10,7 +10,7 @@
#include <linux/serial_reg.h>
-#define SERIAL_BASE ((unsigned char *)0xfe000be0)
+#define SERIAL_BASE ((unsigned char *)0xf0000be0)
/*
* This does not append a newline
diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h
index 2ef2200f108c..ec51fe92483b 100644
--- a/include/asm-arm/arch-ebsa285/hardware.h
+++ b/include/asm-arm/arch-ebsa285/hardware.h
@@ -48,9 +48,6 @@
#define PCICFG0_SIZE 0x01000000
#define PCICFG0_BASE 0xfa000000
-#define FLUSH_SIZE 0x00100000
-#define FLUSH_BASE 0xf9000000
-
#define PCIMEM_SIZE 0x01000000
#define PCIMEM_BASE 0xf0000000
@@ -61,9 +58,6 @@
#define PCIMEM_SIZE 0x80000000
#define PCIMEM_BASE 0x80000000
-#define FLUSH_SIZE 0x00100000
-#define FLUSH_BASE 0x7e000000
-
#define WFLUSH_SIZE 0x01000000
#define WFLUSH_BASE 0x7d000000
@@ -94,7 +88,6 @@
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
-#define FLUSH_BASE_PHYS 0x50000000
#define UNCACHEABLE_ADDR (ARMCSR_BASE + 0x108)
diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h
index 09e335cd687d..99181ffc7e27 100644
--- a/include/asm-arm/arch-ebsa285/memory.h
+++ b/include/asm-arm/arch-ebsa285/memory.h
@@ -49,12 +49,22 @@ extern unsigned long __bus_to_virt(unsigned long);
#define TASK_SIZE UL(0xbf000000)
#define PAGE_OFFSET UL(0xc0000000)
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE 0xf9000000
+
#elif defined(CONFIG_ARCH_CO285)
/* Task size and page offset at 1.5GB */
#define TASK_SIZE UL(0x5f000000)
#define PAGE_OFFSET UL(0x60000000)
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE 0x7e000000
+
#else
#error "Undefined footbridge architecture"
@@ -72,4 +82,6 @@ extern unsigned long __bus_to_virt(unsigned long);
*/
#define TASK_UNMAPPED_BASE ((TASK_SIZE + 0x01000000) / 3)
+#define FLUSH_BASE_PHYS 0x50000000
+
#endif
diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
index 412215e77f44..a94f63ff0535 100644
--- a/include/asm-arm/arch-ep93xx/ts72xx.h
+++ b/include/asm-arm/arch-ep93xx/ts72xx.h
@@ -12,6 +12,8 @@
* febfc000 [67]0000000 4K NAND data register
* febfb000 [67]0400000 4K NAND control register
* febfa000 [67]0800000 4K NAND busy register
+ * febf9000 10800000 4K TS-5620 RTC index register
+ * febf8000 11700000 4K TS-5620 RTC data register
*/
#define TS72XX_MODEL_PHYS_BASE 0x22000000
@@ -58,6 +60,15 @@
#define TS72XX_NAND_BUSY_SIZE 0x00001000
+#define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
+#define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
+#define TS72XX_RTC_INDEX_SIZE 0x00001000
+
+#define TS72XX_RTC_DATA_VIRT_BASE 0xfebf8000
+#define TS72XX_RTC_DATA_PHYS_BASE 0x11700000
+#define TS72XX_RTC_DATA_SIZE 0x00001000
+
+
#ifndef __ASSEMBLY__
#include <asm/io.h>
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
index b45fa367d71e..621ff2c730f2 100644
--- a/include/asm-arm/arch-imx/dma.h
+++ b/include/asm-arm/arch-imx/dma.h
@@ -17,27 +17,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-/*
- * DMA registration
- */
-
typedef enum {
DMA_PRIO_HIGH = 0,
- DMA_PRIO_MEDIUM = 3,
- DMA_PRIO_LOW = 6
+ DMA_PRIO_MEDIUM = 1,
+ DMA_PRIO_LOW = 2
} imx_dma_prio;
-int imx_request_dma(char *name, imx_dma_prio prio,
- void (*irq_handler) (int, void *, struct pt_regs *),
- void (*err_handler) (int, void *, struct pt_regs *),
- void *data);
-
-void imx_free_dma(int dma_ch);
-
-
#define DMA_REQ_UART3_T 2
#define DMA_REQ_UART3_R 3
#define DMA_REQ_SSI2_T 4
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
new file mode 100644
index 000000000000..f2063c1d610d
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -0,0 +1,90 @@
+/*
+ * linux/include/asm-arm/imxads/dma.h
+ *
+ * Copyright (C) 1997,1998 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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 <asm/dma.h>
+
+#ifndef __ASM_ARCH_IMX_DMA_H
+#define __ASM_ARCH_IMX_DMA_H
+
+#define IMX_DMA_CHANNELS 11
+
+/*
+ * struct imx_dma_channel - i.MX specific DMA extension
+ * @name: name specified by DMA client
+ * @irq_handler: client callback for end of transfer
+ * @err_handler: client callback for error condition
+ * @data: clients context data for callbacks
+ * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE
+ * @sg: pointer to the actual read/written chunk for scatter-gather emulation
+ * @sgbc: counter of processed bytes in the actual read/written chunk
+ * @resbytes: total residual number of bytes to transfer
+ * (it can be lower or same as sum of SG mapped chunk sizes)
+ * @sgcount: number of chunks to be read/written
+ *
+ * Structure is used for IMX DMA processing. It would be probably good
+ * @struct dma_struct in the future for external interfacing and use
+ * @struct imx_dma_channel only as extension to it.
+ */
+
+struct imx_dma_channel {
+ const char *name;
+ void (*irq_handler) (int, void *, struct pt_regs *);
+ void (*err_handler) (int, void *, struct pt_regs *);
+ void *data;
+ dmamode_t dma_mode;
+ struct scatterlist *sg;
+ unsigned int sgbc;
+ unsigned int sgcount;
+ unsigned int resbytes;
+ int dma_num;
+};
+
+extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+
+/* The type to distinguish channel numbers parameter from ordinal int type */
+typedef int imx_dmach_t;
+
+int
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+ unsigned int dma_length, unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+ unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+ void (*irq_handler) (int, void *, struct pt_regs *),
+ void (*err_handler) (int, void *, struct pt_regs *), void *data);
+
+void imx_dma_enable(imx_dmach_t dma_ch);
+
+void imx_dma_disable(imx_dmach_t dma_ch);
+
+int imx_dma_request(imx_dmach_t dma_ch, const char *name);
+
+void imx_dma_free(imx_dmach_t dma_ch);
+
+int imx_dma_request_by_prio(imx_dmach_t *pdma_ch, const char *name, imx_dma_prio prio);
+
+
+#endif /* _ASM_ARCH_IMX_DMA_H */
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h
new file mode 100644
index 000000000000..1937151665c7
--- /dev/null
+++ b/include/asm-arm/arch-imx/mmc.h
@@ -0,0 +1,12 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/protocol.h>
+
+struct imxmmc_platform_data {
+ int (*card_present)(void);
+};
+
+extern void imx_set_mmc_info(struct imxmmc_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/debug-macro.S b/include/asm-arm/arch-ixp23xx/debug-macro.S
index eb99fd69fd24..2b25e640247d 100644
--- a/include/asm-arm/arch-ixp23xx/debug-macro.S
+++ b/include/asm-arm/arch-ixp23xx/debug-macro.S
@@ -17,6 +17,9 @@
tst \rx, #1 @ mmu enabled?
ldreq \rx, =IXP23XX_PERIPHERAL_PHYS @ physical
ldrne \rx, =IXP23XX_PERIPHERAL_VIRT @ virtual
+#ifdef __ARMEB__
+ orr \rx, \rx, #0x00000003
+#endif
.endm
#define UART_SHIFT 2
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
index bebcf0aa0d72..6e19f46d54d1 100644
--- a/include/asm-arm/arch-ixp23xx/memory.h
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -28,6 +28,7 @@
* to an address that the kernel can use.
*/
#ifndef __ASSEMBLY__
+#include <asm/mach-types.h>
#define __virt_to_bus(v) \
({ unsigned int ret; \
@@ -40,6 +41,22 @@
data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \
__phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
+/*
+ * Coherency support. Only supported on A2 CPUs or on A1
+ * systems that have the cache coherency workaround.
+ */
+static inline int __ixp23xx_arch_is_coherent(void)
+{
+ extern unsigned int processor_id;
+
+ if (((processor_id & 15) >= 2) || machine_is_roadrunner())
+ return 1;
+
+ return 0;
+}
+
+#define arch_is_coherent() __ixp23xx_arch_is_coherent()
+
#endif
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
index f85b4685a491..e4d99060a049 100644
--- a/include/asm-arm/arch-ixp23xx/platform.h
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -22,6 +22,7 @@ void ixp23xx_sys_init(void);
int ixp23xx_pci_setup(int, struct pci_sys_data *);
void ixp23xx_pci_preinit(void);
struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*);
+void ixp23xx_pci_slave_init(void);
extern struct sys_timer ixp23xx_timer;
diff --git a/include/asm-arm/arch-l7200/hardware.h b/include/asm-arm/arch-l7200/hardware.h
index b755079befab..2ab43f3a4a8d 100644
--- a/include/asm-arm/arch-l7200/hardware.h
+++ b/include/asm-arm/arch-l7200/hardware.h
@@ -52,9 +52,6 @@
#define ISA_SIZE 0x20000000
#define ISA_BASE 0xe0000000
-#define FLUSH_BASE_PHYS 0x40000000 /* ROM */
-#define FLUSH_BASE 0xdf000000
-
#define PCIO_BASE IO_BASE
#endif
diff --git a/include/asm-arm/arch-l7200/memory.h b/include/asm-arm/arch-l7200/memory.h
index 9e50a171f78a..402df637e740 100644
--- a/include/asm-arm/arch-l7200/memory.h
+++ b/include/asm-arm/arch-l7200/memory.h
@@ -20,4 +20,10 @@
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS 0x40000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
index c92bcb837629..9f1a58cbf407 100644
--- a/include/asm-arm/arch-lh7a40x/memory.h
+++ b/include/asm-arm/arch-lh7a40x/memory.h
@@ -31,8 +31,6 @@
#ifdef CONFIG_DISCONTIGMEM
-#define NODES_SHIFT 4 /* Up to 16 nodes */
-
/*
* Given a kernel address, find the home node of the underlying memory.
*/
diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h
index 590bac25b7c4..6513065941d0 100644
--- a/include/asm-arm/arch-omap/aic23.h
+++ b/include/asm-arm/arch-omap/aic23.h
@@ -57,6 +57,7 @@
#define LHV_MIN 0x0000
// Analog audio path control register
+#define STA_REG(x) ((x)<<6)
#define STE_ENABLED 0x0020
#define DAC_SELECTED 0x0010
#define BYPASS_ON 0x0008
@@ -109,4 +110,7 @@
#define TLV320AIC23ID1 (0x1a) // cs low
#define TLV320AIC23ID2 (0x1b) // cs high
+void tlv320aic23_power_up(void);
+void tlv320aic23_power_down(void);
+
#endif /* __ASM_ARCH_AIC23_H */
diff --git a/include/asm-arm/arch-omap/board-ams-delta.h b/include/asm-arm/arch-omap/board-ams-delta.h
new file mode 100644
index 000000000000..0070f6d3b75c
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-ams-delta.h
@@ -0,0 +1,65 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-ams-delta.h
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __ASM_ARCH_OMAP_AMS_DELTA_H
+#define __ASM_ARCH_OMAP_AMS_DELTA_H
+
+#if defined (CONFIG_MACH_AMS_DELTA)
+
+#define AMS_DELTA_LATCH1_PHYS 0x01000000
+#define AMS_DELTA_LATCH1_VIRT 0xEA000000
+#define AMS_DELTA_MODEM_PHYS 0x04000000
+#define AMS_DELTA_MODEM_VIRT 0xEB000000
+#define AMS_DELTA_LATCH2_PHYS 0x08000000
+#define AMS_DELTA_LATCH2_VIRT 0xEC000000
+
+#define AMS_DELTA_LATCH1_LED_CAMERA 0x01
+#define AMS_DELTA_LATCH1_LED_ADVERT 0x02
+#define AMS_DELTA_LATCH1_LED_EMAIL 0x04
+#define AMS_DELTA_LATCH1_LED_HANDSFREE 0x08
+#define AMS_DELTA_LATCH1_LED_VOICEMAIL 0x10
+#define AMS_DELTA_LATCH1_LED_VOICE 0x20
+
+#define AMS_DELTA_LATCH2_LCD_VBLEN 0x0001
+#define AMS_DELTA_LATCH2_LCD_NDISP 0x0002
+#define AMS_DELTA_LATCH2_NAND_NCE 0x0004
+#define AMS_DELTA_LATCH2_NAND_NRE 0x0008
+#define AMS_DELTA_LATCH2_NAND_NWP 0x0010
+#define AMS_DELTA_LATCH2_NAND_NWE 0x0020
+#define AMS_DELTA_LATCH2_NAND_ALE 0x0040
+#define AMS_DELTA_LATCH2_NAND_CLE 0x0080
+#define AMS_DELTA_LATCH2_MODEM_NRESET 0x1000
+#define AMS_DELTA_LATCH2_MODEM_CODEC 0x2000
+
+#define AMS_DELTA_GPIO_PIN_NAND_RB 12
+
+#ifndef __ASSEMBLY__
+void ams_delta_latch1_write(u8 mask, u8 value);
+void ams_delta_latch2_write(u16 mask, u16 value);
+#endif
+
+#endif /* CONFIG_MACH_AMS_DELTA */
+
+#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
diff --git a/include/asm-arm/arch-omap/board-apollon.h b/include/asm-arm/arch-omap/board-apollon.h
new file mode 100644
index 000000000000..de0c5b792c58
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-apollon.h
@@ -0,0 +1,45 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-apollon.h
+ *
+ * Hardware definitions for Samsung OMAP24XX Apollon board.
+ *
+ * Initial creation by Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_OMAP_APOLLON_H
+#define __ASM_ARCH_OMAP_APOLLON_H
+
+/* Placeholder for APOLLON specific defines */
+/* GPMC CS0 */
+#define APOLLON_CS0_BASE 0x00000000
+/* GPMC CS1 */
+#define APOLLON_CS1_BASE 0x08000000
+#define APOLLON_ETHR_START (APOLLON_CS1_BASE + 0x300)
+#define APOLLON_ETHR_GPIO_IRQ 74
+/* GPMC CS2 - reserved for OneNAND */
+#define APOLLON_CS2_BASE 0x10000000
+/* GPMC CS3 - reserved for NOR or NAND */
+#define APOLLON_CS3_BASE 0x18000000
+
+#endif /* __ASM_ARCH_OMAP_APOLLON_H */
+
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
index 39ca5a31aeea..b2888ef9e9b4 100644
--- a/include/asm-arm/arch-omap/board-h2.h
+++ b/include/asm-arm/arch-omap/board-h2.h
@@ -34,9 +34,5 @@
/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
#define OMAP1610_ETHR_START 0x04000300
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
-
#endif /* __ASM_ARCH_OMAP_H2_H */
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index 1b12c1dcc2fa..761ea0a17897 100644
--- a/include/asm-arm/arch-omap/board-h3.h
+++ b/include/asm-arm/arch-omap/board-h3.h
@@ -30,10 +30,6 @@
/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
#define OMAP1710_ETHR_START 0x04000300
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
-
#define MAXIRQNUM (IH_BOARD_BASE)
#define MAXFIQNUM MAXIRQNUM
#define MAXSWINUM MAXIRQNUM
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h
index 33ea29a41654..7ef664bc9e33 100644
--- a/include/asm-arm/arch-omap/board-h4.h
+++ b/include/asm-arm/arch-omap/board-h4.h
@@ -33,12 +33,6 @@
/* GPMC CS1 */
#define OMAP24XX_ETHR_START 0x08000300
#define OMAP24XX_ETHR_GPIO_IRQ 92
-
-#define H4_CS0_BASE 0x04000000
-
-#define H4_CS0_BASE 0x04000000
-
-#define H4_CS0_BASE 0x04000000
-
+#define H4_CS0_BASE 0x04000000
#endif /* __ASM_ARCH_OMAP_H4_H */
diff --git a/include/asm-arm/arch-omap/board-netstar.h b/include/asm-arm/arch-omap/board-netstar.h
deleted file mode 100644
index 77cc0fb54d54..000000000000
--- a/include/asm-arm/arch-omap/board-netstar.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Hardware definitions for OMAP5910 based NetStar board.
- *
- * 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_NETSTAR_H
-#define __ASM_ARCH_NETSTAR_H
-
-#include <asm/arch/tc.h>
-
-#define OMAP_NAND_FLASH_START1 OMAP_CS1_PHYS + (1 << 23)
-#define OMAP_NAND_FLASH_START2 OMAP_CS1_PHYS + (2 << 23)
-
-#endif /* __ASM_ARCH_NETSTAR_H */
diff --git a/include/asm-arm/arch-omap/board-nokia.h b/include/asm-arm/arch-omap/board-nokia.h
new file mode 100644
index 000000000000..72deea203493
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-nokia.h
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-nokia.h
+ *
+ * Information structures for Nokia-specific board config data
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ */
+
+#ifndef _OMAP_BOARD_NOKIA_H
+#define _OMAP_BOARD_NOKIA_H
+
+#include <linux/types.h>
+
+#define OMAP_TAG_NOKIA_BT 0x4e01
+#define OMAP_TAG_WLAN_CX3110X 0x4e02
+#define OMAP_TAG_CBUS 0x4e03
+#define OMAP_TAG_EM_ASIC_BB5 0x4e04
+
+
+#define BT_CHIP_CSR 1
+#define BT_CHIP_TI 2
+
+#define BT_SYSCLK_12 1
+#define BT_SYSCLK_38_4 2
+
+struct omap_bluetooth_config {
+ u8 chip_type;
+ u8 bt_wakeup_gpio;
+ u8 host_wakeup_gpio;
+ u8 reset_gpio;
+ u8 bt_uart;
+ u8 bd_addr[6];
+ u8 bt_sysclk;
+};
+
+struct omap_wlan_cx3110x_config {
+ u8 chip_type;
+ s16 power_gpio;
+ s16 irq_gpio;
+ s16 spi_cs_gpio;
+};
+
+struct omap_cbus_config {
+ s16 clk_gpio;
+ s16 dat_gpio;
+ s16 sel_gpio;
+};
+
+struct omap_em_asic_bb5_config {
+ s16 retu_irq_gpio;
+ s16 tahvo_irq_gpio;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
index 691e52a52b43..eb74420cb439 100644
--- a/include/asm-arm/arch-omap/board-perseus2.h
+++ b/include/asm-arm/arch-omap/board-perseus2.h
@@ -42,8 +42,4 @@
#define NR_IRQS (MAXIRQNUM + 1)
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
-
#endif
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index a0040cd86639..6d6240a4681c 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -21,9 +21,12 @@
#define OMAP_TAG_LCD 0x4f05
#define OMAP_TAG_GPIO_SWITCH 0x4f06
#define OMAP_TAG_UART 0x4f07
+#define OMAP_TAG_FBMEM 0x4f08
+#define OMAP_TAG_STI_CONSOLE 0x4f09
#define OMAP_TAG_BOOT_REASON 0x4f80
#define OMAP_TAG_FLASH_PART 0x4f81
+#define OMAP_TAG_VERSION_STR 0x4f82
struct omap_clock_config {
/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
@@ -54,6 +57,11 @@ struct omap_serial_console_config {
u32 console_speed;
};
+struct omap_sti_console_config {
+ unsigned enable:1;
+ u8 channel;
+};
+
struct omap_usb_config {
/* Configure drivers according to the connectors on your board:
* - "A" connector (rectagular)
@@ -87,6 +95,13 @@ struct omap_lcd_config {
char ctrl_name[16];
};
+struct omap_fbmem_config {
+ u32 fb_sram_start;
+ u32 fb_sram_size;
+ u32 fb_sdram_start;
+ u32 fb_sdram_size;
+};
+
/* Cover:
* high -> closed
* low -> open
@@ -106,6 +121,12 @@ struct omap_gpio_switch_config {
int key_code:24; /* Linux key code */
};
+struct omap_uart_config {
+ /* Bit field of UARTs present; bit 0 --> UART1 */
+ unsigned int enabled_uarts;
+};
+
+
struct omap_flash_part_config {
char part_table[0];
};
@@ -114,11 +135,14 @@ struct omap_boot_reason_config {
char reason_str[12];
};
-struct omap_uart_config {
- /* Bit field of UARTs present; bit 0 --> UART1 */
- unsigned int enabled_uarts;
+struct omap_version_config {
+ char component[12];
+ char version[12];
};
+
+#include <asm-arm/arch-omap/board-nokia.h>
+
struct omap_board_config_entry {
u16 tag;
u16 len;
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 46a0402696de..3c4eb9fbe48a 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -19,6 +19,7 @@ struct clk {
struct list_head node;
struct module *owner;
const char *name;
+ int id;
struct clk *parent;
unsigned long rate;
__u32 flags;
@@ -57,6 +58,7 @@ extern void propagate_rate(struct clk *clk);
extern void followparent_recalc(struct clk * clk);
extern void clk_allow_idle(struct clk *clk);
extern void clk_deny_idle(struct clk *clk);
+extern int clk_get_usecount(struct clk *clk);
/* Clock flags */
#define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */
@@ -80,10 +82,11 @@ extern void clk_deny_idle(struct clk *clk);
#define CM_PLL_SEL1 (1 << 18)
#define CM_PLL_SEL2 (1 << 19)
#define CM_SYSCLKOUT_SEL1 (1 << 20)
-#define CLOCK_IN_OMAP730 (1 << 21)
-#define CLOCK_IN_OMAP1510 (1 << 22)
-#define CLOCK_IN_OMAP16XX (1 << 23)
-#define CLOCK_IN_OMAP242X (1 << 24)
-#define CLOCK_IN_OMAP243X (1 << 25)
+#define CLOCK_IN_OMAP310 (1 << 21)
+#define CLOCK_IN_OMAP730 (1 << 22)
+#define CLOCK_IN_OMAP1510 (1 << 23)
+#define CLOCK_IN_OMAP16XX (1 << 24)
+#define CLOCK_IN_OMAP242X (1 << 25)
+#define CLOCK_IN_OMAP243X (1 << 26)
#endif
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index d4e73efcb816..ca1202312a45 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -404,6 +404,7 @@ extern void omap_free_lcd_dma(void);
extern void omap_setup_lcd_dma(void);
extern void omap_enable_lcd_dma(void);
extern void omap_stop_lcd_dma(void);
+extern int omap_lcd_dma_ext_running(void);
extern void omap_set_lcd_dma_ext_controller(int external);
extern void omap_set_lcd_dma_single_transfer(int single);
extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
index 11772c792f3e..e6522e6a3834 100644
--- a/include/asm-arm/arch-omap/dmtimer.h
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -88,5 +88,6 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
void omap_dm_timer_reset_counter(struct omap_dm_timer *timer);
int omap_dm_timers_active(void);
+u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
#endif /* __ASM_ARCH_TIMER_H */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
index 57bf4f39ca58..06dad83dd41f 100644
--- a/include/asm-arm/arch-omap/dsp.h
+++ b/include/asm-arm/arch-omap/dsp.h
@@ -181,10 +181,16 @@ struct omap_dsp_varinfo {
#define OMAP_DSP_MBCMD_PM_ENABLE 0x01
#define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00
+#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR 0x01
+#define OMAP_DSP_MBCMD_FBCTL_UPD 0x0000
#define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002
#define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003
+#define OMAP_DSP_MBCMD_AUDIO_PWR_UP 0x0000
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002
+
#define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000
#define OMAP_DSP_MBCMD_TDEL_KILL 0x0001
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
index 4fcce6944056..16a459dfa714 100644
--- a/include/asm-arm/arch-omap/dsp_common.h
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -27,11 +27,12 @@
#ifndef ASM_ARCH_DSP_COMMON_H
#define ASM_ARCH_DSP_COMMON_H
-void omap_dsp_pm_suspend(void);
-void omap_dsp_pm_resume(void);
-void omap_dsp_request_mpui(void);
-void omap_dsp_release_mpui(void);
-int omap_dsp_request_mem(void);
-int omap_dsp_release_mem(void);
+extern void omap_dsp_request_mpui(void);
+extern void omap_dsp_release_mpui(void);
+extern int omap_dsp_request_mem(void);
+extern int omap_dsp_release_mem(void);
+
+extern void (*omap_dsp_audio_pwr_up_request)(int stage);
+extern void (*omap_dsp_audio_pwr_down_request)(int stage);
#endif /* ASM_ARCH_DSP_COMMON_H */
diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h
new file mode 100644
index 000000000000..7a43b0a912e4
--- /dev/null
+++ b/include/asm-arm/arch-omap/gpioexpander.h
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpioexpander.h
+ *
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H
+#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
+
+/* Function Prototypes for GPIO Expander functions */
+
+int read_gpio_expa(u8 *, int);
+int write_gpio_expa(u8 , int);
+
+#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 5406b875c422..7909b729826c 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -306,6 +306,10 @@
#include "board-h4.h"
#endif
+#ifdef CONFIG_MACH_OMAP_APOLLON
+#include "board-apollon.h"
+#endif
+
#ifdef CONFIG_MACH_OMAP_OSK
#include "board-osk.h"
#endif
@@ -314,10 +318,6 @@
#include "board-voiceblue.h"
#endif
-#ifdef CONFIG_MACH_NETSTAR
-#include "board-netstar.h"
-#endif
-
#endif /* !__ASSEMBLER__ */
#endif /* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/include/asm-arm/arch-omap/irda.h b/include/asm-arm/arch-omap/irda.h
new file mode 100644
index 000000000000..805ae3575e44
--- /dev/null
+++ b/include/asm-arm/arch-omap/irda.h
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/arch-omap/irda.h
+ *
+ * Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_SEL 1 /* Selects IrDA */
+#define IR_SIRMODE 2
+#define IR_FIRMODE 4
+#define IR_MIRMODE 8
+
+struct omap_irda_config {
+ int transceiver_cap;
+ int (*transceiver_mode)(struct device *dev, int mode);
+ int (*select_irda)(struct device *dev, int state);
+ /* Very specific to the needs of some platforms (h3,h4)
+ * having calls which can sleep in irda_set_speed.
+ */
+ struct work_struct gpio_expa;
+ int rx_channel;
+ int tx_channel;
+ unsigned long dest_start;
+ unsigned long src_start;
+ int tx_trigger;
+ int rx_trigger;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 4ffce1d77759..42098d99f302 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -242,6 +242,11 @@
#define INT_24XX_GPIO_BANK2 30
#define INT_24XX_GPIO_BANK3 31
#define INT_24XX_GPIO_BANK4 32
+#define INT_24XX_MCBSP1_IRQ_TX 59
+#define INT_24XX_MCBSP1_IRQ_RX 60
+#define INT_24XX_MCBSP2_IRQ_TX 62
+#define INT_24XX_MCBSP2_IRQ_RX 63
+#define INT_24XX_UART3_IRQ 74
/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
* 16 MPUIO lines */
diff --git a/include/asm-arm/arch-omap/keypad.h b/include/asm-arm/arch-omap/keypad.h
new file mode 100644
index 000000000000..8a023a984acb
--- /dev/null
+++ b/include/asm-arm/arch-omap/keypad.h
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/arch-omap/keypad.h
+ *
+ * Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASMARM_ARCH_KEYPAD_H
+#define ASMARM_ARCH_KEYPAD_H
+
+struct omap_kp_platform_data {
+ int rows;
+ int cols;
+ int *keymap;
+ unsigned int rep:1;
+ /* specific to OMAP242x*/
+ unsigned int *row_gpios;
+ unsigned int *col_gpios;
+};
+
+/* Group (0..3) -- when multiple keys are pressed, only the
+ * keys pressed in the same group are considered as pressed. This is
+ * in order to workaround certain crappy HW designs that produce ghost
+ * keypresses. */
+#define GROUP_0 (0 << 16)
+#define GROUP_1 (1 << 16)
+#define GROUP_2 (2 << 16)
+#define GROUP_3 (3 << 16)
+#define GROUP_MASK GROUP_3
+
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+
+#endif
+
diff --git a/include/asm-arm/arch-omap/lcd_lph8923.h b/include/asm-arm/arch-omap/lcd_lph8923.h
new file mode 100644
index 000000000000..004e67e22ca7
--- /dev/null
+++ b/include/asm-arm/arch-omap/lcd_lph8923.h
@@ -0,0 +1,14 @@
+#ifndef __LCD_LPH8923_H
+#define __LCD_LPH8923_H
+
+enum lcd_lph8923_test_num {
+ LCD_LPH8923_TEST_RGB_LINES,
+};
+
+enum lcd_lph8923_test_result {
+ LCD_LPH8923_TEST_SUCCESS,
+ LCD_LPH8923_TEST_INVALID,
+ LCD_LPH8923_TEST_FAILED,
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
index e79d98ab2ab6..ed0dde4f7219 100644
--- a/include/asm-arm/arch-omap/mcbsp.h
+++ b/include/asm-arm/arch-omap/mcbsp.h
@@ -37,6 +37,11 @@
#define OMAP1610_MCBSP2_BASE 0xfffb1000
#define OMAP1610_MCBSP3_BASE 0xe1017000
+#define OMAP24XX_MCBSP1_BASE 0x48074000
+#define OMAP24XX_MCBSP2_BASE 0x48076000
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)
+
#define OMAP_MCBSP_REG_DRR2 0x00
#define OMAP_MCBSP_REG_DRR1 0x02
#define OMAP_MCBSP_REG_DXR2 0x04
@@ -71,9 +76,62 @@
#define OMAP_MAX_MCBSP_COUNT 3
+#define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP OMAP_MCBSP1
+#define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX
+#define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX
+
+#elif defined(CONFIG_ARCH_OMAP24XX)
+
+#define OMAP_MCBSP_REG_DRR2 0x00
+#define OMAP_MCBSP_REG_DRR1 0x04
+#define OMAP_MCBSP_REG_DXR2 0x08
+#define OMAP_MCBSP_REG_DXR1 0x0C
+#define OMAP_MCBSP_REG_SPCR2 0x10
+#define OMAP_MCBSP_REG_SPCR1 0x14
+#define OMAP_MCBSP_REG_RCR2 0x18
+#define OMAP_MCBSP_REG_RCR1 0x1C
+#define OMAP_MCBSP_REG_XCR2 0x20
+#define OMAP_MCBSP_REG_XCR1 0x24
+#define OMAP_MCBSP_REG_SRGR2 0x28
+#define OMAP_MCBSP_REG_SRGR1 0x2C
+#define OMAP_MCBSP_REG_MCR2 0x30
+#define OMAP_MCBSP_REG_MCR1 0x34
+#define OMAP_MCBSP_REG_RCERA 0x38
+#define OMAP_MCBSP_REG_RCERB 0x3C
+#define OMAP_MCBSP_REG_XCERA 0x40
+#define OMAP_MCBSP_REG_XCERB 0x44
+#define OMAP_MCBSP_REG_PCR0 0x48
+#define OMAP_MCBSP_REG_RCERC 0x4C
+#define OMAP_MCBSP_REG_RCERD 0x50
+#define OMAP_MCBSP_REG_XCERC 0x54
+#define OMAP_MCBSP_REG_XCERD 0x58
+#define OMAP_MCBSP_REG_RCERE 0x5C
+#define OMAP_MCBSP_REG_RCERF 0x60
+#define OMAP_MCBSP_REG_XCERE 0x64
+#define OMAP_MCBSP_REG_XCERF 0x68
+#define OMAP_MCBSP_REG_RCERG 0x6C
+#define OMAP_MCBSP_REG_RCERH 0x70
+#define OMAP_MCBSP_REG_XCERG 0x74
+#define OMAP_MCBSP_REG_XCERH 0x78
+
+#define OMAP_MAX_MCBSP_COUNT 2
+
+#define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP OMAP_MCBSP2
+#define AUDIO_DMA_TX OMAP24XX_DMA_MCBSP2_TX
+#define AUDIO_DMA_RX OMAP24XX_DMA_MCBSP2_RX
+
+#endif
+
#define OMAP_MCBSP_READ(base, reg) __raw_readw((base) + OMAP_MCBSP_REG_##reg)
#define OMAP_MCBSP_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MCBSP_REG_##reg)
+
/************************** McBSP SPCR1 bit definitions ***********************/
#define RRST 0x0001
#define RRDY 0x0002
@@ -195,6 +253,10 @@ typedef enum {
OMAP_MCBSP3,
} omap_mcbsp_id;
+typedef int __bitwise omap_mcbsp_io_type_t;
+#define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
+#define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
+
typedef enum {
OMAP_MCBSP_WORD_8 = 0,
OMAP_MCBSP_WORD_12,
@@ -246,6 +308,9 @@ u32 omap_mcbsp_recv_word(unsigned int id);
int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
+
/* SPI specific API */
void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
diff --git a/include/asm-arm/arch-omap/mcspi.h b/include/asm-arm/arch-omap/mcspi.h
new file mode 100644
index 000000000000..9e7f40a88e1b
--- /dev/null
+++ b/include/asm-arm/arch-omap/mcspi.h
@@ -0,0 +1,16 @@
+#ifndef _OMAP2_MCSPI_H
+#define _OMAP2_MCSPI_H
+
+struct omap2_mcspi_platform_config {
+ unsigned long base;
+ unsigned short num_cs;
+};
+
+struct omap2_mcspi_device_config {
+ unsigned turbo_mode:1;
+
+ /* Do we want one channel enabled at the same time? */
+ unsigned single_channel:1;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h
index 46be8b8d6346..88cd4c87f0de 100644
--- a/include/asm-arm/arch-omap/menelaus.h
+++ b/include/asm-arm/arch-omap/menelaus.h
@@ -7,7 +7,7 @@
#ifndef __ASM_ARCH_MENELAUS_H
#define __ASM_ARCH_MENELAUS_H
-extern void menelaus_mmc_register(void (*callback)(u8 card_mask),
+extern void menelaus_mmc_register(void (*callback)(unsigned long data, u8 card_mask),
unsigned long data);
extern void menelaus_mmc_remove(void);
extern void menelaus_mmc_opendrain(int enable);
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index 13415a9aab06..0dc24d4ba59c 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -112,14 +112,13 @@
* as mux config
*/
#define MUX_CFG_730(desc, mux_reg, mode_offset, mode, \
- pull_reg, pull_bit, pull_status, \
- pu_pd_reg, pu_pd_status, debug_status)\
+ pull_bit, pull_status, debug_status)\
{ \
.name = desc, \
.debug = debug_status, \
MUX_REG_730(mux_reg, mode_offset, mode) \
PULL_REG_730(mux_reg, pull_bit, pull_status) \
- PU_PD_REG(pu_pd_reg, pu_pd_status) \
+ PU_PD_REG(NA, 0) \
},
#define MUX_CFG_24XX(desc, reg_offset, mode, \
@@ -172,6 +171,11 @@ enum omap730_index {
E4_730_KBC2,
F4_730_KBC3,
E3_730_KBC4,
+
+ /* USB */
+ AA17_730_USB_DM,
+ W16_730_USB_PU_EN,
+ W17_730_USB_VBUSI,
};
enum omap1xxx_index {
@@ -403,9 +407,53 @@ enum omap24xx_index {
/* 24xx Menelaus interrupt */
W19_24XX_SYS_NIRQ,
+ /* 24xx clock */
+ W14_24XX_SYS_CLKOUT,
+
+ /* 242X McBSP */
+ Y15_24XX_MCBSP2_CLKX,
+ R14_24XX_MCBSP2_FSX,
+ W15_24XX_MCBSP2_DR,
+ V15_24XX_MCBSP2_DX,
+
/* 24xx GPIO */
+ M21_242X_GPIO11,
+ AA10_242X_GPIO13,
+ AA6_242X_GPIO14,
+ AA4_242X_GPIO15,
+ Y11_242X_GPIO16,
+ AA12_242X_GPIO17,
+ AA8_242X_GPIO58,
Y20_24XX_GPIO60,
+ W4__24XX_GPIO74,
M15_24XX_GPIO92,
+ V14_24XX_GPIO117,
+
+ P20_24XX_TSC_IRQ,
+
+ /* UART3 */
+ K15_24XX_UART3_TX,
+ K14_24XX_UART3_RX,
+
+ /* Keypad GPIO*/
+ T19_24XX_KBR0,
+ R19_24XX_KBR1,
+ V18_24XX_KBR2,
+ M21_24XX_KBR3,
+ E5__24XX_KBR4,
+ M18_24XX_KBR5,
+ R20_24XX_KBC0,
+ M14_24XX_KBC1,
+ H19_24XX_KBC2,
+ V17_24XX_KBC3,
+ P21_24XX_KBC4,
+ L14_24XX_KBC5,
+ N19_24XX_KBC6,
+
+ /* 24xx Menelaus Keypad GPIO */
+ B3__24XX_KBR5,
+ AA4_24XX_KBC2,
+ B13_24XX_KBC6,
};
#ifdef CONFIG_OMAP_MUX
diff --git a/include/asm-arm/arch-omap/omap-alsa.h b/include/asm-arm/arch-omap/omap-alsa.h
new file mode 100644
index 000000000000..df4695474e3d
--- /dev/null
+++ b/include/asm-arm/arch-omap/omap-alsa.h
@@ -0,0 +1,124 @@
+/*
+ * linux/include/asm-arm/arch-omap/omap-alsa.h
+ *
+ * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
+ *
+ * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ * {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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.
+ *
+ * History
+ * -------
+ *
+ * 2005/07/25 INdT-10LE Kernel Team - Alsa driver for omap osk,
+ * original version based in sa1100 driver
+ * and omap oss driver.
+ */
+
+#ifndef __OMAP_ALSA_H
+#define __OMAP_ALSA_H
+
+#include <sound/driver.h>
+#include <asm/arch/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <asm/arch/mcbsp.h>
+#include <linux/platform_device.h>
+
+#define DMA_BUF_SIZE (1024 * 8)
+
+/*
+ * Buffer management for alsa and dma
+ */
+struct audio_stream {
+ char *id; /* identification string */
+ int stream_id; /* numeric identification */
+ int dma_dev; /* dma number of that device */
+ int *lch; /* Chain of channels this stream is linked to */
+ char started; /* to store if the chain was started or not */
+ int dma_q_head; /* DMA Channel Q Head */
+ int dma_q_tail; /* DMA Channel Q Tail */
+ char dma_q_count; /* DMA Channel Q Count */
+ int active:1; /* we are using this stream for transfer now */
+ int period; /* current transfer period */
+ int periods; /* current count of periods registerd in the DMA engine */
+ spinlock_t dma_lock; /* for locking in DMA operations */
+ snd_pcm_substream_t *stream; /* the pcm stream */
+ unsigned linked:1; /* dma channels linked */
+ int offset; /* store start position of the last period in the alsa buffer */
+ int (*hw_start)(void); /* interface to start HW interface, e.g. McBSP */
+ int (*hw_stop)(void); /* interface to stop HW interface, e.g. McBSP */
+};
+
+/*
+ * Alsa card structure for aic23
+ */
+struct snd_card_omap_codec {
+ snd_card_t *card;
+ snd_pcm_t *pcm;
+ long samplerate;
+ struct audio_stream s[2]; /* playback & capture */
+};
+
+/* Codec specific information and function pointers.
+ * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c)
+ * are responsible for defining the function pointers.
+ */
+struct omap_alsa_codec_config {
+ char *name;
+ struct omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
+ snd_pcm_hw_constraint_list_t *hw_constraints_rates;
+ snd_pcm_hardware_t *snd_omap_alsa_playback;
+ snd_pcm_hardware_t *snd_omap_alsa_capture;
+ void (*codec_configure_dev)(void);
+ void (*codec_set_samplerate)(long);
+ void (*codec_clock_setup)(void);
+ int (*codec_clock_on)(void);
+ int (*codec_clock_off)(void);
+ int (*get_default_samplerate)(void);
+};
+
+/*********** Mixer function prototypes *************************/
+int snd_omap_mixer(struct snd_card_omap_codec *);
+void snd_omap_init_mixer(void);
+
+#ifdef CONFIG_PM
+void snd_omap_suspend_mixer(void);
+void snd_omap_resume_mixer(void);
+#endif
+
+int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config);
+int snd_omap_alsa_remove(struct platform_device *pdev);
+#ifdef CONFIG_PM
+int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state);
+int snd_omap_alsa_resume(struct platform_device *pdev);
+#else
+#define snd_omap_alsa_suspend NULL
+#define snd_omap_alsa_resume NULL
+#endif
+
+void callback_omap_alsa_sound_dma(void *);
+
+#endif
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h
index 4ba2622cc142..fccdb3db025f 100644
--- a/include/asm-arm/arch-omap/omapfb.h
+++ b/include/asm-arm/arch-omap/omapfb.h
@@ -34,9 +34,10 @@
#define OMAPFB_MIRROR OMAP_IOW(31, int)
#define OMAPFB_SYNC_GFX OMAP_IO(37)
#define OMAPFB_VSYNC OMAP_IO(38)
-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, enum omapfb_update_mode)
+#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
+#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old)
#define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long)
-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, enum omapfb_update_mode)
+#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
#define OMAPFB_UPDATE_WINDOW OMAP_IOW(47, struct omapfb_update_window)
@@ -66,9 +67,14 @@ enum omapfb_color_format {
};
struct omapfb_update_window {
- u32 x, y;
- u32 width, height;
- u32 format;
+ __u32 x, y;
+ __u32 width, height;
+ __u32 format;
+};
+
+struct omapfb_update_window_old {
+ __u32 x, y;
+ __u32 width, height;
};
enum omapfb_plane {
@@ -83,17 +89,17 @@ enum omapfb_channel_out {
};
struct omapfb_setup_plane {
- u8 plane;
- u8 channel_out;
- u32 offset;
- u32 pos_x, pos_y;
- u32 width, height;
- u32 color_mode;
+ __u8 plane;
+ __u8 channel_out;
+ __u32 offset;
+ __u32 pos_x, pos_y;
+ __u32 width, height;
+ __u32 color_mode;
};
struct omapfb_enable_plane {
- u8 plane;
- u8 enable;
+ __u8 plane;
+ __u8 enable;
};
enum omapfb_color_key_type {
@@ -103,10 +109,10 @@ enum omapfb_color_key_type {
};
struct omapfb_color_key {
- u8 channel_out;
- u32 background;
- u32 trans_key;
- u8 key_type;
+ __u8 channel_out;
+ __u32 background;
+ __u32 trans_key;
+ __u8 key_type;
};
enum omapfb_update_mode {
@@ -120,6 +126,9 @@ enum omapfb_update_mode {
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
+#include <linux/mutex.h>
+
+#include <asm/arch/board.h>
#define OMAP_LCDC_INV_VSYNC 0x0001
#define OMAP_LCDC_INV_HSYNC 0x0002
@@ -184,19 +193,38 @@ struct extif_timings {
int re_cycle_time;
int cs_pulse_width;
int access_time;
+
+ int clk_div;
+
+ u32 tim[5]; /* set by extif->convert_timings */
+
+ int converted;
};
struct lcd_ctrl_extif {
int (*init) (void);
void (*cleanup) (void);
+ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
+ int (*convert_timings) (struct extif_timings *timings);
void (*set_timings) (const struct extif_timings *timings);
- void (*write_command) (u32 cmd);
- u32 (*read_data) (void);
- void (*write_data) (u32 data);
+ void (*set_bits_per_cycle)(int bpc);
+ void (*write_command) (const void *buf, unsigned int len);
+ void (*read_data) (void *buf, unsigned int len);
+ void (*write_data) (const void *buf, unsigned int len);
void (*transfer_area) (int width, int height,
void (callback)(void * data), void *data);
+ unsigned long max_transmit_size;
};
+struct omapfb_notifier_block {
+ struct notifier_block nb;
+ void *data;
+};
+
+typedef int (*omapfb_notifier_callback_t)(struct omapfb_notifier_block *,
+ unsigned long event,
+ struct omapfb_device *fbdev);
+
struct lcd_ctrl {
const char *name;
void *data;
@@ -204,9 +232,11 @@ struct lcd_ctrl {
int (*init) (struct omapfb_device *fbdev,
int ext_mode, int req_vram_size);
void (*cleanup) (void);
+ void (*bind_client) (struct omapfb_notifier_block *nb);
void (*get_vram_layout)(unsigned long *size,
void **virt_base,
dma_addr_t *phys_base);
+ int (*mmap) (struct vm_area_struct *vma);
unsigned long (*get_caps) (void);
int (*set_update_mode)(enum omapfb_update_mode mode);
enum omapfb_update_mode (*get_update_mode)(void);
@@ -240,7 +270,7 @@ struct omapfb_device {
int state;
int ext_lcdc; /* Using external
LCD controller */
- struct semaphore rqueue_sema;
+ struct mutex rqueue_mutex;
void *vram_virt_base;
dma_addr_t vram_phys_base;
@@ -261,12 +291,13 @@ struct omapfb_device {
struct device *dev;
};
-extern struct lcd_panel h3_panel;
-extern struct lcd_panel h2_panel;
-extern struct lcd_panel p2_panel;
-extern struct lcd_panel osk_panel;
-extern struct lcd_panel innovator1610_panel;
-extern struct lcd_panel innovator1510_panel;
+struct omapfb_platform_data {
+ struct omap_lcd_config lcd;
+ struct omap_fbmem_config fbmem;
+};
+
+#define OMAPFB_EVENT_READY 1
+#define OMAPFB_EVENT_DISABLED 2
#ifdef CONFIG_ARCH_OMAP1
extern struct lcd_ctrl omap1_lcd_ctrl;
@@ -274,7 +305,20 @@ extern struct lcd_ctrl omap1_lcd_ctrl;
extern struct lcd_ctrl omap2_disp_ctrl;
#endif
+extern void omapfb_register_panel(struct lcd_panel *panel);
extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+ unsigned long event);
+extern int omapfb_register_client(struct omapfb_notifier_block *nb,
+ omapfb_notifier_callback_t callback,
+ void *callback_data);
+extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
+extern int omapfb_update_window_async(struct omapfb_update_window *win,
+ void (*callback)(void *),
+ void *callback_data);
+
+/* in arch/arm/plat-omap/devices.c */
+extern void omapfb_reserve_mem(void);
#endif /* __KERNEL__ */
diff --git a/include/asm-arm/arch-omap/param.h b/include/asm-arm/arch-omap/param.h
new file mode 100644
index 000000000000..face9ad41e97
--- /dev/null
+++ b/include/asm-arm/arch-omap/param.h
@@ -0,0 +1,8 @@
+/*
+ * linux/include/asm-arm/arch-omap/param.h
+ *
+ */
+
+#ifdef CONFIG_OMAP_32K_TIMER_HZ
+#define HZ CONFIG_OMAP_32K_TIMER_HZ
+#endif
diff --git a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h
index 7c790425e363..05b003f3a94c 100644
--- a/include/asm-arm/arch-omap/pm.h
+++ b/include/asm-arm/arch-omap/pm.h
@@ -49,7 +49,7 @@
/*
* ----------------------------------------------------------------------------
- * Powermanagement bitmasks
+ * Power management bitmasks
* ----------------------------------------------------------------------------
*/
#define IDLE_WAIT_CYCLES 0x00000fff
@@ -112,32 +112,59 @@
#endif
#ifndef __ASSEMBLER__
+
+#include <linux/clk.h>
+
+extern void prevent_idle_sleep(void);
+extern void allow_idle_sleep(void);
+
+/**
+ * clk_deny_idle - Prevents the clock from being idled during MPU idle
+ * @clk: clock signal handle
+ */
+void clk_deny_idle(struct clk *clk);
+
+/**
+ * clk_allow_idle - Counters previous clk_deny_idle
+ * @clk: clock signal handle
+ */
+void clk_deny_idle(struct clk *clk);
+
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
extern void omap730_cpu_suspend(unsigned short, unsigned short);
extern void omap1510_cpu_suspend(unsigned short, unsigned short);
extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, u32 cpu_revision);
extern void omap730_idle_loop_suspend(void);
extern void omap1510_idle_loop_suspend(void);
extern void omap1610_idle_loop_suspend(void);
+extern void omap24xx_idle_loop_suspend(void);
+
+extern unsigned int omap730_cpu_suspend_sz;
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap24xx_cpu_suspend_sz;
+extern unsigned int omap730_idle_loop_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+extern unsigned int omap24xx_idle_loop_suspend_sz;
#ifdef CONFIG_OMAP_SERIAL_WAKE
extern void omap_serial_wake_trigger(int enable);
#else
+#define omap_serial_wakeup_init() {}
#define omap_serial_wake_trigger(x) {}
#endif /* CONFIG_OMAP_SERIAL_WAKE */
-extern unsigned int omap730_cpu_suspend_sz;
-extern unsigned int omap730_idle_loop_suspend_sz;
-extern unsigned int omap1510_cpu_suspend_sz;
-extern unsigned int omap1510_idle_loop_suspend_sz;
-extern unsigned int omap1610_cpu_suspend_sz;
-extern unsigned int omap1610_idle_loop_suspend_sz;
-
#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
+#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
+#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
+#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
+
#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
@@ -154,6 +181,10 @@ extern unsigned int omap1610_idle_loop_suspend_sz;
#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
+#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x
+#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+
/*
* List of global OMAP registers to preserve.
* More ones like CP and general purpose register values are preserved
@@ -176,6 +207,15 @@ enum arm_save_state {
ARM_SLEEP_SAVE_SIZE
};
+enum dsp_save_state {
+ DSP_SLEEP_SAVE_START = 0,
+ /*
+ * DSP registers 16 bits
+ */
+ DSP_SLEEP_SAVE_DSP_IDLECT2,
+ DSP_SLEEP_SAVE_SIZE
+};
+
enum ulpd_save_state {
ULPD_SLEEP_SAVE_START = 0,
/*
@@ -254,5 +294,30 @@ enum mpui1610_save_state {
#endif
};
+enum omap24xx_save_state {
+ OMAP24XX_SLEEP_SAVE_START = 0,
+ OMAP24XX_SLEEP_SAVE_INTC_MIR0,
+ OMAP24XX_SLEEP_SAVE_INTC_MIR1,
+ OMAP24XX_SLEEP_SAVE_INTC_MIR2,
+ OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE,
+ OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO3_OE,
+ OMAP24XX_SLEEP_SAVE_GPIO4_OE,
+ OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT,
+ OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0,
+ OMAP24XX_SLEEP_SAVE_SIZE
+};
+
#endif /* ASSEMBLER */
#endif /* __ASM_ARCH_OMAP_PM_H */
diff --git a/include/asm-arm/arch-omap/prcm.h b/include/asm-arm/arch-omap/prcm.h
index 7b48a5cbb15f..7bcaf94bde9f 100644
--- a/include/asm-arm/arch-omap/prcm.h
+++ b/include/asm-arm/arch-omap/prcm.h
@@ -1,5 +1,7 @@
/*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/include/asm-arm/arch-omap/prcm.h
+ *
+ * Access definations for use in OMAP24XX clock and power management
*
* Copyright (C) 2005 Texas Instruments, Inc.
*
@@ -21,405 +23,7 @@
#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
#define __ASM_ARM_ARCH_DPM_PRCM_H
-/* SET_PERFORMANCE_LEVEL PARAMETERS */
-#define PRCM_HALF_SPEED 1
-#define PRCM_FULL_SPEED 2
-
-#ifndef __ASSEMBLER__
-
-#define PRCM_REG32(offset) __REG32(OMAP24XX_PRCM_BASE + (offset))
-
-#define PRCM_REVISION PRCM_REG32(0x000)
-#define PRCM_SYSCONFIG PRCM_REG32(0x010)
-#define PRCM_IRQSTATUS_MPU PRCM_REG32(0x018)
-#define PRCM_IRQENABLE_MPU PRCM_REG32(0x01C)
-#define PRCM_VOLTCTRL PRCM_REG32(0x050)
-#define PRCM_VOLTST PRCM_REG32(0x054)
-#define PRCM_CLKSRC_CTRL PRCM_REG32(0x060)
-#define PRCM_CLKOUT_CTRL PRCM_REG32(0x070)
-#define PRCM_CLKEMUL_CTRL PRCM_REG32(0x078)
-#define PRCM_CLKCFG_CTRL PRCM_REG32(0x080)
-#define PRCM_CLKCFG_STATUS PRCM_REG32(0x084)
-#define PRCM_VOLTSETUP PRCM_REG32(0x090)
-#define PRCM_CLKSSETUP PRCM_REG32(0x094)
-#define PRCM_POLCTRL PRCM_REG32(0x098)
-
-/* GENERAL PURPOSE */
-#define GENERAL_PURPOSE1 PRCM_REG32(0x0B0)
-#define GENERAL_PURPOSE2 PRCM_REG32(0x0B4)
-#define GENERAL_PURPOSE3 PRCM_REG32(0x0B8)
-#define GENERAL_PURPOSE4 PRCM_REG32(0x0BC)
-#define GENERAL_PURPOSE5 PRCM_REG32(0x0C0)
-#define GENERAL_PURPOSE6 PRCM_REG32(0x0C4)
-#define GENERAL_PURPOSE7 PRCM_REG32(0x0C8)
-#define GENERAL_PURPOSE8 PRCM_REG32(0x0CC)
-#define GENERAL_PURPOSE9 PRCM_REG32(0x0D0)
-#define GENERAL_PURPOSE10 PRCM_REG32(0x0D4)
-#define GENERAL_PURPOSE11 PRCM_REG32(0x0D8)
-#define GENERAL_PURPOSE12 PRCM_REG32(0x0DC)
-#define GENERAL_PURPOSE13 PRCM_REG32(0x0E0)
-#define GENERAL_PURPOSE14 PRCM_REG32(0x0E4)
-#define GENERAL_PURPOSE15 PRCM_REG32(0x0E8)
-#define GENERAL_PURPOSE16 PRCM_REG32(0x0EC)
-#define GENERAL_PURPOSE17 PRCM_REG32(0x0F0)
-#define GENERAL_PURPOSE18 PRCM_REG32(0x0F4)
-#define GENERAL_PURPOSE19 PRCM_REG32(0x0F8)
-#define GENERAL_PURPOSE20 PRCM_REG32(0x0FC)
-
-/* MPU */
-#define CM_CLKSEL_MPU PRCM_REG32(0x140)
-#define CM_CLKSTCTRL_MPU PRCM_REG32(0x148)
-#define RM_RSTST_MPU PRCM_REG32(0x158)
-#define PM_WKDEP_MPU PRCM_REG32(0x1C8)
-#define PM_EVGENCTRL_MPU PRCM_REG32(0x1D4)
-#define PM_EVEGENONTIM_MPU PRCM_REG32(0x1D8)
-#define PM_EVEGENOFFTIM_MPU PRCM_REG32(0x1DC)
-#define PM_PWSTCTRL_MPU PRCM_REG32(0x1E0)
-#define PM_PWSTST_MPU PRCM_REG32(0x1E4)
-
-/* CORE */
-#define CM_FCLKEN1_CORE PRCM_REG32(0x200)
-#define CM_FCLKEN2_CORE PRCM_REG32(0x204)
-#define CM_FCLKEN3_CORE PRCM_REG32(0x208)
-#define CM_ICLKEN1_CORE PRCM_REG32(0x210)
-#define CM_ICLKEN2_CORE PRCM_REG32(0x214)
-#define CM_ICLKEN3_CORE PRCM_REG32(0x218)
-#define CM_ICLKEN4_CORE PRCM_REG32(0x21C)
-#define CM_IDLEST1_CORE PRCM_REG32(0x220)
-#define CM_IDLEST2_CORE PRCM_REG32(0x224)
-#define CM_IDLEST3_CORE PRCM_REG32(0x228)
-#define CM_IDLEST4_CORE PRCM_REG32(0x22C)
-#define CM_AUTOIDLE1_CORE PRCM_REG32(0x230)
-#define CM_AUTOIDLE2_CORE PRCM_REG32(0x234)
-#define CM_AUTOIDLE3_CORE PRCM_REG32(0x238)
-#define CM_AUTOIDLE4_CORE PRCM_REG32(0x23C)
-#define CM_CLKSEL1_CORE PRCM_REG32(0x240)
-#define CM_CLKSEL2_CORE PRCM_REG32(0x244)
-#define CM_CLKSTCTRL_CORE PRCM_REG32(0x248)
-#define PM_WKEN1_CORE PRCM_REG32(0x2A0)
-#define PM_WKEN2_CORE PRCM_REG32(0x2A4)
-#define PM_WKST1_CORE PRCM_REG32(0x2B0)
-#define PM_WKST2_CORE PRCM_REG32(0x2B4)
-#define PM_WKDEP_CORE PRCM_REG32(0x2C8)
-#define PM_PWSTCTRL_CORE PRCM_REG32(0x2E0)
-#define PM_PWSTST_CORE PRCM_REG32(0x2E4)
-
-/* GFX */
-#define CM_FCLKEN_GFX PRCM_REG32(0x300)
-#define CM_ICLKEN_GFX PRCM_REG32(0x310)
-#define CM_IDLEST_GFX PRCM_REG32(0x320)
-#define CM_CLKSEL_GFX PRCM_REG32(0x340)
-#define CM_CLKSTCTRL_GFX PRCM_REG32(0x348)
-#define RM_RSTCTRL_GFX PRCM_REG32(0x350)
-#define RM_RSTST_GFX PRCM_REG32(0x358)
-#define PM_WKDEP_GFX PRCM_REG32(0x3C8)
-#define PM_PWSTCTRL_GFX PRCM_REG32(0x3E0)
-#define PM_PWSTST_GFX PRCM_REG32(0x3E4)
-
-/* WAKE-UP */
-#define CM_FCLKEN_WKUP PRCM_REG32(0x400)
-#define CM_ICLKEN_WKUP PRCM_REG32(0x410)
-#define CM_IDLEST_WKUP PRCM_REG32(0x420)
-#define CM_AUTOIDLE_WKUP PRCM_REG32(0x430)
-#define CM_CLKSEL_WKUP PRCM_REG32(0x440)
-#define RM_RSTCTRL_WKUP PRCM_REG32(0x450)
-#define RM_RSTTIME_WKUP PRCM_REG32(0x454)
-#define RM_RSTST_WKUP PRCM_REG32(0x458)
-#define PM_WKEN_WKUP PRCM_REG32(0x4A0)
-#define PM_WKST_WKUP PRCM_REG32(0x4B0)
-
-/* CLOCKS */
-#define CM_CLKEN_PLL PRCM_REG32(0x500)
-#define CM_IDLEST_CKGEN PRCM_REG32(0x520)
-#define CM_AUTOIDLE_PLL PRCM_REG32(0x530)
-#define CM_CLKSEL1_PLL PRCM_REG32(0x540)
-#define CM_CLKSEL2_PLL PRCM_REG32(0x544)
-
-/* DSP */
-#define CM_FCLKEN_DSP PRCM_REG32(0x800)
-#define CM_ICLKEN_DSP PRCM_REG32(0x810)
-#define CM_IDLEST_DSP PRCM_REG32(0x820)
-#define CM_AUTOIDLE_DSP PRCM_REG32(0x830)
-#define CM_CLKSEL_DSP PRCM_REG32(0x840)
-#define CM_CLKSTCTRL_DSP PRCM_REG32(0x848)
-#define RM_RSTCTRL_DSP PRCM_REG32(0x850)
-#define RM_RSTST_DSP PRCM_REG32(0x858)
-#define PM_WKEN_DSP PRCM_REG32(0x8A0)
-#define PM_WKDEP_DSP PRCM_REG32(0x8C8)
-#define PM_PWSTCTRL_DSP PRCM_REG32(0x8E0)
-#define PM_PWSTST_DSP PRCM_REG32(0x8E4)
-#define PRCM_IRQSTATUS_DSP PRCM_REG32(0x8F0)
-#define PRCM_IRQENABLE_DSP PRCM_REG32(0x8F4)
-
-/* IVA */
-#define PRCM_IRQSTATUS_IVA PRCM_REG32(0x8F8)
-#define PRCM_IRQENABLE_IVA PRCM_REG32(0x8FC)
-
-/* Modem on 2430 */
-#define CM_FCLKEN_MDM PRCM_REG32(0xC00)
-#define CM_ICLKEN_MDM PRCM_REG32(0xC10)
-#define CM_IDLEST_MDM PRCM_REG32(0xC20)
-#define CM_CLKSEL_MDM PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000)
-#define DISP_REG32(offset) __REG32(DISP_BASE + (offset))
-
-#define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000)
-#define GPMC_BASE (OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset))
-
-#define GPT1_BASE (OMAP24XX_GPT1)
-#define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset))
-
-/* Misc sysconfig */
-#define DISPC_SYSCONFIG DISP_REG32(0x410)
-#define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000)
-#define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG 0x5A000010
-#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG 0x5D000010
-//#define DSP_DMA_SYSCONFIG 0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C)
-#define GPMC_SYSCONFIG GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG 0x5C060010
-#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG 0x67FFFE10
-
-/* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000)
-
-#define GPTIMER1_SYSCONFIG GPT1_REG32(0x010)
-#define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10)
-#define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10)
-#define GPTIMER4_SYSCONFIG __REG32(OMAP24XX_GPT4 + 0x10)
-#define GPTIMER5_SYSCONFIG __REG32(OMAP24XX_GPT5 + 0x10)
-#define GPTIMER6_SYSCONFIG __REG32(OMAP24XX_GPT6 + 0x10)
-#define GPTIMER7_SYSCONFIG __REG32(OMAP24XX_GPT7 + 0x10)
-#define GPTIMER8_SYSCONFIG __REG32(OMAP24XX_GPT8 + 0x10)
-#define GPTIMER9_SYSCONFIG __REG32(OMAP24XX_GPT9 + 0x10)
-#define GPTIMER10_SYSCONFIG __REG32(OMAP24XX_GPT10 + 0x10)
-#define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10)
-#define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10)
-
-#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
-
-#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10))
-
-/* GP TIMER 1 */
-#define GPTIMER1_TISTAT GPT1_REG32(0x014)
-#define GPTIMER1_TISR GPT1_REG32(0x018)
-#define GPTIMER1_TIER GPT1_REG32(0x01C)
-#define GPTIMER1_TWER GPT1_REG32(0x020)
-#define GPTIMER1_TCLR GPT1_REG32(0x024)
-#define GPTIMER1_TCRR GPT1_REG32(0x028)
-#define GPTIMER1_TLDR GPT1_REG32(0x02C)
-#define GPTIMER1_TTGR GPT1_REG32(0x030)
-#define GPTIMER1_TWPS GPT1_REG32(0x034)
-#define GPTIMER1_TMAR GPT1_REG32(0x038)
-#define GPTIMER1_TCAR1 GPT1_REG32(0x03C)
-#define GPTIMER1_TSICR GPT1_REG32(0x040)
-#define GPTIMER1_TCAR2 GPT1_REG32(0x044)
-
-/* rkw -- base fix up please... */
-#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018)
-
-/* SDRC */
-#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084)
-
-/* GPIO 1 */
-#define GPIO1_BASE GPIOX_BASE(1)
-#define GPIO1_REG32(offset) __REG32(GPIO1_BASE + (offset))
-#define GPIO1_IRQENABLE1 GPIO1_REG32(0x01C)
-#define GPIO1_IRQSTATUS1 GPIO1_REG32(0x018)
-#define GPIO1_IRQENABLE2 GPIO1_REG32(0x02C)
-#define GPIO1_IRQSTATUS2 GPIO1_REG32(0x028)
-#define GPIO1_WAKEUPENABLE GPIO1_REG32(0x020)
-#define GPIO1_RISINGDETECT GPIO1_REG32(0x048)
-#define GPIO1_DATAIN GPIO1_REG32(0x038)
-#define GPIO1_OE GPIO1_REG32(0x034)
-#define GPIO1_DATAOUT GPIO1_REG32(0x03C)
-
-/* GPIO2 */
-#define GPIO2_BASE GPIOX_BASE(2)
-#define GPIO2_REG32(offset) __REG32(GPIO2_BASE + (offset))
-#define GPIO2_IRQENABLE1 GPIO2_REG32(0x01C)
-#define GPIO2_IRQSTATUS1 GPIO2_REG32(0x018)
-#define GPIO2_IRQENABLE2 GPIO2_REG32(0x02C)
-#define GPIO2_IRQSTATUS2 GPIO2_REG32(0x028)
-#define GPIO2_WAKEUPENABLE GPIO2_REG32(0x020)
-#define GPIO2_RISINGDETECT GPIO2_REG32(0x048)
-#define GPIO2_DATAIN GPIO2_REG32(0x038)
-#define GPIO2_OE GPIO2_REG32(0x034)
-#define GPIO2_DATAOUT GPIO2_REG32(0x03C)
-
-/* GPIO 3 */
-#define GPIO3_BASE GPIOX_BASE(3)
-#define GPIO3_REG32(offset) __REG32(GPIO3_BASE + (offset))
-#define GPIO3_IRQENABLE1 GPIO3_REG32(0x01C)
-#define GPIO3_IRQSTATUS1 GPIO3_REG32(0x018)
-#define GPIO3_IRQENABLE2 GPIO3_REG32(0x02C)
-#define GPIO3_IRQSTATUS2 GPIO3_REG32(0x028)
-#define GPIO3_WAKEUPENABLE GPIO3_REG32(0x020)
-#define GPIO3_RISINGDETECT GPIO3_REG32(0x048)
-#define GPIO3_FALLINGDETECT GPIO3_REG32(0x04C)
-#define GPIO3_DATAIN GPIO3_REG32(0x038)
-#define GPIO3_OE GPIO3_REG32(0x034)
-#define GPIO3_DATAOUT GPIO3_REG32(0x03C)
-#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
-#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
-
-/* GPIO 4 */
-#define GPIO4_BASE GPIOX_BASE(4)
-#define GPIO4_REG32(offset) __REG32(GPIO4_BASE + (offset))
-#define GPIO4_IRQENABLE1 GPIO4_REG32(0x01C)
-#define GPIO4_IRQSTATUS1 GPIO4_REG32(0x018)
-#define GPIO4_IRQENABLE2 GPIO4_REG32(0x02C)
-#define GPIO4_IRQSTATUS2 GPIO4_REG32(0x028)
-#define GPIO4_WAKEUPENABLE GPIO4_REG32(0x020)
-#define GPIO4_RISINGDETECT GPIO4_REG32(0x048)
-#define GPIO4_FALLINGDETECT GPIO4_REG32(0x04C)
-#define GPIO4_DATAIN GPIO4_REG32(0x038)
-#define GPIO4_OE GPIO4_REG32(0x034)
-#define GPIO4_DATAOUT GPIO4_REG32(0x03C)
-#define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050)
-#define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054)
-
-
-/* IO CONFIG */
-#define CONTROL_BASE (OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset))
-
-#define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104)
-#define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134)
-#define CONTROL_PADCONF_UART1_RX CONTROL_REG32(0x0C8)
-#define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C)
-#define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090)
-#define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC)
-#define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0)
-#define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC)
-
-/* CONTROL */
-#define CONTROL_DEVCONF CONTROL_REG32(0x274)
-
-/* INTERRUPT CONTROLLER */
-#define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000)
-#define INTC_REG32(offset) __REG32(INTC_BASE + (offset))
-
-#define INTC1_U_BASE INTC_REG32(0x000)
-#define INTC_MIR0 INTC_REG32(0x084)
-#define INTC_MIR_SET0 INTC_REG32(0x08C)
-#define INTC_MIR_CLEAR0 INTC_REG32(0x088)
-#define INTC_ISR_CLEAR0 INTC_REG32(0x094)
-#define INTC_MIR1 INTC_REG32(0x0A4)
-#define INTC_MIR_SET1 INTC_REG32(0x0AC)
-#define INTC_MIR_CLEAR1 INTC_REG32(0x0A8)
-#define INTC_ISR_CLEAR1 INTC_REG32(0x0B4)
-#define INTC_MIR2 INTC_REG32(0x0C4)
-#define INTC_MIR_SET2 INTC_REG32(0x0CC)
-#define INTC_MIR_CLEAR2 INTC_REG32(0x0C8)
-#define INTC_ISR_CLEAR2 INTC_REG32(0x0D4)
-#define INTC_SIR_IRQ INTC_REG32(0x040)
-#define INTC_CONTROL INTC_REG32(0x048)
-#define INTC_ILR11 INTC_REG32(0x12C)
-#define INTC_ILR32 INTC_REG32(0x180)
-#define INTC_ILR37 INTC_REG32(0x194)
-#define INTC_SYSCONFIG INTC_REG32(0x010)
-
-/* RAM FIREWALL */
-#define RAMFW_BASE (0x68005000)
-#define RAMFW_REG32(offset) __REG32(RAMFW_BASE + (offset))
-
-#define RAMFW_REQINFOPERM0 RAMFW_REG32(0x048)
-#define RAMFW_READPERM0 RAMFW_REG32(0x050)
-#define RAMFW_WRITEPERM0 RAMFW_REG32(0x058)
-
-/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
-//#define DEBUG_BOARD_LED_REGISTER 0x04000014
-
-/* GPMC CS0 */
-#define GPMC_CONFIG1_0 GPMC_REG32(0x060)
-#define GPMC_CONFIG2_0 GPMC_REG32(0x064)
-#define GPMC_CONFIG3_0 GPMC_REG32(0x068)
-#define GPMC_CONFIG4_0 GPMC_REG32(0x06C)
-#define GPMC_CONFIG5_0 GPMC_REG32(0x070)
-#define GPMC_CONFIG6_0 GPMC_REG32(0x074)
-#define GPMC_CONFIG7_0 GPMC_REG32(0x078)
-
-/* GPMC CS1 */
-#define GPMC_CONFIG1_1 GPMC_REG32(0x090)
-#define GPMC_CONFIG2_1 GPMC_REG32(0x094)
-#define GPMC_CONFIG3_1 GPMC_REG32(0x098)
-#define GPMC_CONFIG4_1 GPMC_REG32(0x09C)
-#define GPMC_CONFIG5_1 GPMC_REG32(0x0a0)
-#define GPMC_CONFIG6_1 GPMC_REG32(0x0a4)
-#define GPMC_CONFIG7_1 GPMC_REG32(0x0a8)
-
-/* DSS */
-#define DSS_CONTROL DISP_REG32(0x040)
-#define DISPC_CONTROL DISP_REG32(0x440)
-#define DISPC_SYSSTATUS DISP_REG32(0x414)
-#define DISPC_IRQSTATUS DISP_REG32(0x418)
-#define DISPC_IRQENABLE DISP_REG32(0x41C)
-#define DISPC_CONFIG DISP_REG32(0x444)
-#define DISPC_DEFAULT_COLOR0 DISP_REG32(0x44C)
-#define DISPC_DEFAULT_COLOR1 DISP_REG32(0x450)
-#define DISPC_TRANS_COLOR0 DISP_REG32(0x454)
-#define DISPC_TRANS_COLOR1 DISP_REG32(0x458)
-#define DISPC_LINE_NUMBER DISP_REG32(0x460)
-#define DISPC_TIMING_H DISP_REG32(0x464)
-#define DISPC_TIMING_V DISP_REG32(0x468)
-#define DISPC_POL_FREQ DISP_REG32(0x46C)
-#define DISPC_DIVISOR DISP_REG32(0x470)
-#define DISPC_SIZE_DIG DISP_REG32(0x478)
-#define DISPC_SIZE_LCD DISP_REG32(0x47C)
-#define DISPC_GFX_BA0 DISP_REG32(0x480)
-#define DISPC_GFX_BA1 DISP_REG32(0x484)
-#define DISPC_GFX_POSITION DISP_REG32(0x488)
-#define DISPC_GFX_SIZE DISP_REG32(0x48C)
-#define DISPC_GFX_ATTRIBUTES DISP_REG32(0x4A0)
-#define DISPC_GFX_FIFO_THRESHOLD DISP_REG32(0x4A4)
-#define DISPC_GFX_ROW_INC DISP_REG32(0x4AC)
-#define DISPC_GFX_PIXEL_INC DISP_REG32(0x4B0)
-#define DISPC_GFX_WINDOW_SKIP DISP_REG32(0x4B4)
-#define DISPC_GFX_TABLE_BA DISP_REG32(0x4B8)
-#define DISPC_DATA_CYCLE1 DISP_REG32(0x5D4)
-#define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8)
-#define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC)
-
-/* Wake up define for board */
-#define GPIO97 (1 << 1)
-#define GPIO88 (1 << 24)
-
-#endif /* __ASSEMBLER__ */
+u32 omap_prcm_get_reset_sources(void);
#endif
diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h
index e72ccbf0fe06..6fc0dd57b7c3 100644
--- a/include/asm-arm/arch-omap/sram.h
+++ b/include/asm-arm/arch-omap/sram.h
@@ -20,6 +20,8 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
u32 mem_type);
extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+extern unsigned long omap_fb_sram_start;
+extern unsigned long omap_fb_sram_size;
/* Do not use these */
extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h
index 6724a81bd10b..67970d1a2020 100644
--- a/include/asm-arm/arch-omap/system.h
+++ b/include/asm-arm/arch-omap/system.h
@@ -9,12 +9,13 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
-#include <asm/arch/prcm.h>
#ifndef CONFIG_MACH_VOICEBLUE
#define voiceblue_reset() do {} while (0)
#endif
+extern void omap_prcm_arch_reset(char mode);
+
static inline void arch_idle(void)
{
cpu_do_idle();
@@ -38,24 +39,12 @@ static inline void omap1_arch_reset(char mode)
omap_writew(1, ARM_RSTCT1);
}
-static inline void omap2_arch_reset(char mode)
-{
- u32 rate;
- struct clk *vclk, *sclk;
-
- vclk = clk_get(NULL, "virt_prcm_set");
- sclk = clk_get(NULL, "sys_ck");
- rate = clk_get_rate(sclk);
- clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */
- RM_RSTCTRL_WKUP |= 2;
-}
-
static inline void arch_reset(char mode)
{
if (!cpu_is_omap24xx())
omap1_arch_reset(mode);
else
- omap2_arch_reset(mode);
+ omap_prcm_arch_reset(mode);
}
#endif
diff --git a/include/asm-arm/arch-rpc/hardware.h b/include/asm-arm/arch-rpc/hardware.h
index 9d7f87375aa7..7480f4e8d974 100644
--- a/include/asm-arm/arch-rpc/hardware.h
+++ b/include/asm-arm/arch-rpc/hardware.h
@@ -46,7 +46,6 @@
#define SCREEN_END 0xdfc00000
#define SCREEN_BASE 0xdf800000
-#define FLUSH_BASE 0xdf000000
#define UNCACHEABLE_ADDR 0xdf010000
/*
@@ -59,8 +58,6 @@
#define PCIO_BASE IOMEM(0xe0010000)
#define FLOPPYDMA_BASE IOMEM(0xe002a000)
-#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
-
#define vidc_writel(val) __raw_writel(val, VIDC_BASE)
#define IO_EC_EASI_BASE 0x81400000
diff --git a/include/asm-arm/arch-rpc/memory.h b/include/asm-arm/arch-rpc/memory.h
index 0592cb3f0c74..303c424ce673 100644
--- a/include/asm-arm/arch-rpc/memory.h
+++ b/include/asm-arm/arch-rpc/memory.h
@@ -30,4 +30,10 @@
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS 0x00000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index cc06b1bd37b2..894c35cf3b1e 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -6,116 +6,83 @@
* 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.
+*/
+
+/* We have a problem that the INTOFFSET register does not always
+ * show one interrupt. Occasionally we get two interrupts through
+ * the prioritiser, and this causes the INTOFFSET register to show
+ * what looks like the logical-or of the two interrupt numbers.
+ *
+ * Thanks to Klaus, Shannon, et al for helping to debug this problem
+*/
+
+#define INTPND (0x10)
+#define INTOFFSET (0x14)
+#define EXTINTPEND (0xa8)
+#define EXTINTMASK (0xa4)
- * Modifications:
- * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- */
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
-
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mov \tmp, #S3C24XX_VA_IRQ
- ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
-30000:
- teq \irqnr, #4
- teqne \irqnr, #5
- beq 1002f @ external irq reg
-
- @ debug check to see if interrupt reported is the same
- @ as the offset....
-
- teq \irqnr, #0
- beq 20002f
- ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
- mov \irqstat, \irqstat, lsr \irqnr
- tst \irqstat, #1
- bne 20002f
-
- /* debug/warning if we get an invalud response from the
- * INTOFFSET register */
-#if 1
- stmfd r13!, { r0 - r4 , r8-r12, r14 }
- ldr r1, [ \tmp, #0x14 ] @ INTOFFSET
- ldr r2, [ \tmp, #0x10 ] @ INTPND
- ldr r3, [ \tmp, #0x00 ] @ SRCPND
- adr r0, 20003f
- bl printk
- b 20004f
-
-20003:
- .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
- .byte 0
- .align 4
-20004:
- mov r1, #1
- mov \tmp, #S3C24XX_VA_IRQ
- ldmfd r13!, { r0 - r4 , r8-r12, r14 }
-#endif
-
- @ try working out interrupt number for ourselves
- mov \irqnr, #0
- ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
-10021:
- movs \irqstat, \irqstat, lsr#1
- bcs 30000b @ try and re-start the proccess
- add \irqnr, \irqnr, #1
- cmp \irqnr, #32
- ble 10021b
-
- @ found no interrupt, set Z flag and leave
- movs \irqnr, #0
- b 1001f
-
-20005:
-20002: @ exit
- @ we base the s3c2410x interrupts at 16 and above to allow
- @ isa peripherals to have their standard interrupts, also
- @ ensure that Z flag is un-set on exit
-
- @ note, we cannot be sure if we get IRQ_EINT0 (0) that
- @ there is simply no interrupt pending, so in all other
- @ cases we jump to say we have found something, otherwise
- @ we check to see if the interrupt really is assrted
- adds \irqnr, \irqnr, #IRQ_EINT0
- teq \irqnr, #IRQ_EINT0
- bne 1001f @ exit
- ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
- teq \irqstat, #0
- moveq \irqnr, #0
- b 1001f
-
- @ we get here from no main or external interrupts pending
-1002:
- add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
- ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND
- ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK
-
- bic \irqstat, \irqstat, \irqnr @ clear masked irqs
-
- mov \irqnr, #IRQ_EINT4 @ start extint nos
- mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits
-10021:
- movs \irqstat, \irqstat, lsr#1
- bcs 1004f
- add \irqnr, \irqnr, #1
- cmp \irqnr, #IRQ_EINT23
- ble 10021b
-
- @ found no interrupt, set Z flag and leave
- movs \irqnr, #0
-
-1004: @ ensure Z flag clear in case our MOVS shifted out the last bit
- teq \irqnr, #0
+ mov \base, #S3C24XX_VA_IRQ
+
+ ldr \irqstat, [ \base, #INTPND]
+ bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ
+ beq 2000f
+
+ @@ try the interrupt offset register, since it is there
+
+ ldr \irqnr, [ \base, #INTOFFSET ]
+ mov \tmp, #1
+ tst \irqstat, \tmp, lsl \irqnr
+ addne \irqnr, \irqnr, #IRQ_EINT0
+ bne 1001f
+
+ @@ the number specified is not a valid irq, so try
+ @@ and work it out for ourselves
+
+ mov \irqnr, #IRQ_EINT0 @@ start here
+ b 3000f
+
+2000:
+ @@ load the GPIO interrupt register, and check it
+
+ add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
+ ldr \irqstat, [ \tmp, # EXTINTPEND ]
+ ldr \irqnr, [ \tmp, # EXTINTMASK ]
+ bics \irqstat, \irqstat, \irqnr
+ beq 1001f
+
+ mov \irqnr, #(IRQ_EINT4 - 4)
+
+ @@ work out which irq (if any) we got
+3000:
+ movs \tmp, \irqstat, lsl#16
+ addeq \irqnr, \irqnr, #16
+ moveq \irqstat, \irqstat, lsr#16
+ tst \irqstat, #0xff
+ addeq \irqnr, \irqnr, #8
+ moveq \irqstat, \irqstat, lsr#8
+ tst \irqstat, #0xf
+ addeq \irqnr, \irqnr, #4
+ moveq \irqstat, \irqstat, lsr#4
+ tst \irqstat, #0x3
+ addeq \irqnr, \irqnr, #2
+ moveq \irqstat, \irqstat, lsr#2
+ tst \irqstat, #0x1
+ addeq \irqnr, \irqnr, #1
+
+ @@ we have the value
+ movs \irqnr, \irqnr
+
1001:
- @ exit irq routine
- .endm
+ @@ exit here, Z flag unset if IRQ
+ .endm
/* currently don't need an disable_fiq macro */
.macro disable_fiq
.endm
-
-
diff --git a/include/asm-arm/arch-s3c2410/leds-gpio.h b/include/asm-arm/arch-s3c2410/leds-gpio.h
new file mode 100644
index 000000000000..f07ed040622b
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/leds-gpio.h
@@ -0,0 +1,28 @@
+/* linux/include/asm-arm/arch-s3c2410/leds-gpio.h
+ *
+ * (c) 2006 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - LEDs GPIO connector
+ *
+ * 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_LEDSGPIO_H
+#define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"
+
+#define S3C24XX_LEDF_ACTLOW (1<<0) /* LED is on when GPIO low */
+#define S3C24XX_LEDF_TRISTATE (1<<1) /* tristate to turn off */
+
+struct s3c24xx_led_platdata {
+ unsigned int gpio;
+ unsigned int flags;
+
+ char *name;
+ char *def_trigger;
+};
+
+#endif /* __ASM_ARCH_LEDSGPIO_H */
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index 28711aaa4968..ee008a5484f3 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -14,10 +14,6 @@
#include <linux/config.h>
-/* Flushing areas */
-#define FLUSH_BASE_PHYS 0xe0000000 /* SA1100 zero bank */
-#define FLUSH_BASE 0xf5000000
-#define FLUSH_BASE_MINICACHE 0xf5800000
#define UNCACHEABLE_ADDR 0xfa050000
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index 018a9f0e3986..a29fac1387ca 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -91,4 +91,11 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes);
#endif
+/*
+ * Cache flushing area - SA1100 zero bank
+ */
+#define FLUSH_BASE_PHYS 0xe0000000
+#define FLUSH_BASE 0xf5000000
+#define FLUSH_BASE_MINICACHE 0xf5100000
+
#endif
diff --git a/include/asm-arm/arch-shark/hardware.h b/include/asm-arm/arch-shark/hardware.h
index 4d35f8c154c3..ecba45260898 100644
--- a/include/asm-arm/arch-shark/hardware.h
+++ b/include/asm-arm/arch-shark/hardware.h
@@ -17,11 +17,6 @@
*/
#define IO_BASE 0xe0000000
-/*
- * RAM definitions
- */
-#define FLUSH_BASE_PHYS 0x80000000
-
#else
#define IO_BASE 0
@@ -33,7 +28,6 @@
#define ROMCARD_SIZE 0x08000000
#define ROMCARD_START 0x10000000
-#define FLUSH_BASE 0xdf000000
#define PCIO_BASE 0xe0000000
diff --git a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h
index 95a29b4bc5d0..6968d6103ea0 100644
--- a/include/asm-arm/arch-shark/memory.h
+++ b/include/asm-arm/arch-shark/memory.h
@@ -39,4 +39,10 @@ static inline void __arch_adjust_zones(int node, unsigned long *zone_size, unsig
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area
+ */
+#define FLUSH_BASE_PHYS 0x80000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index e3e8541ee63b..63ca7412a462 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -47,7 +47,7 @@ static inline int dma_get_cache_alignment(void)
static inline int dma_is_consistent(dma_addr_t handle)
{
- return 0;
+ return !!arch_is_coherent();
}
/*
@@ -145,7 +145,9 @@ static inline dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction dir)
{
- consistent_sync(cpu_addr, size, dir);
+ if (!arch_is_coherent())
+ consistent_sync(cpu_addr, size, dir);
+
return virt_to_dma(dev, (unsigned long)cpu_addr);
}
#else
@@ -255,7 +257,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
sg->dma_address = page_to_dma(dev, sg->page) + sg->offset;
virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
return nents;
@@ -310,14 +314,16 @@ static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ if (!arch_is_coherent())
+ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
}
static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ if (!arch_is_coherent())
+ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
}
#else
extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
@@ -347,7 +353,8 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
}
@@ -359,7 +366,8 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
}
#else
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 6246bf83627d..52bae088a185 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -26,7 +26,9 @@
struct vfp_hard_struct {
__u64 fpregs[16];
+#if __LINUX_ARM_ARCH__ < 6
__u32 fpmx_state;
+#endif
__u32 fpexc;
__u32 fpscr;
/*
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index afa5c3ea077c..209289407595 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -172,10 +172,10 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
* virt_addr_valid(k) indicates whether a virtual address is valid
*/
#ifndef CONFIG_DISCONTIGMEM
-#define ARCH_PFN_OFFSET (PHYS_PFN_OFFSET)
+#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
-#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
#define PHYS_TO_NID(addr) (0)
@@ -187,8 +187,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
* around in memory.
*/
#include <linux/numa.h>
-#define arch_pfn_to_nid(pfn) (PFN_TO_NID(pfn))
-#define arch_local_page_offset(pfn, nid) (LOCAL_MAP_NR((pfn) << PAGE_OFFSET))
+#define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn)
+#define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
#define pfn_valid(pfn) \
({ \
@@ -234,6 +234,14 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr))
#endif
+/*
+ * Optional coherency support. Currently used only by selected
+ * Intel XSC3-based systems.
+ */
+#ifndef arch_is_coherent
+#define arch_is_coherent() 0
+#endif
+
#endif
#include <asm-generic/memory_model.h>
diff --git a/include/asm-arm/numnodes.h b/include/asm-arm/numnodes.h
deleted file mode 100644
index 8df36818ebc9..000000000000
--- a/include/asm-arm/numnodes.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/include/asm-arm/numnodes.h
- *
- * Copyright (C) 2002 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* This declaration for the size of the NUMA (CONFIG_DISCONTIGMEM)
- * memory node table is the default.
- *
- * A good place to override this value is include/asm/arch/memory.h.
- */
-
-#ifndef __ASM_ARM_NUMNODES_H
-#define __ASM_ARM_NUMNODES_H
-
-#include <asm/memory.h>
-
-#ifndef NODES_SHIFT
-# define NODES_SHIFT 2 /* Normally, Max 4 Nodes */
-#endif
-
-#endif
diff --git a/include/asm-arm/pgtable-hwdef.h b/include/asm-arm/pgtable-hwdef.h
index 1d033495cc75..1bc1f997bda2 100644
--- a/include/asm-arm/pgtable-hwdef.h
+++ b/include/asm-arm/pgtable-hwdef.h
@@ -73,6 +73,7 @@
#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
#define PTE_EXT_APX (1 << 9) /* v6 */
+#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */
#define PTE_EXT_SHARED (1 << 10) /* v6 */
#define PTE_EXT_NG (1 << 11) /* v6 */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index e595ae24efe2..e85c08d78dda 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -156,6 +156,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define L_PTE_WRITE (1 << 5)
#define L_PTE_EXEC (1 << 6)
#define L_PTE_DIRTY (1 << 7)
+#define L_PTE_COHERENT (1 << 9) /* I/O coherent (xsc3) */
#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */
#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 65ac305c2d45..ee8dfea549bc 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -360,6 +360,24 @@
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
+/*
+ * The following syscalls are obsolete and no longer available for EABI.
+ */
+#if defined(__ARM_EABI__)
+#undef __NR_time
+#undef __NR_umount
+#undef __NR_stime
+#undef __NR_alarm
+#undef __NR_utime
+#undef __NR_getrlimit
+#undef __NR_select
+#undef __NR_readdir
+#undef __NR_mmap
+#undef __NR_socketcall
+#undef __NR_syscall
+#undef __NR_ipc
+#endif
+
#define __sys2(x) #x
#define __sys1(x) __sys2(x)
diff --git a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h
index 15bd6e74c9cf..27fe028b4e72 100644
--- a/include/asm-arm/vfpmacros.h
+++ b/include/asm-arm/vfpmacros.h
@@ -16,10 +16,18 @@
@ read all the working registers back into the VFP
.macro VFPFLDMIA, base
+#if __LINUX_ARM_ARCH__ < 6
LDC p11, cr0, [\base],#33*4 @ FLDMIAX \base!, {d0-d15}
+#else
+ LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15}
+#endif
.endm
@ write all the working registers out of the VFP
.macro VFPFSTMIA, base
+#if __LINUX_ARM_ARCH__ < 6
STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15}
+#else
+ STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15}
+#endif
.endm
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index 1d63c2aa8ec2..b1c593b6dbff 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -8,7 +8,6 @@
*/
extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
-#define prepare_to_switch() do { } while(0)
#define switch_to(prev,next,last) last = resume(prev,next, \
(int)&((struct task_struct *)0)->thread)
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 2627bbdf8a11..bb2dfe480213 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -288,7 +288,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index f72ff0c4dc0b..1734ed91bcdc 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -18,8 +18,6 @@
struct thread_struct;
-#define prepare_to_switch() do { } while(0)
-
/*
* switch_to(prev, next) should switch from task `prev' to `next'
* `prev' will never be the same as `next'.
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index 322531caa484..2662a3e12dc4 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -289,7 +289,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h
index dfe96c7121cf..8e81cf665e75 100644
--- a/include/asm-h8300/system.h
+++ b/include/asm-h8300/system.h
@@ -4,8 +4,6 @@
#include <linux/config.h> /* get configuration macros */
#include <linux/linkage.h>
-#define prepare_to_switch() do { } while(0)
-
/*
* switch_to(n) should switch tasks to task ptr, first checking that
* ptr isn't the current task, in which case it does nothing. This
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index 56a4a5686c88..adb05159379b 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -285,7 +285,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index ff9ac8d19eb2..288233fd77d7 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -139,6 +139,8 @@ void switch_ipi_to_APIC_timer(void *cpumask);
extern int timer_over_8254;
+extern int modern_apic(void);
+
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index 22d80ece95cb..4ddce5296a78 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -183,6 +183,7 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
{
int __i;
#ifdef CONFIG_M386
+ unsigned long flags;
if(unlikely(boot_cpu_data.x86==3))
goto no_xadd;
#endif
@@ -196,10 +197,10 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
#ifdef CONFIG_M386
no_xadd: /* Legacy 386 processor */
- local_irq_disable();
+ local_irq_save(flags);
__i = atomic_read(v);
atomic_set(v, i + __i);
- local_irq_enable();
+ local_irq_restore(flags);
return i + __i;
#endif
}
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index 5c0b5876b931..b44bfc6239cb 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -71,6 +71,7 @@
#define X86_FEATURE_P4 (3*32+ 7) /* P4 */
#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index edf65be21a92..ca82acb8cb1f 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -35,6 +35,10 @@ struct e820map {
};
extern struct e820map e820;
+
+extern int e820_all_mapped(unsigned long start, unsigned long end,
+ unsigned type);
+
#endif/*!__ASSEMBLY__*/
#endif/*__E820_HEADER*/
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 16ef9f996e3f..7f1a8a6ee32f 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -89,6 +89,7 @@
* then 32 bit HPET counter wrapsaround in less than 0.5 sec.
*/
#define HPET_MIN_PERIOD (100000UL)
+#define HPET_TICK_RATE (HZ * 100000UL)
extern unsigned long hpet_tick; /* hpet clks count per tick */
extern unsigned long hpet_address; /* hpet memory map physical address */
diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h
index 152d0baa576a..7b1f01191e70 100644
--- a/include/asm-i386/i387.h
+++ b/include/asm-i386/i387.h
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/kernel_stat.h>
#include <asm/processor.h>
#include <asm/sigcontext.h>
#include <asm/user.h>
@@ -38,17 +39,38 @@ extern void init_fpu(struct task_struct *);
extern void kernel_fpu_begin(void);
#define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
+/* We need a safe address that is cheap to find and that is already
+ in L1 during context switch. The best choices are unfortunately
+ different for UP and SMP */
+#ifdef CONFIG_SMP
+#define safe_address (__per_cpu_offset[0])
+#else
+#define safe_address (kstat_cpu(0).cpustat.user)
+#endif
+
/*
* These must be called with preempt disabled
*/
static inline void __save_init_fpu( struct task_struct *tsk )
{
+ /* Use more nops than strictly needed in case the compiler
+ varies code */
alternative_input(
- "fnsave %1 ; fwait ;" GENERIC_NOP2,
- "fxsave %1 ; fnclex",
+ "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
+ "fxsave %[fx]\n"
+ "bt $7,%[fsw] ; jc 1f ; fnclex\n1:",
X86_FEATURE_FXSR,
- "m" (tsk->thread.i387.fxsave)
- :"memory");
+ [fx] "m" (tsk->thread.i387.fxsave),
+ [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
+ /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. __per_cpu_offset[0] is a random variable that should be in L1 */
+ alternative_input(
+ GENERIC_NOP8 GENERIC_NOP2,
+ "emms\n\t" /* clear stack tags */
+ "fildl %[addr]", /* set F?P to defined value */
+ X86_FEATURE_FXSAVE_LEAK,
+ [addr] "m" (safe_address));
task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index 62113d3bfdc2..770bf6da8c3d 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -18,7 +18,6 @@ extern void find_smp_config (void);
extern void get_smp_config (void);
extern int nr_ioapics;
extern int apic_version [MAX_APICS];
-extern int mp_bus_id_to_type [MAX_MP_BUSSES];
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
extern int mpc_default_type;
diff --git a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h
deleted file mode 100644
index a61f38c8176f..000000000000
--- a/include/asm-i386/numnodes.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_X86_NUMAQ
-
-/* Max 16 Nodes */
-#define NODES_SHIFT 4
-
-#elif defined(CONFIG_ACPI_SRAT)
-
-/* Max 8 Nodes */
-#define NODES_SHIFT 3
-
-#endif /* CONFIG_X86_NUMAQ */
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index 27bde973abc7..2756d4b04c27 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -18,6 +18,9 @@
#define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
+#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
+
#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte_low, 0))
#define pte_same(a, b) ((a).pte_low == (b).pte_low)
#define pte_page(x) pfn_to_page(pte_pfn(x))
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index 36a5aa63cbbf..dccb1b3337ad 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -85,6 +85,26 @@ static inline void pud_clear (pud_t * pud) { }
#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
pmd_index(address))
+/*
+ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
+ * entry, so clear the bottom half first and enforce ordering with a compiler
+ * barrier.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ ptep->pte_low = 0;
+ smp_wmb();
+ ptep->pte_high = 0;
+}
+
+static inline void pmd_clear(pmd_t *pmd)
+{
+ u32 *tmp = (u32 *)pmd;
+ *tmp = 0;
+ smp_wmb();
+ *(tmp + 1) = 0;
+}
+
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t res;
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index ee056c41a9fb..672c3f76b9df 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -204,12 +204,10 @@ extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
extern unsigned long pg0[];
#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
#define pmd_none(x) (!(unsigned long)pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
@@ -268,7 +266,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
pte_t pte;
if (full) {
pte = *ptep;
- *ptep = __pte(0);
+ pte_clear(mm, addr, ptep);
} else {
pte = ptep_get_and_clear(mm, addr, ptep);
}
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 2e7f3e257fdd..eb4b152c82fc 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -288,7 +288,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
@@ -318,10 +318,12 @@
#define __NR_unshare 310
#define __NR_set_robust_list 311
#define __NR_get_robust_list 312
-#define __NR_sys_splice 313
-#define __NR_sys_sync_file_range 314
+#define __NR_splice 313
+#define __NR_sync_file_range 314
+#define __NR_tee 315
+#define __NR_vmsplice 316
-#define NR_syscalls 315
+#define NR_syscalls 317
/*
* user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-ia64/acpi-ext.h b/include/asm-ia64/acpi-ext.h
index 56d2ddc97b30..734d137dda6e 100644
--- a/include/asm-ia64/acpi-ext.h
+++ b/include/asm-ia64/acpi-ext.h
@@ -1,12 +1,15 @@
/*
- * ia64/platform/hp/common/hp_acpi.h
+ * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
+ * Alex Williamson <alex.williamson@hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*
- * Copyright (C) 2003 Hewlett-Packard
- * Copyright (C) Alex Williamson
- * Copyright (C) Bjorn Helgaas
+ * 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.
*
* Vendor specific extensions to ACPI.
*/
+
#ifndef _ASM_IA64_ACPI_EXT_H
#define _ASM_IA64_ACPI_EXT_H
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index d734585a23cf..09a5dd0e44a8 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -110,9 +110,8 @@ extern void prefill_possible_map(void);
extern int additional_cpus;
#ifdef CONFIG_ACPI_NUMA
-/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
-#ifdef CONFIG_IA64_NR_NODES
-#define MAX_PXM_DOMAINS CONFIG_IA64_NR_NODES
+#if MAX_NUMNODES > 256
+#define MAX_PXM_DOMAINS MAX_NUMNODES
#else
#define MAX_PXM_DOMAINS (256)
#endif
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index 218c458ab60c..c195a9ad1255 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -58,6 +58,8 @@ enum die_val {
DIE_MCA_RENDZVOUS_ENTER,
DIE_MCA_RENDZVOUS_PROCESS,
DIE_MCA_RENDZVOUS_LEAVE,
+ DIE_MCA_NEW_TIMEOUT,
+ DIE_INIT_ENTER,
DIE_INIT_MONARCH_ENTER,
DIE_INIT_MONARCH_PROCESS,
DIE_INIT_MONARCH_LEAVE,
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index c3e4ed8a3e17..a9c995a86c21 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -347,9 +347,11 @@ extern ia64_mv_dma_supported swiotlb_dma_supported;
#endif
#ifndef platform_pci_legacy_read
# define platform_pci_legacy_read ia64_pci_legacy_read
+extern int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size);
#endif
#ifndef platform_pci_legacy_write
# define platform_pci_legacy_write ia64_pci_legacy_write
+extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size);
#endif
#ifndef platform_inb
# define platform_inb __ia64_inb
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index bfbbb8da79c7..9c5389b7e623 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -148,6 +148,11 @@ extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *)
extern void ia64_unreg_MCA_extension(void);
extern u64 ia64_get_rnat(u64 *);
+struct ia64_mca_notify_die {
+ struct ia64_sal_os_state *sos;
+ int *monarch_cpu;
+};
+
#else /* __ASSEMBLY__ */
#define IA64_MCA_CORRECTED 0x0 /* Error has been corrected by OS_MCA */
diff --git a/include/asm-ia64/mutex.h b/include/asm-ia64/mutex.h
index 5a3224f6af38..bed73a643a56 100644
--- a/include/asm-ia64/mutex.h
+++ b/include/asm-ia64/mutex.h
@@ -84,7 +84,7 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
static inline int
__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
{
- if (likely(cmpxchg_acq(count, 1, 0)) == 1)
+ if (cmpxchg_acq(count, 1, 0) == 1)
return 1;
return 0;
}
diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h
deleted file mode 100644
index e9d356f549d9..000000000000
--- a/include/asm-ia64/numnodes.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-#ifdef CONFIG_IA64_DIG
-/* Max 8 Nodes */
-# define NODES_SHIFT 3
-#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
-/* Max 32 Nodes */
-# define NODES_SHIFT 5
-#elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
-# if CONFIG_IA64_NR_NODES == 256
-# define NODES_SHIFT 8
-# elif CONFIG_IA64_NR_NODES <= 512
-# define NODES_SHIFT 9
-# elif CONFIG_IA64_NR_NODES <= 1024
-# define NODES_SHIFT 10
-# endif
-#endif
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
index 291ef3d69da2..e61ebac38cdd 100644
--- a/include/asm-ia64/sn/sn2/sn_hwperf.h
+++ b/include/asm-ia64/sn/sn2/sn_hwperf.h
@@ -45,8 +45,12 @@ struct sn_hwperf_object_info {
#define SN_HWPERF_IS_NODE(x) ((x) && strstr((x)->name, "SHub"))
#define SN_HWPERF_IS_NODE_SHUB2(x) ((x) && strstr((x)->name, "SHub 2."))
#define SN_HWPERF_IS_IONODE(x) ((x) && strstr((x)->name, "TIO"))
-#define SN_HWPERF_IS_ROUTER(x) ((x) && strstr((x)->name, "Router"))
#define SN_HWPERF_IS_NL3ROUTER(x) ((x) && strstr((x)->name, "NL3Router"))
+#define SN_HWPERF_IS_NL4ROUTER(x) ((x) && strstr((x)->name, "NL4Router"))
+#define SN_HWPERF_IS_OLDROUTER(x) ((x) && strstr((x)->name, "Router"))
+#define SN_HWPERF_IS_ROUTER(x) (SN_HWPERF_IS_NL3ROUTER(x) || \
+ SN_HWPERF_IS_NL4ROUTER(x) || \
+ SN_HWPERF_IS_OLDROUTER(x))
#define SN_HWPERF_FOREIGN(x) ((x) && !(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
#define SN_HWPERF_SAME_OBJTYPE(x,y) ((SN_HWPERF_IS_NODE(x) && SN_HWPERF_IS_NODE(y)) ||\
(SN_HWPERF_IS_IONODE(x) && SN_HWPERF_IS_IONODE(y)) ||\
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index bf4cc867a698..51aca022cf39 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -8,7 +8,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc. All rights reserved.
*/
@@ -85,6 +85,7 @@
#define SN_SAL_GET_PROM_FEATURE_SET 0x02000065
#define SN_SAL_SET_OS_FEATURE_SET 0x02000066
+#define SN_SAL_INJECT_ERROR 0x02000067
/*
* Service-specific constants
@@ -705,10 +706,8 @@ static inline int
sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
{
struct ia64_sal_retval ret_stuff;
- int cnodeid;
unsigned long irq_flags;
- cnodeid = nasid_to_cnodeid(get_node_number(paddr));
local_irq_save(irq_flags);
ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
(u64)nasid_array, perms, 0, 0, 0);
@@ -1140,4 +1139,16 @@ ia64_sn_set_os_feature(int feature)
return rv.status;
}
+static inline int
+sn_inject_error(u64 paddr, u64 *data, u64 *ecc)
+{
+ struct ia64_sal_retval ret_stuff;
+ unsigned long irq_flags;
+
+ local_irq_save(irq_flags);
+ ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data,
+ (u64)ecc, 0, 0, 0, 0);
+ local_irq_restore(irq_flags);
+ return ret_stuff.status;
+}
#endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 56394a2c7055..e5392c4d30c6 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -67,7 +67,7 @@ struct thread_info {
#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-#define alloc_task_struct() ((task_t *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER))
+#define alloc_task_struct() ((task_t *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER))
#define free_task_struct(tsk) free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
#endif /* !__ASSEMBLY */
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 3ee19dfa46df..616b5ed2aa72 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -23,6 +23,11 @@
#define PENALTY_FOR_NODE_WITH_CPUS 255
/*
+ * Distance above which we begin to use zone reclaim
+ */
+#define RECLAIM_DISTANCE 15
+
+/*
* Returns the number of the node containing CPU 'cpu'
*/
#define cpu_to_node(cpu) (int)(cpu_to_node_map[cpu])
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 36070c1014d8..7107763168bf 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -286,12 +286,17 @@
/* 1294, 1295 reserved for pselect/ppoll */
#define __NR_unshare 1296
#define __NR_splice 1297
+#define __NR_set_robust_list 1298
+#define __NR_get_robust_list 1299
+#define __NR_sync_file_range 1300
+#define __NR_tee 1301
+#define __NR_vmsplice 1302
#ifdef __KERNEL__
#include <linux/config.h>
-#define NR_syscalls 274 /* length of syscall table */
+#define NR_syscalls 279 /* length of syscall table */
#define __ARCH_WANT_SYS_RT_SIGACTION
diff --git a/include/asm-ia64/vga.h b/include/asm-ia64/vga.h
index bc3349ffc505..091177cda223 100644
--- a/include/asm-ia64/vga.h
+++ b/include/asm-ia64/vga.h
@@ -17,7 +17,7 @@
extern unsigned long vga_console_iobase;
extern unsigned long vga_console_membase;
-#define VGA_MAP_MEM(x) ((unsigned long) ioremap(vga_console_membase + (x), 0))
+#define VGA_MAP_MEM(x) ((unsigned long) ioremap_nocache(vga_console_membase + (x), 0))
#define vga_readb(x) (*(x))
#define vga_writeb(x,y) (*(y) = (x))
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
index b7f4d8aaeb46..1a1aa17edd33 100644
--- a/include/asm-m32r/assembler.h
+++ b/include/asm-m32r/assembler.h
@@ -109,6 +109,9 @@
push r13
mvfachi r13
push r13
+ ldi r13, #0
+ push r13 ; dummy push acc1h
+ push r13 ; dummy push acc1l
#else
#error unknown isa configuration
#endif
@@ -156,6 +159,8 @@
pop r13
mvtaclo r13, a1
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+ pop r13 ; dummy pop acc1h
+ pop r13 ; dummy pop acc1l
pop r13
mvtachi r13
pop r13
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
index 1d3c25d61bcb..031369a7afc8 100644
--- a/include/asm-m32r/mappi3/mappi3_pld.h
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -53,16 +53,14 @@
/* Power Control of MMC and CF */
#define PLD_CPCR __reg16(PLD_BASE + 0x14000)
-
-/*==== ICU ====*/
-#define M32R_IRQ_PC104 (5) /* INT4(PC/104) */
-#define M32R_IRQ_I2C (28) /* I2C-BUS */
-#define PLD_IRQ_CFIREQ (6) /* INT5 CFC Card Interrupt */
-#define PLD_IRQ_CFC_INSERT (7) /* INT6 CFC Card Insert */
-#define PLD_IRQ_IDEIREQ (8) /* INT7 IDE Interrupt */
-#define PLD_IRQ_MMCCARD (43) /* MMC Card Insert */
-#define PLD_IRQ_MMCIRQ (44) /* MMC Transfer Done */
-
+/* ICU */
+#define M32R_IRQ_PC104 (5) /* INT4(PC/104) */
+#define M32R_IRQ_I2C (28) /* I2C-BUS */
+#define PLD_IRQ_CFIREQ (6) /* INT5 CFC Card Interrupt */
+#define PLD_IRQ_CFC_INSERT (7) /* INT6 CFC Card Insert & Eject */
+#define PLD_IRQ_IDEIREQ (8) /* INT7 IDE Interrupt */
+#define PLD_IRQ_MMCCARD (43) /* MMC Card Insert */
+#define PLD_IRQ_MMCIRQ (44) /* MMC Transfer Done */
#if 0
/* LED Control
@@ -97,7 +95,6 @@
#define PLD_CRC16ADATA __reg16(PLD_BASE + 0x18008)
#define PLD_CRC16AINDATA __reg16(PLD_BASE + 0x1800a)
-
#if 0
/* RTC */
#define PLD_RTCCR __reg16(PLD_BASE + 0x1c000)
@@ -140,4 +137,7 @@
#endif
+/* Reset Control */
+#define PLD_REBOOT __reg16(PLD_BASE + 0x38000)
+
#endif /* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/numnodes.h b/include/asm-m32r/numnodes.h
deleted file mode 100644
index 479a39d49f83..000000000000
--- a/include/asm-m32r/numnodes.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _ASM_NUMNODES_H_
-#define _ASM_NUMNODES_H_
-
-#include <linux/config.h>
-
-#ifdef CONFIG_DISCONTIGMEM
-
-#if defined(CONFIG_CHIP_M32700)
-#define NODES_SHIFT 1 /* Max 2 Nodes */
-#endif /* CONFIG_CHIP_M32700 */
-
-#endif /* CONFIG_DISCONTIGMEM */
-
-#endif /* _ASM_NUMNODES_H_ */
-
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 0d058b2d844e..53c792452dfc 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -43,6 +43,14 @@
#define PT_ACC1L 18
#define PT_ACCH PT_ACC0H
#define PT_ACCL PT_ACC0L
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH 15
+#define PT_ACCL 16
+#define PT_DUMMY_ACC1H 17
+#define PT_DUMMY_ACC1L 18
+#else
+#error unknown isa conifiguration
+#endif
#define PT_PSW 19
#define PT_BPC 20
#define PT_BBPSW 21
@@ -52,21 +60,6 @@
#define PT_LR 25
#define PT_SPI 26
#define PT_ORIGR0 27
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH 15
-#define PT_ACCL 16
-#define PT_PSW 17
-#define PT_BPC 18
-#define PT_BBPSW 19
-#define PT_BBPC 20
-#define PT_SPU 21
-#define PT_FP 22
-#define PT_LR 23
-#define PT_SPI 24
-#define PT_ORIGR0 25
-#else
-#error unknown isa conifiguration
-#endif
/* virtual pt_reg entry for gdb */
#define PT_PC 30
@@ -121,6 +114,8 @@ struct pt_regs {
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
unsigned long acch;
unsigned long accl;
+ unsigned long dummy_acc1h;
+ unsigned long dummy_acc1l;
#else
#error unknown isa configuration
#endif
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index bf447c52a0a1..81750edc8916 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -9,7 +9,7 @@
* SMP- and interrupt-safe semaphores..
*
* Copyright (C) 1996 Linus Torvalds
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
*/
#include <linux/config.h>
@@ -77,27 +77,8 @@ asmlinkage void __up(struct semaphore * sem);
*/
static inline void down(struct semaphore * sem)
{
- unsigned long flags;
- long count;
-
might_sleep();
- local_irq_save(flags);
- __asm__ __volatile__ (
- "# down \n\t"
- DCACHE_CLEAR("%0", "r4", "%1")
- M32R_LOCK" %0, @%1; \n\t"
- "addi %0, #-1; \n\t"
- M32R_UNLOCK" %0, @%1; \n\t"
- : "=&r" (count)
- : "r" (&sem->count)
- : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
- );
- local_irq_restore(flags);
-
- if (unlikely(count < 0))
+ if (unlikely(atomic_dec_return(&sem->count) < 0))
__down(sem);
}
@@ -107,28 +88,10 @@ static inline void down(struct semaphore * sem)
*/
static inline int down_interruptible(struct semaphore * sem)
{
- unsigned long flags;
- long count;
int result = 0;
might_sleep();
- local_irq_save(flags);
- __asm__ __volatile__ (
- "# down_interruptible \n\t"
- DCACHE_CLEAR("%0", "r4", "%1")
- M32R_LOCK" %0, @%1; \n\t"
- "addi %0, #-1; \n\t"
- M32R_UNLOCK" %0, @%1; \n\t"
- : "=&r" (count)
- : "r" (&sem->count)
- : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
- );
- local_irq_restore(flags);
-
- if (unlikely(count < 0))
+ if (unlikely(atomic_dec_return(&sem->count) < 0))
result = __down_interruptible(sem);
return result;
@@ -174,26 +137,7 @@ static inline int down_trylock(struct semaphore * sem)
*/
static inline void up(struct semaphore * sem)
{
- unsigned long flags;
- long count;
-
- local_irq_save(flags);
- __asm__ __volatile__ (
- "# up \n\t"
- DCACHE_CLEAR("%0", "r4", "%1")
- M32R_LOCK" %0, @%1; \n\t"
- "addi %0, #1; \n\t"
- M32R_UNLOCK" %0, @%1; \n\t"
- : "=&r" (count)
- : "r" (&sem->count)
- : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
- );
- local_irq_restore(flags);
-
- if (unlikely(count <= 0))
+ if (unlikely(atomic_inc_return(&sem->count) <= 0))
__up(sem);
}
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index c233e2def2a3..942b8a30937d 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -32,6 +32,8 @@ struct sigcontext {
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
unsigned long sc_acch;
unsigned long sc_accl;
+ unsigned long sc_dummy_acc1h;
+ unsigned long sc_dummy_acc1l;
#else
#error unknown isa configuration
#endif
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 7885b7df84a2..1184293e5712 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -67,7 +67,8 @@ extern volatile int cpu_2_physid[NR_CPUS];
#define raw_smp_processor_id() (current_thread_info()->cpu)
extern cpumask_t cpu_callout_map;
-#define cpu_possible_map cpu_callout_map
+extern cpumask_t cpu_possible_map;
+extern cpumask_t cpu_present_map;
static __inline__ int hard_smp_processor_id(void)
{
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index d6a2c613be68..e55013f378e5 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -6,8 +6,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2001 Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
*/
#include <linux/config.h>
@@ -19,53 +19,28 @@
* switch_to(prev, next) should switch from task `prev' to `next'
* `prev' will never be the same as `next'.
*
- * `next' and `prev' should be struct task_struct, but it isn't always defined
+ * `next' and `prev' should be task_t, but it isn't always defined
*/
-#ifndef CONFIG_SMP
-#define prepare_to_switch() do { } while(0)
-#endif /* not CONFIG_SMP */
-
#define switch_to(prev, next, last) do { \
- register unsigned long arg0 __asm__ ("r0") = (unsigned long)prev; \
- register unsigned long arg1 __asm__ ("r1") = (unsigned long)next; \
- register unsigned long *oldsp __asm__ ("r2") = &(prev->thread.sp); \
- register unsigned long *newsp __asm__ ("r3") = &(next->thread.sp); \
- register unsigned long *oldlr __asm__ ("r4") = &(prev->thread.lr); \
- register unsigned long *newlr __asm__ ("r5") = &(next->thread.lr); \
- register struct task_struct *__last __asm__ ("r6"); \
__asm__ __volatile__ ( \
- "st r8, @-r15 \n\t" \
- "st r9, @-r15 \n\t" \
- "st r10, @-r15 \n\t" \
- "st r11, @-r15 \n\t" \
- "st r12, @-r15 \n\t" \
- "st r13, @-r15 \n\t" \
- "st r14, @-r15 \n\t" \
- "seth r14, #high(1f) \n\t" \
- "or3 r14, r14, #low(1f) \n\t" \
- "st r14, @r4 ; store old LR \n\t" \
- "st r15, @r2 ; store old SP \n\t" \
- "ld r15, @r3 ; load new SP \n\t" \
- "st r0, @-r15 ; store 'prev' onto new stack \n\t" \
- "ld r14, @r5 ; load new LR \n\t" \
- "jmp r14 \n\t" \
- ".fillinsn \n " \
- "1: \n\t" \
- "ld r6, @r15+ ; load 'prev' from new stack \n\t" \
- "ld r14, @r15+ \n\t" \
- "ld r13, @r15+ \n\t" \
- "ld r12, @r15+ \n\t" \
- "ld r11, @r15+ \n\t" \
- "ld r10, @r15+ \n\t" \
- "ld r9, @r15+ \n\t" \
- "ld r8, @r15+ \n\t" \
- : "=&r" (__last) \
- : "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
- "r" (oldlr), "r" (newlr) \
- : "memory" \
+ " seth lr, #high(1f) \n" \
+ " or3 lr, lr, #low(1f) \n" \
+ " st lr, @%4 ; store old LR \n" \
+ " ld lr, @%5 ; load new LR \n" \
+ " st sp, @%2 ; store old SP \n" \
+ " ld sp, @%3 ; load new SP \n" \
+ " push %1 ; store `prev' on new stack \n" \
+ " jmp lr \n" \
+ " .fillinsn \n" \
+ "1: \n" \
+ " pop %0 ; restore `__last' from new stack \n" \
+ : "=r" (last) \
+ : "0" (prev), \
+ "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+ "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+ : "memory", "lr" \
); \
- last = __last; \
} while(0)
/*
@@ -171,8 +146,8 @@ extern void __xchg_called_with_bad_pointer(void);
#define DCACHE_CLEAR(reg0, reg1, addr)
#endif /* CONFIG_CHIP_M32700_TS1 */
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
- int size)
+static inline unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
{
unsigned long flags;
unsigned long tmp = 0;
@@ -224,7 +199,7 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
#define __HAVE_ARCH_CMPXCHG 1
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
{
unsigned long flags;
@@ -258,7 +233,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
if something tries to do an invalid cmpxchg(). */
extern void __cmpxchg_called_with_bad_pointer(void);
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
{
switch (size) {
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index e8ae61956a51..819cc28a94f7 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -5,17 +5,9 @@
* linux/include/asm-m32r/uaccess.h
*
* M32R version.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
*/
-#undef UACCESS_DEBUG
-
-#ifdef UACCESS_DEBUG
-#define UAPRINTK(args...) printk(args)
-#else
-#define UAPRINTK(args...)
-#endif /* UACCESS_DEBUG */
-
/*
* User space memory access functions
*/
@@ -38,27 +30,29 @@
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
#ifdef CONFIG_MMU
+
#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
-#else
-#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
-#define USER_DS MAKE_MM_SEG(0xFFFFFFFF)
-#endif /* CONFIG_MMU */
-
#define get_ds() (KERNEL_DS)
-#ifdef CONFIG_MMU
#define get_fs() (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))
-#else
+
+#else /* not CONFIG_MMU */
+
+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS MAKE_MM_SEG(0xFFFFFFFF)
+#define get_ds() (KERNEL_DS)
+
static inline mm_segment_t get_fs(void)
{
- return USER_DS;
+ return USER_DS;
}
static inline void set_fs(mm_segment_t s)
{
}
-#endif /* CONFIG_MMU */
+
+#endif /* not CONFIG_MMU */
#define segment_eq(a,b) ((a).seg == (b).seg)
@@ -83,9 +77,9 @@ static inline void set_fs(mm_segment_t s)
" subx %0, %0\n" \
" cmpu %4, %1\n" \
" subx %0, %5\n" \
- : "=&r"(flag), "=r"(sum) \
- : "1"(addr), "r"((int)(size)), \
- "r"(current_thread_info()->addr_limit.seg), "r"(0) \
+ : "=&r" (flag), "=r" (sum) \
+ : "1" (addr), "r" ((int)(size)), \
+ "r" (current_thread_info()->addr_limit.seg), "r" (0) \
: "cbit" ); \
flag; })
@@ -113,10 +107,10 @@ static inline void set_fs(mm_segment_t s)
#else
static inline int access_ok(int type, const void *addr, unsigned long size)
{
- extern unsigned long memory_start, memory_end;
- unsigned long val = (unsigned long)addr;
+ extern unsigned long memory_start, memory_end;
+ unsigned long val = (unsigned long)addr;
- return ((val >= memory_start) && ((val + size) < memory_end));
+ return ((val >= memory_start) && ((val + size) < memory_end));
}
#endif /* CONFIG_MMU */
@@ -155,39 +149,6 @@ extern int fixup_exception(struct pt_regs *regs);
* accesses to the same area of user memory).
*/
-extern void __get_user_1(void);
-extern void __get_user_2(void);
-extern void __get_user_4(void);
-
-#ifndef MODULE
-#define __get_user_x(size,ret,x,ptr) \
- __asm__ __volatile__( \
- " mv r0, %0\n" \
- " mv r1, %1\n" \
- " bl __get_user_" #size "\n" \
- " mv %0, r0\n" \
- " mv %1, r1\n" \
- : "=r"(ret), "=r"(x) \
- : "0"(ptr) \
- : "r0", "r1", "r14" )
-#else /* MODULE */
-/*
- * Use "jl" instead of "bl" for MODULE
- */
-#define __get_user_x(size,ret,x,ptr) \
- __asm__ __volatile__( \
- " mv r0, %0\n" \
- " mv r1, %1\n" \
- " seth lr, #high(__get_user_" #size ")\n" \
- " or3 lr, lr, #low(__get_user_" #size ")\n" \
- " jl lr\n" \
- " mv %0, r0\n" \
- " mv %1, r1\n" \
- : "=r"(ret), "=r"(x) \
- : "0"(ptr) \
- : "r0", "r1", "r14" )
-#endif
-
/* Careful: we have to cast the result to the type of the pointer for sign
reasons */
/**
@@ -208,20 +169,7 @@ extern void __get_user_4(void);
* On error, the variable @x is set to zero.
*/
#define get_user(x,ptr) \
-({ int __ret_gu; \
- unsigned long __val_gu; \
- __chk_user_ptr(ptr); \
- switch(sizeof (*(ptr))) { \
- case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
- case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
- case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
- default: __get_user_x(X,__ret_gu,__val_gu,ptr); break; \
- } \
- (x) = (__typeof__(*(ptr)))__val_gu; \
- __ret_gu; \
-})
-
-extern void __put_user_bad(void);
+ __get_user_check((x),(ptr),sizeof(*(ptr)))
/**
* put_user: - Write a simple value into user space.
@@ -240,8 +188,7 @@ extern void __put_user_bad(void);
* Returns zero on success, or -EFAULT on error.
*/
#define put_user(x,ptr) \
- __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-
+ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/**
* __get_user: - Get a simple variable from user space, with less checking.
@@ -264,8 +211,64 @@ extern void __put_user_bad(void);
* On error, the variable @x is set to zero.
*/
#define __get_user(x,ptr) \
- __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+ __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user_nocheck(x,ptr,size) \
+({ \
+ long __gu_err = 0; \
+ unsigned long __gu_val; \
+ might_sleep(); \
+ __get_user_size(__gu_val,(ptr),(size),__gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+#define __get_user_check(x,ptr,size) \
+({ \
+ long __gu_err = -EFAULT; \
+ unsigned long __gu_val = 0; \
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
+ might_sleep(); \
+ if (access_ok(VERIFY_READ,__gu_addr,size)) \
+ __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval) \
+do { \
+ retval = 0; \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+ case 1: __get_user_asm(x,ptr,retval,"ub"); break; \
+ case 2: __get_user_asm(x,ptr,retval,"uh"); break; \
+ case 4: __get_user_asm(x,ptr,retval,""); break; \
+ default: (x) = __get_user_bad(); \
+ } \
+} while (0)
+
+#define __get_user_asm(x, addr, err, itype) \
+ __asm__ __volatile__( \
+ " .fillinsn\n" \
+ "1: ld"itype" %1,@%2\n" \
+ " .fillinsn\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ " .balign 4\n" \
+ "3: ldi %0,%3\n" \
+ " seth r14,#high(2b)\n" \
+ " or3 r14,r14,#low(2b)\n" \
+ " jmp r14\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .balign 4\n" \
+ " .long 1b,3b\n" \
+ ".previous" \
+ : "=&r" (err), "=&r" (x) \
+ : "r" (addr), "i" (-EFAULT), "0" (err) \
+ : "r14", "memory")
/**
* __put_user: - Write a simple value into user space, with less checking.
@@ -287,11 +290,13 @@ extern void __put_user_bad(void);
* Returns zero on success, or -EFAULT on error.
*/
#define __put_user(x,ptr) \
- __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
#define __put_user_nocheck(x,ptr,size) \
({ \
long __pu_err; \
+ might_sleep(); \
__put_user_size((x),(ptr),(size),__pu_err); \
__pu_err; \
})
@@ -308,28 +313,28 @@ extern void __put_user_bad(void);
})
#if defined(__LITTLE_ENDIAN__)
-#define __put_user_u64(x, addr, err) \
- __asm__ __volatile__( \
- " .fillinsn\n" \
- "1: st %L1,@%2\n" \
- " .fillinsn\n" \
- "2: st %H1,@(4,%2)\n" \
- " .fillinsn\n" \
- "3:\n" \
- ".section .fixup,\"ax\"\n" \
- " .balign 4\n" \
- "4: ldi %0,%3\n" \
- " seth r14,#high(3b)\n" \
- " or3 r14,r14,#low(3b)\n" \
- " jmp r14\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .balign 4\n" \
- " .long 1b,4b\n" \
- " .long 2b,4b\n" \
- ".previous" \
- : "=&r"(err) \
- : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
+#define __put_user_u64(x, addr, err) \
+ __asm__ __volatile__( \
+ " .fillinsn\n" \
+ "1: st %L1,@%2\n" \
+ " .fillinsn\n" \
+ "2: st %H1,@(4,%2)\n" \
+ " .fillinsn\n" \
+ "3:\n" \
+ ".section .fixup,\"ax\"\n" \
+ " .balign 4\n" \
+ "4: ldi %0,%3\n" \
+ " seth r14,#high(3b)\n" \
+ " or3 r14,r14,#low(3b)\n" \
+ " jmp r14\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .balign 4\n" \
+ " .long 1b,4b\n" \
+ " .long 2b,4b\n" \
+ ".previous" \
+ : "=&r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
: "r14", "memory")
#elif defined(__BIG_ENDIAN__)
@@ -353,13 +358,15 @@ extern void __put_user_bad(void);
" .long 1b,4b\n" \
" .long 2b,4b\n" \
".previous" \
- : "=&r"(err) \
- : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
+ : "=&r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
: "r14", "memory")
#else
#error no endian defined
#endif
+extern void __put_user_bad(void);
+
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
@@ -398,52 +405,8 @@ struct __large_struct { unsigned long buf[100]; };
" .balign 4\n" \
" .long 1b,3b\n" \
".previous" \
- : "=&r"(err) \
- : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
- : "r14", "memory")
-
-#define __get_user_nocheck(x,ptr,size) \
-({ \
- long __gu_err; \
- unsigned long __gu_val; \
- __get_user_size(__gu_val,(ptr),(size),__gu_err); \
- (x) = (__typeof__(*(ptr)))__gu_val; \
- __gu_err; \
-})
-
-extern long __get_user_bad(void);
-
-#define __get_user_size(x,ptr,size,retval) \
-do { \
- retval = 0; \
- __chk_user_ptr(ptr); \
- switch (size) { \
- case 1: __get_user_asm(x,ptr,retval,"ub"); break; \
- case 2: __get_user_asm(x,ptr,retval,"uh"); break; \
- case 4: __get_user_asm(x,ptr,retval,""); break; \
- default: (x) = __get_user_bad(); \
- } \
-} while (0)
-
-#define __get_user_asm(x, addr, err, itype) \
- __asm__ __volatile__( \
- " .fillinsn\n" \
- "1: ld"itype" %1,@%2\n" \
- " .fillinsn\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- " .balign 4\n" \
- "3: ldi %0,%3\n" \
- " seth r14,#high(2b)\n" \
- " or3 r14,r14,#low(2b)\n" \
- " jmp r14\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .balign 4\n" \
- " .long 1b,3b\n" \
- ".previous" \
- : "=&r"(err), "=&r"(x) \
- : "r"(addr), "i"(-EFAULT), "0"(err) \
+ : "=&r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
: "r14", "memory")
/*
@@ -453,7 +416,6 @@ do { \
* anything, so this is accurate.
*/
-
/*
* Copy To/From Userspace
*/
@@ -511,8 +473,9 @@ do { \
" .long 2b,9b\n" \
" .long 3b,9b\n" \
".previous\n" \
- : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c) \
- : "0"(to), "1"(from), "2"(size), "3"(size / 4) \
+ : "=&r" (__dst), "=&r" (__src), "=&r" (size), \
+ "=&r" (__c) \
+ : "0" (to), "1" (from), "2" (size), "3" (size / 4) \
: "r14", "memory"); \
} while (0)
@@ -573,8 +536,9 @@ do { \
" .long 2b,7b\n" \
" .long 3b,7b\n" \
".previous\n" \
- : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c) \
- : "0"(to), "1"(from), "2"(size), "3"(size / 4) \
+ : "=&r" (__dst), "=&r" (__src), "=&r" (size), \
+ "=&r" (__c) \
+ : "0" (to), "1" (from), "2" (size), "3" (size / 4) \
: "r14", "memory"); \
} while (0)
@@ -676,7 +640,7 @@ unsigned long __generic_copy_from_user(void *, const void __user *, unsigned lon
#define copy_from_user(to,from,n) \
({ \
might_sleep(); \
-__generic_copy_from_user((to),(from),(n)); \
+ __generic_copy_from_user((to),(from),(n)); \
})
long __must_check strncpy_from_user(char *dst, const char __user *src,
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index 39be87ca2a5a..be0eb014c3b0 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -292,7 +292,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
#define NR_syscalls 285
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 30b18ea6cb11..f54aa147ec19 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -17,7 +17,26 @@
#ifdef CONFIG_64BIT
#include <asm/asmmacro-64.h>
#endif
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
+#ifdef CONFIG_MIPS_MT_SMTC
+ .macro local_irq_enable reg=t0
+ mfc0 \reg, CP0_TCSTATUS
+ ori \reg, \reg, TCSTATUS_IXMT
+ xori \reg, \reg, TCSTATUS_IXMT
+ mtc0 \reg, CP0_TCSTATUS
+ ehb
+ .endm
+
+ .macro local_irq_disable reg=t0
+ mfc0 \reg, CP0_TCSTATUS
+ ori \reg, \reg, TCSTATUS_IXMT
+ mtc0 \reg, CP0_TCSTATUS
+ ehb
+ .endm
+#else
.macro local_irq_enable reg=t0
mfc0 \reg, CP0_STATUS
ori \reg, \reg, 1
@@ -32,6 +51,7 @@
mtc0 \reg, CP0_STATUS
irq_disable_hazard
.endm
+#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_CPU_SB1
.macro fpu_enable_hazard
@@ -48,4 +68,31 @@
.endm
#endif
+/*
+ * Temporary until all gas have MT ASE support
+ */
+ .macro DMT reg=0
+ .word (0x41600bc1 | (\reg << 16))
+ .endm
+
+ .macro EMT reg=0
+ .word (0x41600be1 | (\reg << 16))
+ .endm
+
+ .macro DVPE reg=0
+ .word (0x41600001 | (\reg << 16))
+ .endm
+
+ .macro EVPE reg=0
+ .word (0x41600021 | (\reg << 16))
+ .endm
+
+ .macro MFTR rt=0, rd=0, u=0, sel=0
+ .word (0x41000000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+ .endm
+
+ .macro MTTR rt=0, rd=0, u=0, sel=0
+ .word (0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+ .endm
+
#endif /* _ASM_ASMMACRO_H */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index a1728f8c0705..d2f444537e4b 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -467,64 +467,56 @@ static inline unsigned long __ffs(unsigned long word)
}
/*
- * ffs - find first bit set.
+ * fls - find last bit set.
* @word: The word to search
*
- * Returns 1..SZLONG
- * Returns 0 if no bit exists
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-
-static inline unsigned long ffs(unsigned long word)
+static inline int fls(int word)
{
- if (!word)
- return 0;
+ __asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
- return __ffs(word) + 1;
+ return 32 - word;
}
-/*
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long ffz(unsigned long word)
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64)
+static inline int fls64(__u64 word)
{
- return __ffs (~word);
+ __asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
+
+ return 64 - word;
}
+#else
+#include <asm-generic/bitops/fls64.h>
+#endif
/*
- * fls - find last bit set.
+ * ffs - find first bit set.
* @word: The word to search
*
- * Returns 1..SZLONG
- * Returns 0 if no bit exists
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
*/
-static inline unsigned long fls(unsigned long word)
+static inline int ffs(int word)
{
-#ifdef CONFIG_CPU_MIPS32
- __asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
-
- return 32 - word;
-#endif
-
-#ifdef CONFIG_CPU_MIPS64
- __asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
+ if (!word)
+ return 0;
- return 64 - word;
-#endif
+ return fls(word & -word);
}
#else
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */
-#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index aeae9fabf4a9..47bc8f6c20d2 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -74,6 +74,7 @@ static inline void copy_from_user_page(struct vm_area_struct *vma,
extern void (*flush_cache_sigtramp)(unsigned long addr);
extern void (*flush_icache_all)(void);
+extern void (*local_flush_data_cache_page)(void * addr);
extern void (*flush_data_cache_page)(unsigned long addr);
/*
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 3f2b6d9ac45e..254e11ed247b 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -40,7 +40,7 @@
#define cpu_has_sb1_cache (cpu_data[0].options & MIPS_CPU_SB1_CACHE)
#endif
#ifndef cpu_has_fpu
-#define cpu_has_fpu (cpu_data[0].options & MIPS_CPU_FPU)
+#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU)
#endif
#ifndef cpu_has_32fpr
#define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR)
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 140be1c67da7..6572ac703662 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -73,6 +73,16 @@ struct cpuinfo_mips {
struct cache_desc dcache; /* Primary D or combined I/D cache */
struct cache_desc scache; /* Secondary cache */
struct cache_desc tcache; /* Tertiary/split secondary cache */
+#if defined(CONFIG_MIPS_MT_SMTC)
+ /*
+ * In the MIPS MT "SMTC" model, each TC is considered
+ * to be a "CPU" for the purposes of scheduling, but
+ * exception resources, ASID spaces, etc, are common
+ * to all TCs within the same VPE.
+ */
+ int vpe_id; /* Virtual Processor number */
+ int tc_id; /* Thread Context number */
+#endif /* CONFIG_MIPS_MT */
void *data; /* Additional data */
} __attribute__((aligned(SMP_CACHE_BYTES)));
diff --git a/include/asm-mips/ds1742.h b/include/asm-mips/ds1742.h
new file mode 100644
index 000000000000..c2f2c32da637
--- /dev/null
+++ b/include/asm-mips/ds1742.h
@@ -0,0 +1,13 @@
+/*
+ * 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 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef _ASM_DS1742_H
+#define _ASM_DS1742_H
+
+#include <ds1742.h>
+
+#endif /* _ASM_DS1742_H */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index 851f013adad3..bdc9de2df1ef 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -119,8 +119,49 @@
#define SHT_MIPS_CONFLICT 0x70000002
#define SHT_MIPS_GPTAB 0x70000003
#define SHT_MIPS_UCODE 0x70000004
-
-#define SHF_MIPS_GPREL 0x10000000
+#define SHT_MIPS_DEBUG 0x70000005
+#define SHT_MIPS_REGINFO 0x70000006
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d
+#define SHT_MIPS_SHDR 0x70000010
+#define SHT_MIPS_FDESC 0x70000011
+#define SHT_MIPS_EXTSYM 0x70000012
+#define SHT_MIPS_DENSE 0x70000013
+#define SHT_MIPS_PDESC 0x70000014
+#define SHT_MIPS_LOCSYM 0x70000015
+#define SHT_MIPS_AUXSYM 0x70000016
+#define SHT_MIPS_OPTSYM 0x70000017
+#define SHT_MIPS_LOCSTR 0x70000018
+#define SHT_MIPS_LINE 0x70000019
+#define SHT_MIPS_RFDESC 0x7000001a
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+#define SHF_MIPS_GPREL 0x10000000
+#define SHF_MIPS_MERGE 0x20000000
+#define SHF_MIPS_ADDR 0x40000000
+#define SHF_MIPS_STRING 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL 0x04000000
+#define SHF_MIPS_NAMES 0x02000000
+#define SHF_MIPS_NODUPES 0x01000000
#ifndef ELF_ARCH
/* ELF register definitions */
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 9c828b1f8218..b0f50015e252 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -21,6 +21,10 @@
#include <asm/processor.h>
#include <asm/current.h>
+#ifdef CONFIG_MIPS_MT_FPAFF
+#include <asm/mips_mt.h>
+#endif
+
struct sigcontext;
struct sigcontext32;
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index feb29a793888..dadc05188db7 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -284,6 +284,8 @@ do { \
#define instruction_hazard() do { } while (0)
#endif
+extern void mips_ihb(void);
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_HAZARDS_H */
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index 774348734fa0..4bb9c06f4410 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -19,7 +19,12 @@ __asm__ (
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n"
+ " ori $1, 0x400 \n"
+ " xori $1, 0x400 \n"
+ " mtc0 $1, $2, 1 \n"
+#elif defined(CONFIG_CPU_MIPSR2)
" ei \n"
#else
" mfc0 $1,$12 \n"
@@ -62,7 +67,12 @@ __asm__ (
" .macro local_irq_disable\n"
" .set push \n"
" .set noat \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 $1, $2, 1 \n"
+ " ori $1, 0x400 \n"
+ " .set noreorder \n"
+ " mtc0 $1, $2, 1 \n"
+#elif defined(CONFIG_CPU_MIPSR2)
" di \n"
#else
" mfc0 $1,$12 \n"
@@ -88,7 +98,11 @@ __asm__ (
" .macro local_save_flags flags \n"
" .set push \n"
" .set reorder \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 \\flags, $2, 1 \n"
+#else
" mfc0 \\flags, $12 \n"
+#endif
" .set pop \n"
" .endm \n");
@@ -102,7 +116,13 @@ __asm__ (
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 \\result, $2, 1 \n"
+ " ori $1, \\result, 0x400 \n"
+ " .set noreorder \n"
+ " mtc0 $1, $2, 1 \n"
+ " andi \\result, \\result, 0x400 \n"
+#elif defined(CONFIG_CPU_MIPSR2)
" di \\result \n"
" andi \\result, 1 \n"
#else
@@ -128,7 +148,14 @@ __asm__ (
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#ifdef CONFIG_MIPS_MT_SMTC
+ "mfc0 $1, $2, 1 \n"
+ "andi \\flags, 0x400 \n"
+ "ori $1, 0x400 \n"
+ "xori $1, 0x400 \n"
+ "or \\flags, $1 \n"
+ "mtc0 \\flags, $2, 1 \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
/*
* Slow, but doesn't suffer from a relativly unlikely race
* condition we're having since days 1.
@@ -167,11 +194,29 @@ do { \
: "memory"); \
} while(0)
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- !(flags & 1); \
-})
+static inline int irqs_disabled(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
+ */
+ unsigned long __result;
+
+ __asm__ __volatile__(
+ " .set noreorder \n"
+ " mfc0 %0, $2, 1 \n"
+ " andi %0, 0x400 \n"
+ " slt %0, $0, %0 \n"
+ " .set reorder \n"
+ : "=r" (__result));
+
+ return __result;
+#else
+ unsigned long flags;
+ local_save_flags(flags);
+
+ return !(flags & 1);
+#endif
+}
#endif /* _ASM_INTERRUPT_H */
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 8a342ccb34a8..dde677f02bc0 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -11,6 +11,9 @@
#include <linux/config.h>
#include <linux/linkage.h>
+
+#include <asm/mipsmtregs.h>
+
#include <irq.h>
#ifdef CONFIG_I8259
@@ -26,6 +29,23 @@ struct pt_regs;
extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Clear interrupt mask handling "backstop" if irq_hwmask
+ * entry so indicates. This implies that the ack() or end()
+ * functions will take over re-enabling the low-level mask.
+ * Otherwise it will be done on return from exception.
+ */
+#define __DO_IRQ_SMTC_HOOK() \
+do { \
+ if (irq_hwmask[irq] & 0x0000ff00) \
+ write_c0_tccontext(read_c0_tccontext() & \
+ ~(irq_hwmask[irq] & 0x0000ff00)); \
+} while (0)
+#else
+#define __DO_IRQ_SMTC_HOOK() do { } while (0)
+#endif
+
#ifdef CONFIG_PREEMPT
/*
@@ -39,6 +59,7 @@ extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
#define do_IRQ(irq, regs) \
do { \
irq_enter(); \
+ __DO_IRQ_SMTC_HOOK(); \
__do_IRQ((irq), (regs)); \
irq_exit(); \
} while (0)
@@ -46,5 +67,14 @@ do { \
#endif
extern void arch_init_irq(void);
+extern void spurious_interrupt(struct pt_regs *regs);
+
+#ifdef CONFIG_MIPS_MT_SMTC
+struct irqaction;
+
+extern unsigned long irq_hwmask[];
+extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+ unsigned long hwmask);
+#endif /* CONFIG_MIPS_MT_SMTC */
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/kspd.h b/include/asm-mips/kspd.h
new file mode 100644
index 000000000000..4e9e724c8935
--- /dev/null
+++ b/include/asm-mips/kspd.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef _ASM_KSPD_H
+#define _ASM_KSPD_H
+
+struct kspd_notifications {
+ void (*kspd_sp_exit)(int sp_id);
+
+ struct list_head list;
+};
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+extern void kspd_notify(struct kspd_notifications *notify);
+#else
+static inline void kspd_notify(struct kspd_notifications *notify)
+{
+}
+#endif
+
+#endif
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index 550979a9ea9d..e3315359500a 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -104,65 +104,107 @@ static __inline__ unsigned long ide_default_io_base(int index)
#endif
/* MIPS port and memory-mapped I/O string operations. */
+static inline void __ide_flush_prologue(void)
+{
+#ifdef CONFIG_SMP
+ if (cpu_has_dc_aliases)
+ preempt_disable();
+#endif
+}
+
+static inline void __ide_flush_epilogue(void)
+{
+#ifdef CONFIG_SMP
+ if (cpu_has_dc_aliases)
+ preempt_enable();
+#endif
+}
static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
{
if (cpu_has_dc_aliases) {
unsigned long end = addr + size;
- for (; addr < end; addr += PAGE_SIZE)
- flush_dcache_page(virt_to_page(addr));
+
+ while (addr < end) {
+ local_flush_data_cache_page((void *)addr);
+ addr += PAGE_SIZE;
+ }
}
}
+/*
+ * insw() and gang might be called with interrupts disabled, so we can't
+ * send IPIs for flushing due to the potencial of deadlocks, see the comment
+ * above smp_call_function() in arch/mips/kernel/smp.c. We work around the
+ * problem by disabling preemption so we know we actually perform the flush
+ * on the processor that actually has the lines to be flushed which hopefully
+ * is even better for performance anyway.
+ */
static inline void __ide_insw(unsigned long port, void *addr,
unsigned int count)
{
+ __ide_flush_prologue();
insw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
{
+ __ide_flush_prologue();
insl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
static inline void __ide_outsw(unsigned long port, const void *addr,
unsigned long count)
{
+ __ide_flush_prologue();
outsw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_outsl(unsigned long port, const void *addr,
unsigned long count)
{
+ __ide_flush_prologue();
outsl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
{
+ __ide_flush_prologue();
readsw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
{
+ __ide_flush_prologue();
readsl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
{
+ __ide_flush_prologue();
writesw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
{
+ __ide_flush_prologue();
writesl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
/* ide_insw calls insw, not __ide_insw. Why? */
diff --git a/include/asm-mips/mach-jmr3927/ds1742.h b/include/asm-mips/mach-jmr3927/ds1742.h
index cff6192d4bdb..8a8fef6d07fa 100644
--- a/include/asm-mips/mach-jmr3927/ds1742.h
+++ b/include/asm-mips/mach-jmr3927/ds1742.h
@@ -3,14 +3,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2003 by Ralf Baechle
+ * Copyright (C) 2003, 06 by Ralf Baechle
*/
#ifndef __ASM_MACH_JMR3927_DS1742_H
#define __ASM_MACH_JMR3927_DS1742_H
#include <asm/jmr3927/jmr3927.h>
-#define rtc_read(reg) (jmr3927_nvram_in(addr))
+#define rtc_read(reg) (jmr3927_nvram_in(reg))
#define rtc_write(data, reg) (jmr3927_nvram_out((data),(reg)))
#endif /* __ASM_MACH_JMR3927_DS1742_H */
diff --git a/include/asm-mips/mach-mips/param.h b/include/asm-mips/mach-mips/param.h
new file mode 100644
index 000000000000..805ef6d27d3c
--- /dev/null
+++ b/include/asm-mips/mach-mips/param.h
@@ -0,0 +1,13 @@
+/*
+ * 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 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_MIPS_PARAM_H
+#define __ASM_MACH_MIPS_PARAM_H
+
+#define HZ 100 /* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_MIPS_PARAM_H */
diff --git a/include/asm-mips/marvell.h b/include/asm-mips/marvell.h
index 9225b3397a4f..6bb2125bb053 100644
--- a/include/asm-mips/marvell.h
+++ b/include/asm-mips/marvell.h
@@ -53,4 +53,6 @@ struct mv_pci_controller {
unsigned long config_vreg;
};
+extern void ll_mv64340_irq(struct pt_regs *regs);
+
#endif /* __ASM_MIPS_MARVELL_H */
diff --git a/include/asm-mips/mips-boards/atlas.h b/include/asm-mips/mips-boards/atlas.h
index 0998151fb3a1..a8ae12d120ee 100644
--- a/include/asm-mips/mips-boards/atlas.h
+++ b/include/asm-mips/mips-boards/atlas.h
@@ -33,13 +33,29 @@
#define ATLAS_RTC_ADR_REG 0x1f000800
#define ATLAS_RTC_DAT_REG 0x1f000808
-
/*
* Atlas interrupt controller register base.
*/
#define ATLAS_ICTRL_REGS_BASE 0x1f000000
/*
+ * Atlas registers are memory mapped on 64-bit aligned boundaries and
+ * only word access are allowed.
+ */
+struct atlas_ictrl_regs {
+ volatile unsigned int intraw;
+ int dummy1;
+ volatile unsigned int intseten;
+ int dummy2;
+ volatile unsigned int intrsten;
+ int dummy3;
+ volatile unsigned int intenable;
+ int dummy4;
+ volatile unsigned int intstatus;
+ int dummy5;
+};
+
+/*
* Atlas UART register base.
*/
#define ATLAS_UART_REGS_BASE 0x1f000900
diff --git a/include/asm-mips/mips-boards/atlasint.h b/include/asm-mips/mips-boards/atlasint.h
index bba35c183d08..fd7ebc54fa90 100644
--- a/include/asm-mips/mips-boards/atlasint.h
+++ b/include/asm-mips/mips-boards/atlasint.h
@@ -62,23 +62,4 @@
#define ATLASINT_RES31 (ATLASINT_BASE+31)
#define ATLASINT_END (ATLASINT_BASE+31)
-/*
- * Atlas registers are memory mapped on 64-bit aligned boundaries and
- * only word access are allowed.
- */
-struct atlas_ictrl_regs {
- volatile unsigned int intraw;
- int dummy1;
- volatile unsigned int intseten;
- int dummy2;
- volatile unsigned int intrsten;
- int dummy3;
- volatile unsigned int intenable;
- int dummy4;
- volatile unsigned int intstatus;
- int dummy5;
-};
-
-extern void atlasint_init(void);
-
#endif /* !(_MIPS_ATLASINT_H) */
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index 25b6ffc26623..fa8b913cc3e0 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -67,6 +67,7 @@
#define MIPS_REVISION_CORID_CORE_FPGA2 7
#define MIPS_REVISION_CORID_CORE_FPGAR2 8
#define MIPS_REVISION_CORID_CORE_FPGA3 9
+#define MIPS_REVISION_CORID_CORE_24K 10
/**** Artificial corid defines ****/
/*
diff --git a/include/asm-mips/mips_mt.h b/include/asm-mips/mips_mt.h
new file mode 100644
index 000000000000..c31a312b9783
--- /dev/null
+++ b/include/asm-mips/mips_mt.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions and decalrations for MIPS MT support
+ * that are common between SMTC, VSMP, and/or AP/SP
+ * kernel models.
+ */
+#ifndef __ASM_MIPS_MT_H
+#define __ASM_MIPS_MT_H
+
+extern cpumask_t mt_fpu_cpumask;
+extern unsigned long mt_fpemul_threshold;
+
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
+extern void mips_mt_set_cpuoptions(void);
+
+#endif /* __ASM_MIPS_MT_H */
diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
index a669c0702c66..f637ce70758f 100644
--- a/include/asm-mips/mipsmtregs.h
+++ b/include/asm-mips/mipsmtregs.h
@@ -165,7 +165,7 @@
#ifndef __ASSEMBLY__
-extern void mips_mt_regdump(void);
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
static inline unsigned int dvpe(void)
{
@@ -234,7 +234,7 @@ static inline void __raw_emt(void)
__asm__ __volatile__(
" .set noreorder \n"
" .set mips32r2 \n"
- " emt \n"
+ " .word 0x41600be1 # emt \n"
" ehb \n"
" .set mips0 \n"
" .set reorder");
@@ -282,8 +282,11 @@ static inline void ehb(void)
\
__asm__ __volatile__( \
" .set push \n" \
+ " .set noat \n" \
" .set mips32r2 \n" \
- " mftgpr %0," #rt " \n" \
+ " # mftgpr $1," #rt " \n" \
+ " .word 0x41000820 | (" #rt " << 16) \n" \
+ " move %0, $1 \n" \
" .set pop \n" \
: "=r" (__res)); \
\
@@ -295,9 +298,7 @@ static inline void ehb(void)
unsigned long __res; \
\
__asm__ __volatile__( \
- ".set noat\n\t" \
- "mftr\t%0, " #rt ", " #u ", " #sel "\n\t" \
- ".set at\n\t" \
+ " mftr %0, " #rt ", " #u ", " #sel " \n" \
: "=r" (__res)); \
\
__res; \
@@ -364,6 +365,9 @@ do { \
#define read_vpe_c0_ebase() mftc0(15,1)
#define write_vpe_c0_ebase(val) mttc0(15, 1, val)
#define write_vpe_c0_compare(val) mttc0(11, 0, val)
+#define read_vpe_c0_badvaddr() mftc0(8, 0)
+#define read_vpe_c0_epc() mftc0(14, 0)
+#define write_vpe_c0_epc(val) mttc0(14, 0, val)
/* TC */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 035ba0a9b0df..a2ef579f6b1a 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -836,6 +836,9 @@ do { \
#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */
#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val)
+#define read_c0_badvaddr() __read_ulong_c0_register($8, 0)
+#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
+
#define read_c0_count() __read_32bit_c0_register($9, 0)
#define write_c0_count(val) __write_32bit_c0_register($9, 0, val)
@@ -858,7 +861,19 @@ do { \
#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val)
#define read_c0_status() __read_32bit_c0_register($12, 0)
+#ifdef CONFIG_MIPS_MT_SMTC
+#define write_c0_status(val) \
+do { \
+ __write_32bit_c0_register($12, 0, val); \
+ __ehb(); \
+} while (0)
+#else
+/*
+ * Legacy non-SMTC code, which may be hazardous
+ * but which might not support EHB
+ */
#define write_c0_status(val) __write_32bit_c0_register($12, 0, val)
+#endif /* CONFIG_MIPS_MT_SMTC */
#define read_c0_cause() __read_32bit_c0_register($13, 0)
#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val)
@@ -1001,6 +1016,9 @@ do { \
#define read_c0_taglo() __read_32bit_c0_register($28, 0)
#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val)
+#define read_c0_dtaglo() __read_32bit_c0_register($28, 2)
+#define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val)
+
#define read_c0_taghi() __read_32bit_c0_register($29, 0)
#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val)
@@ -1354,15 +1372,119 @@ static inline void tlb_write_random(void)
/*
* Manipulate bits in a c0 register.
*/
+#ifndef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Linux requires shutting-down microthread scheduling
+ * during CP0 register read-modify-write sequences.
+ */
+#define __BUILD_SET_C0(name) \
+static inline unsigned int \
+set_c0_##name(unsigned int set) \
+{ \
+ unsigned int res; \
+ \
+ res = read_c0_##name(); \
+ res |= set; \
+ write_c0_##name(res); \
+ \
+ return res; \
+} \
+ \
+static inline unsigned int \
+clear_c0_##name(unsigned int clear) \
+{ \
+ unsigned int res; \
+ \
+ res = read_c0_##name(); \
+ res &= ~clear; \
+ write_c0_##name(res); \
+ \
+ return res; \
+} \
+ \
+static inline unsigned int \
+change_c0_##name(unsigned int change, unsigned int new) \
+{ \
+ unsigned int res; \
+ \
+ res = read_c0_##name(); \
+ res &= ~change; \
+ res |= (new & change); \
+ write_c0_##name(res); \
+ \
+ return res; \
+}
+
+#else /* SMTC versions that manage MT scheduling */
+
+#include <asm/interrupt.h>
+
+/*
+ * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
+ * header file recursion.
+ */
+static inline unsigned int __dmt(void)
+{
+ int res;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips32r2 \n"
+ " .set noat \n"
+ " .word 0x41610BC1 # dmt $1 \n"
+ " ehb \n"
+ " move %0, $1 \n"
+ " .set pop \n"
+ : "=r" (res));
+
+ instruction_hazard();
+
+ return res;
+}
+
+#define __VPECONTROL_TE_SHIFT 15
+#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT)
+
+#define __EMT_ENABLE __VPECONTROL_TE
+
+static inline void __emt(unsigned int previous)
+{
+ if ((previous & __EMT_ENABLE))
+ __asm__ __volatile__(
+ " .set noreorder \n"
+ " .set mips32r2 \n"
+ " .word 0x41600be1 # emt \n"
+ " ehb \n"
+ " .set mips0 \n"
+ " .set reorder \n");
+}
+
+static inline void __ehb(void)
+{
+ __asm__ __volatile__(
+ " ehb \n");
+}
+
+/*
+ * Note that local_irq_save/restore affect TC-specific IXMT state,
+ * not Status.IE as in non-SMTC kernel.
+ */
+
#define __BUILD_SET_C0(name) \
static inline unsigned int \
set_c0_##name(unsigned int set) \
{ \
unsigned int res; \
+ unsigned int omt; \
+ unsigned int flags; \
\
+ local_irq_save(flags); \
+ omt = __dmt(); \
res = read_c0_##name(); \
res |= set; \
write_c0_##name(res); \
+ __emt(omt); \
+ local_irq_restore(flags); \
\
return res; \
} \
@@ -1371,10 +1493,16 @@ static inline unsigned int \
clear_c0_##name(unsigned int clear) \
{ \
unsigned int res; \
+ unsigned int omt; \
+ unsigned int flags; \
\
+ local_irq_save(flags); \
+ omt = __dmt(); \
res = read_c0_##name(); \
res &= ~clear; \
write_c0_##name(res); \
+ __emt(omt); \
+ local_irq_restore(flags); \
\
return res; \
} \
@@ -1383,14 +1511,22 @@ static inline unsigned int \
change_c0_##name(unsigned int change, unsigned int new) \
{ \
unsigned int res; \
+ unsigned int omt; \
+ unsigned int flags; \
\
+ local_irq_save(flags); \
+ \
+ omt = __dmt(); \
res = read_c0_##name(); \
res &= ~change; \
res |= (new & change); \
write_c0_##name(res); \
+ __emt(omt); \
+ local_irq_restore(flags); \
\
return res; \
}
+#endif
__BUILD_SET_C0(status)
__BUILD_SET_C0(cause)
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 61cf22588137..6e09f4c87211 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -17,6 +17,10 @@
#include <linux/slab.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#include <asm/smtc.h>
+#endif /* SMTC */
/*
* For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -54,6 +58,14 @@ extern unsigned long pgd_current[];
#define ASID_INC 0x1
#define ASID_MASK 0xfff
+/* SMTC/34K debug hack - but maybe we'll keep it */
+#elif defined(CONFIG_MIPS_MT_SMTC)
+
+#define ASID_INC 0x1
+extern unsigned long smtc_asid_mask;
+#define ASID_MASK (smtc_asid_mask)
+#define HW_ASID_MASK 0xff
+/* End SMTC/34K debug hack */
#else /* FIXME: not correct for R6000 */
#define ASID_INC 0x1
@@ -76,6 +88,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
+#ifndef CONFIG_MIPS_MT_SMTC
+/* Normal, classic MIPS get_new_mmu_context */
static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
{
@@ -91,6 +105,12 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
}
+#else /* CONFIG_MIPS_MT_SMTC */
+
+#define get_new_mmu_context(mm,cpu) smtc_get_new_mmu_context((mm),(cpu))
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -111,14 +131,46 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
{
unsigned int cpu = smp_processor_id();
unsigned long flags;
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long oldasid;
+ unsigned long mtflags;
+ int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
local_irq_save(flags);
+ mtflags = dvpe();
+#else /* Not SMTC */
+ local_irq_save(flags);
+#endif /* CONFIG_MIPS_MT_SMTC */
/* Check if our ASID is of an older version and thus invalid */
if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
get_new_mmu_context(next, cpu);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * If the EntryHi ASID being replaced happens to be
+ * the value flagged at ASID recycling time as having
+ * an extended life, clear the bit showing it being
+ * in use by this "CPU", and if that's the last bit,
+ * free up the ASID value for use and flush any old
+ * instances of it from the TLB.
+ */
+ oldasid = (read_c0_entryhi() & ASID_MASK);
+ if(smtc_live_asid[mytlb][oldasid]) {
+ smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+ if(smtc_live_asid[mytlb][oldasid] == 0)
+ smtc_flush_tlb_asid(oldasid);
+ }
+ /*
+ * Tread softly on EntryHi, and so long as we support
+ * having ASID_MASK smaller than the hardware maximum,
+ * make sure no "soft" bits become "hard"...
+ */
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+ | (cpu_context(cpu, next) & ASID_MASK));
+ ehb(); /* Make sure it propagates to TCStatus */
+ evpe(mtflags);
+#else
write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/*
@@ -151,12 +203,34 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
unsigned long flags;
unsigned int cpu = smp_processor_id();
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long oldasid;
+ unsigned long mtflags;
+ int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
+
local_irq_save(flags);
/* Unconditionally get a new ASID. */
get_new_mmu_context(next, cpu);
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* See comments for similar code above */
+ mtflags = dvpe();
+ oldasid = read_c0_entryhi() & ASID_MASK;
+ if(smtc_live_asid[mytlb][oldasid]) {
+ smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+ if(smtc_live_asid[mytlb][oldasid] == 0)
+ smtc_flush_tlb_asid(oldasid);
+ }
+ /* See comments for similar code above */
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+ (cpu_context(cpu, next) & ASID_MASK));
+ ehb(); /* Make sure it propagates to TCStatus */
+ evpe(mtflags);
+#else
write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/* mark mmu ownership change */
@@ -174,17 +248,49 @@ static inline void
drop_mmu_context(struct mm_struct *mm, unsigned cpu)
{
unsigned long flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long oldasid;
+ /* Can't use spinlock because called from TLB flush within DVPE */
+ unsigned int prevvpe;
+ int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
local_irq_save(flags);
if (cpu_isset(cpu, mm->cpu_vm_mask)) {
get_new_mmu_context(mm, cpu);
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* See comments for similar code above */
+ prevvpe = dvpe();
+ oldasid = (read_c0_entryhi() & ASID_MASK);
+ if(smtc_live_asid[mytlb][oldasid]) {
+ smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+ if(smtc_live_asid[mytlb][oldasid] == 0)
+ smtc_flush_tlb_asid(oldasid);
+ }
+ /* See comments for similar code above */
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+ | cpu_asid(cpu, mm));
+ ehb(); /* Make sure it propagates to TCStatus */
+ evpe(prevvpe);
+#else /* not CONFIG_MIPS_MT_SMTC */
write_c0_entryhi(cpu_asid(cpu, mm));
+#endif /* CONFIG_MIPS_MT_SMTC */
} else {
/* will get a new context next time */
+#ifndef CONFIG_MIPS_MT_SMTC
cpu_context(cpu, mm) = 0;
+#else /* SMTC */
+ int i;
+
+ /* SMTC shares the TLB (and ASIDs) across VPEs */
+ for (i = 0; i < num_online_cpus(); i++) {
+ if((smtc_status & SMTC_TLB_SHARED)
+ || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+ cpu_context(i, mm) = 0;
+ }
+#endif /* CONFIG_MIPS_MT_SMTC */
}
-
local_irq_restore(flags);
}
diff --git a/include/asm-mips/numnodes.h b/include/asm-mips/numnodes.h
deleted file mode 100644
index 4f00c16ceeb0..000000000000
--- a/include/asm-mips/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 128 Nodes */
-#define NODES_SHIFT 6
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 39d2bd50fece..0fb75f0762e0 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -12,6 +12,7 @@
#define _ASM_PROCESSOR_H
#include <linux/config.h>
+#include <linux/cpumask.h>
#include <linux/threads.h>
#include <asm/cachectl.h>
@@ -107,6 +108,10 @@ struct mips_dsp_state {
#define INIT_DSP {{0,},}
+#define INIT_CPUMASK { \
+ {0,} \
+}
+
typedef struct {
unsigned long seg;
} mm_segment_t;
@@ -129,6 +134,12 @@ struct thread_struct {
/* Saved fpu/fpu emulator stuff. */
union mips_fpu_union fpu;
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* Emulated instruction count */
+ unsigned long emulated_fp;
+ /* Saved per-thread scheduler affinity mask */
+ cpumask_t user_cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
/* Saved state of the DSP ASE, if available. */
struct mips_dsp_state dsp;
@@ -142,6 +153,7 @@ struct thread_struct {
#define MF_LOGADE 2 /* Log address errors to syslog */
#define MF_32BIT_REGS 4 /* also implies 16/32 fprs */
#define MF_32BIT_ADDR 8 /* 32-bit address space (o32/n32) */
+#define MF_FPUBOUND 0x10 /* thread bound to FPU-full CPU set */
unsigned long mflags;
unsigned long irix_trampoline; /* Wheee... */
unsigned long irix_oldctx;
@@ -153,6 +165,12 @@ struct thread_struct {
#define MF_N32 MF_32BIT_ADDR
#define MF_N64 0
+#ifdef CONFIG_MIPS_MT_FPAFF
+#define FPAFF_INIT 0, INIT_CPUMASK,
+#else
+#define FPAFF_INIT
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
#define INIT_THREAD { \
/* \
* saved main processor registers \
@@ -168,6 +186,10 @@ struct thread_struct {
*/ \
INIT_FPU, \
/* \
+ * fpu affinity state (null if not FPAFF) \
+ */ \
+ FPAFF_INIT \
+ /* \
* saved dsp/dsp emulator stuff \
*/ \
INIT_DSP, \
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 95c5839ac465..fa9d8713c12a 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -45,6 +45,10 @@ struct pt_regs {
unsigned long cp0_badvaddr;
unsigned long cp0_cause;
unsigned long cp0_epc;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long cp0_tcstatus;
+ unsigned long smtc_pad;
+#endif /* CONFIG_MIPS_MT_SMTC */
};
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index 90c374700977..3c8e3c8d1a9a 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -15,6 +15,7 @@
#include <asm/asm.h>
#include <asm/cacheops.h>
#include <asm/cpu-features.h>
+#include <asm/mipsmtregs.h>
/*
* This macro return a properly sign-extended address suitable as base address
@@ -37,16 +38,120 @@
" cache %0, %1 \n" \
" .set pop \n" \
: \
- : "i" (op), "m" (*(unsigned char *)(addr)))
+ : "i" (op), "R" (*(unsigned char *)(addr)))
+
+#ifdef CONFIG_MIPS_MT
+/*
+ * Temporary hacks for SMTC debug. Optionally force single-threaded
+ * execution during I-cache flushes.
+ */
+
+#define PROTECT_CACHE_FLUSHES 1
+
+#ifdef PROTECT_CACHE_FLUSHES
+
+extern int mt_protiflush;
+extern int mt_protdflush;
+extern void mt_cflush_lockdown(void);
+extern void mt_cflush_release(void);
+
+#define BEGIN_MT_IPROT \
+ unsigned long flags = 0; \
+ unsigned long mtflags = 0; \
+ if(mt_protiflush) { \
+ local_irq_save(flags); \
+ ehb(); \
+ mtflags = dvpe(); \
+ mt_cflush_lockdown(); \
+ }
+
+#define END_MT_IPROT \
+ if(mt_protiflush) { \
+ mt_cflush_release(); \
+ evpe(mtflags); \
+ local_irq_restore(flags); \
+ }
+
+#define BEGIN_MT_DPROT \
+ unsigned long flags = 0; \
+ unsigned long mtflags = 0; \
+ if(mt_protdflush) { \
+ local_irq_save(flags); \
+ ehb(); \
+ mtflags = dvpe(); \
+ mt_cflush_lockdown(); \
+ }
+
+#define END_MT_DPROT \
+ if(mt_protdflush) { \
+ mt_cflush_release(); \
+ evpe(mtflags); \
+ local_irq_restore(flags); \
+ }
+
+#else
+
+#define BEGIN_MT_IPROT
+#define BEGIN_MT_DPROT
+#define END_MT_IPROT
+#define END_MT_DPROT
+
+#endif /* PROTECT_CACHE_FLUSHES */
+
+#define __iflush_prologue \
+ unsigned long redundance; \
+ extern int mt_n_iflushes; \
+ BEGIN_MT_IPROT \
+ for (redundance = 0; redundance < mt_n_iflushes; redundance++) {
+
+#define __iflush_epilogue \
+ END_MT_IPROT \
+ }
+
+#define __dflush_prologue \
+ unsigned long redundance; \
+ extern int mt_n_dflushes; \
+ BEGIN_MT_DPROT \
+ for (redundance = 0; redundance < mt_n_dflushes; redundance++) {
+
+#define __dflush_epilogue \
+ END_MT_DPROT \
+ }
+
+#define __inv_dflush_prologue __dflush_prologue
+#define __inv_dflush_epilogue __dflush_epilogue
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue __sflush_prologue
+#define __inv_sflush_epilogue __sflush_epilogue
+
+#else /* CONFIG_MIPS_MT */
+
+#define __iflush_prologue {
+#define __iflush_epilogue }
+#define __dflush_prologue {
+#define __dflush_epilogue }
+#define __inv_dflush_prologue {
+#define __inv_dflush_epilogue }
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue {
+#define __inv_sflush_epilogue }
+
+#endif /* CONFIG_MIPS_MT */
static inline void flush_icache_line_indexed(unsigned long addr)
{
+ __iflush_prologue
cache_op(Index_Invalidate_I, addr);
+ __iflush_epilogue
}
static inline void flush_dcache_line_indexed(unsigned long addr)
{
+ __dflush_prologue
cache_op(Index_Writeback_Inv_D, addr);
+ __dflush_epilogue
}
static inline void flush_scache_line_indexed(unsigned long addr)
@@ -56,17 +161,23 @@ static inline void flush_scache_line_indexed(unsigned long addr)
static inline void flush_icache_line(unsigned long addr)
{
+ __iflush_prologue
cache_op(Hit_Invalidate_I, addr);
+ __iflush_epilogue
}
static inline void flush_dcache_line(unsigned long addr)
{
+ __dflush_prologue
cache_op(Hit_Writeback_Inv_D, addr);
+ __dflush_epilogue
}
static inline void invalidate_dcache_line(unsigned long addr)
{
+ __dflush_prologue
cache_op(Hit_Invalidate_D, addr);
+ __dflush_epilogue
}
static inline void invalidate_scache_line(unsigned long addr)
@@ -239,9 +350,13 @@ static inline void blast_##pfx##cache##lsize(void) \
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
+ __##pfx##flush_prologue \
+ \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws,indexop); \
+ \
+ __##pfx##flush_epilogue \
} \
\
static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
@@ -249,10 +364,14 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
unsigned long start = page; \
unsigned long end = page + PAGE_SIZE; \
\
+ __##pfx##flush_prologue \
+ \
do { \
cache##lsize##_unroll32(start,hitop); \
start += lsize * 32; \
} while (start < end); \
+ \
+ __##pfx##flush_epilogue \
} \
\
static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
@@ -265,9 +384,13 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
+ __##pfx##flush_prologue \
+ \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws,indexop); \
+ \
+ __##pfx##flush_epilogue \
}
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
@@ -288,12 +411,17 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
unsigned long lsize = cpu_##desc##_line_size(); \
unsigned long addr = start & ~(lsize - 1); \
unsigned long aend = (end - 1) & ~(lsize - 1); \
+ \
+ __##pfx##flush_prologue \
+ \
while (1) { \
prot##cache_op(hitop, addr); \
if (addr == aend) \
break; \
addr += lsize; \
} \
+ \
+ __##pfx##flush_epilogue \
}
__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
index a2abc4572b63..82ad401c7dca 100644
--- a/include/asm-mips/rtc.h
+++ b/include/asm-mips/rtc.h
@@ -32,7 +32,7 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
{
unsigned long nowtime;
- nowtime = rtc_get_time();
+ nowtime = rtc_mips_get_time();
to_tm(nowtime, time);
time->tm_year -= 1900;
@@ -47,7 +47,7 @@ static inline int set_rtc_time(struct rtc_time *time)
nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
time->tm_mday, time->tm_hour, time->tm_min,
time->tm_sec);
- ret = rtc_set_time(nowtime);
+ ret = rtc_mips_set_time(nowtime);
return ret;
}
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h
index 1298c3fdf6c9..76cd51c6be39 100644
--- a/include/asm-mips/rtlx.h
+++ b/include/asm-mips/rtlx.h
@@ -3,32 +3,46 @@
*
*/
-#ifndef _RTLX_H
-#define _RTLX_H_
+#ifndef __ASM_RTLX_H
+#define __ASM_RTLX_H_
#define LX_NODE_BASE 10
#define MIPSCPU_INT_BASE 16
#define MIPS_CPU_RTLX_IRQ 0
-#define RTLX_VERSION 1
+#define RTLX_VERSION 2
#define RTLX_xID 0x12345600
#define RTLX_ID (RTLX_xID | RTLX_VERSION)
#define RTLX_CHANNELS 8
-#define RTLX_BUFFER_SIZE 1024
+#define RTLX_CHANNEL_STDIO 0
+#define RTLX_CHANNEL_DBG 1
+#define RTLX_CHANNEL_SYSIO 2
-/*
- * lx_state bits
- */
-#define RTLX_STATE_OPENED 1UL
+extern int rtlx_open(int index, int can_sleep);
+extern int rtlx_release(int index);
+extern ssize_t rtlx_read(int index, void *buff, size_t count, int user);
+extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user);
+extern unsigned int rtlx_read_poll(int index, int can_sleep);
+extern unsigned int rtlx_write_poll(int index);
+
+enum rtlx_state {
+ RTLX_STATE_UNUSED,
+ RTLX_STATE_INITIALISED,
+ RTLX_STATE_REMOTE_READY,
+ RTLX_STATE_OPENED
+};
+
+#define RTLX_BUFFER_SIZE 1024
/* each channel supports read and write.
linux (vpe0) reads lx_buffer and writes rt_buffer
SP (vpe1) reads rt_buffer and writes lx_buffer
*/
struct rtlx_channel {
- unsigned long lx_state;
+ enum rtlx_state rt_state;
+ enum rtlx_state lx_state;
int buffer_size;
@@ -38,15 +52,13 @@ struct rtlx_channel {
int lx_write, lx_read;
char *lx_buffer;
-
- void *queues;
-
};
struct rtlx_info {
unsigned long id;
+ enum rtlx_state state;
struct rtlx_channel channel[RTLX_CHANNELS];
};
-#endif /* _RTLX_H_ */
+#endif /* __ASM_RTLX_H_ */
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index 7b2366412203..7196ceb0e948 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -77,15 +77,15 @@
#include <asm/it8712.h>
#define ITE_SERIAL_PORT_DEFNS \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
- .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
{ .baud_base = (24000000/(16*13)), .port = (IT8172_PCI_IO_BASE + IT8712_UART1_PORT), \
- .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
/* Smart Card Reader 0 */ \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR0_BASE), \
- .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
/* Smart Card Reader 1 */ \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
- .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+ .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
#else
#define ITE_SERIAL_PORT_DEFNS
#endif
@@ -95,10 +95,10 @@
#include <asm/it8172/it8172_int.h>
#define IVR_SERIAL_PORT_DEFNS \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
- .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
/* Smart Card Reader 1 */ \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
- .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+ .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
#else
#define IVR_SERIAL_PORT_DEFNS
#endif
diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h
new file mode 100644
index 000000000000..e1941d1b8726
--- /dev/null
+++ b/include/asm-mips/smtc.h
@@ -0,0 +1,55 @@
+#ifndef _ASM_SMTC_MT_H
+#define _ASM_SMTC_MT_H
+
+/*
+ * Definitions for SMTC multitasking on MIPS MT cores
+ */
+
+#include <asm/mips_mt.h>
+
+/*
+ * System-wide SMTC status information
+ */
+
+extern unsigned int smtc_status;
+
+#define SMTC_TLB_SHARED 0x00000001
+#define SMTC_MTC_ACTIVE 0x00000002
+
+/*
+ * TLB/ASID Management information
+ */
+
+#define MAX_SMTC_TLBS 2
+#define MAX_SMTC_ASIDS 256
+#if NR_CPUS <= 8
+typedef char asiduse;
+#else
+#if NR_CPUS <= 16
+typedef short asiduse;
+#else
+typedef long asiduse;
+#endif
+#endif
+
+extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
+
+void smtc_flush_tlb_asid(unsigned long asid);
+extern int mipsmt_build_cpu_map(int startslot);
+extern void mipsmt_prepare_cpus(void);
+extern void smtc_smp_finish(void);
+extern void smtc_boot_secondary(int cpu, struct task_struct *t);
+
+/*
+ * Sharing the TLB between multiple VPEs means that the
+ * "random" index selection function is not allowed to
+ * select the current value of the Index register. To
+ * avoid additional TLB pressure, the Index registers
+ * are "parked" with an non-Valid value.
+ */
+
+#define PARKED_INDEX ((unsigned int)0x80000000)
+
+#endif /* _ASM_SMTC_MT_H */
diff --git a/include/asm-mips/smtc_ipi.h b/include/asm-mips/smtc_ipi.h
new file mode 100644
index 000000000000..f22c3e2f993a
--- /dev/null
+++ b/include/asm-mips/smtc_ipi.h
@@ -0,0 +1,118 @@
+/*
+ * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
+ */
+#ifndef __ASM_SMTC_IPI_H
+#define __ASM_SMTC_IPI_H
+
+//#define SMTC_IPI_DEBUG
+
+#ifdef SMTC_IPI_DEBUG
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#endif /* SMTC_IPI_DEBUG */
+
+/*
+ * An IPI "message"
+ */
+
+struct smtc_ipi {
+ struct smtc_ipi *flink;
+ int type;
+ void *arg;
+ int dest;
+#ifdef SMTC_IPI_DEBUG
+ int sender;
+ long stamp;
+#endif /* SMTC_IPI_DEBUG */
+};
+
+/*
+ * Defined IPI Types
+ */
+
+#define LINUX_SMP_IPI 1
+#define SMTC_CLOCK_TICK 2
+
+/*
+ * A queue of IPI messages
+ */
+
+struct smtc_ipi_q {
+ struct smtc_ipi *head;
+ spinlock_t lock;
+ struct smtc_ipi *tail;
+ int depth;
+};
+
+extern struct smtc_ipi_q IPIQ[NR_CPUS];
+extern struct smtc_ipi_q freeIPIq;
+
+static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+ long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (q->head == NULL)
+ q->head = q->tail = p;
+ else
+ q->tail->flink = p;
+ p->flink = NULL;
+ q->tail = p;
+ q->depth++;
+#ifdef SMTC_IPI_DEBUG
+ p->sender = read_c0_tcbind();
+ p->stamp = read_c0_count();
+#endif /* SMTC_IPI_DEBUG */
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
+{
+ struct smtc_ipi *p;
+ long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (q->head == NULL)
+ p = NULL;
+ else {
+ p = q->head;
+ q->head = q->head->flink;
+ q->depth--;
+ /* Arguably unnecessary, but leaves queue cleaner */
+ if (q->head == NULL)
+ q->tail = NULL;
+ }
+ spin_unlock_irqrestore(&q->lock, flags);
+ return p;
+}
+
+static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+ long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (q->head == NULL) {
+ q->head = q->tail = p;
+ p->flink = NULL;
+ } else {
+ p->flink = q->head;
+ q->head = p;
+ }
+ q->depth++;
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
+{
+ long flags;
+ int retval;
+
+ spin_lock_irqsave(&q->lock, flags);
+ retval = q->depth;
+ spin_unlock_irqrestore(&q->lock, flags);
+ return retval;
+}
+
+extern void smtc_send_ipi(int cpu, int type, unsigned int action);
+
+#endif /* __ASM_SMTC_IPI_H */
diff --git a/include/asm-mips/smtc_proc.h b/include/asm-mips/smtc_proc.h
new file mode 100644
index 000000000000..25da651f1f5f
--- /dev/null
+++ b/include/asm-mips/smtc_proc.h
@@ -0,0 +1,23 @@
+/*
+ * Definitions for SMTC /proc entries
+ * Copyright(C) 2005 MIPS Technologies Inc.
+ */
+#ifndef __ASM_SMTC_PROC_H
+#define __ASM_SMTC_PROC_H
+
+/*
+ * per-"CPU" statistics
+ */
+
+struct smtc_cpu_proc {
+ unsigned long timerints;
+ unsigned long selfipis;
+};
+
+extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+/* Count of number of recoveries of "stolen" FPU access rights on 34K */
+
+extern atomic_t smtc_fpu_recoveries;
+
+#endif /* __ASM_SMTC_PROC_H */
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 2acf3e844f00..c4856a874965 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -14,9 +14,14 @@
#include <linux/threads.h>
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
.macro SAVE_AT
.set push
.set noat
@@ -57,13 +62,30 @@
#ifdef CONFIG_SMP
.macro get_saved_sp /* SMP variation */
#ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ .set mips32
+ mfc0 k0, CP0_TCBIND;
+ .set mips0
+ lui k1, %hi(kernelsp)
+ srl k0, k0, 19
+ /* No need to shift down and up to clear bits 0-1 */
+#else
mfc0 k0, CP0_CONTEXT
lui k1, %hi(kernelsp)
srl k0, k0, 23
+#endif
addu k1, k0
LONG_L k1, %lo(kernelsp)(k1)
#endif
#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ .set mips64
+ mfc0 k0, CP0_TCBIND;
+ .set mips0
+ lui k0, %highest(kernelsp)
+ dsrl k1, 19
+ /* No need to shift down and up to clear bits 0-2 */
+#else
MFC0 k1, CP0_CONTEXT
lui k0, %highest(kernelsp)
dsrl k1, 23
@@ -71,20 +93,31 @@
dsll k0, k0, 16
daddiu k0, %hi(kernelsp)
dsll k0, k0, 16
+#endif /* CONFIG_MIPS_MT_SMTC */
daddu k1, k1, k0
LONG_L k1, %lo(kernelsp)(k1)
-#endif
+#endif /* CONFIG_64BIT */
.endm
.macro set_saved_sp stackp temp temp2
#ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ mfc0 \temp, CP0_TCBIND
+ srl \temp, 19
+#else
mfc0 \temp, CP0_CONTEXT
srl \temp, 23
#endif
+#endif
#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ mfc0 \temp, CP0_TCBIND
+ dsrl \temp, 19
+#else
MFC0 \temp, CP0_CONTEXT
dsrl \temp, 23
#endif
+#endif
LONG_S \stackp, kernelsp(\temp)
.endm
#else
@@ -122,10 +155,25 @@
PTR_SUBU sp, k1, PT_SIZE
LONG_S k0, PT_R29(sp)
LONG_S $3, PT_R3(sp)
+ /*
+ * You might think that you don't need to save $0,
+ * but the FPU emulator and gdb remote debug stub
+ * need it to operate correctly
+ */
LONG_S $0, PT_R0(sp)
mfc0 v1, CP0_STATUS
LONG_S $2, PT_R2(sp)
LONG_S v1, PT_STATUS(sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * Ideally, these instructions would be shuffled in
+ * to cover the pipeline delay.
+ */
+ .set mips32
+ mfc0 v1, CP0_TCSTATUS
+ .set mips0
+ LONG_S v1, PT_TCSTATUS(sp)
+#endif /* CONFIG_MIPS_MT_SMTC */
LONG_S $4, PT_R4(sp)
mfc0 v1, CP0_CAUSE
LONG_S $5, PT_R5(sp)
@@ -234,14 +282,36 @@
.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
.set noat
+#ifdef CONFIG_MIPS_MT_SMTC
+ .set mips32r2
+ /*
+ * This may not really be necessary if ints are already
+ * inhibited here.
+ */
+ mfc0 v0, CP0_TCSTATUS
+ ori v0, TCSTATUS_IXMT
+ mtc0 v0, CP0_TCSTATUS
+ ehb
+ DMT 5 # dmt a1
+ jal mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 a0, CP0_STATUS
- ori a0, 0x1f
- xori a0, 0x1f
+ ori a0, STATMASK
+ xori a0, STATMASK
mtc0 a0, CP0_STATUS
li v1, 0xff00
and a0, v1
@@ -250,6 +320,26 @@
and v0, v1
or v0, a0
mtc0 v0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Only after EXL/ERL have been restored to status can we
+ * restore TCStatus.IXMT.
+ */
+ LONG_L v1, PT_TCSTATUS(sp)
+ ehb
+ mfc0 v0, CP0_TCSTATUS
+ andi v1, TCSTATUS_IXMT
+ /* We know that TCStatua.IXMT should be set from above */
+ xori v0, v0, TCSTATUS_IXMT
+ or v0, v0, v1
+ mtc0 v0, CP0_TCSTATUS
+ ehb
+ andi a1, a1, VPECONTROL_TE
+ beqz a1, 1f
+ emt
+1:
+ .set mips0
+#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v1, PT_EPC(sp)
MTC0 v1, CP0_EPC
LONG_L $31, PT_R31(sp)
@@ -302,11 +392,33 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro CLI
+#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1f
or t0, t1
xori t0, 0x1f
mtc0 t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+ /*
+ * For SMTC, we need to set privilege
+ * and disable interrupts only for the
+ * current TC, using the TCStatus register.
+ */
+ mfc0 t0,CP0_TCSTATUS
+ /* Fortunately CU 0 is in the same place in both registers */
+ /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+ li t1, ST0_CU0 | 0x08001c00
+ or t0,t1
+ /* Clear TKSU, leave IXMT */
+ xori t0, 0x00001800
+ mtc0 t0, CP0_TCSTATUS
+ ehb
+ /* We need to leave the global IE bit set, but clear EXL...*/
+ mfc0 t0, CP0_STATUS
+ ori t0, ST0_EXL | ST0_ERL
+ xori t0, ST0_EXL | ST0_ERL
+ mtc0 t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
@@ -315,11 +427,35 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro STI
+#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1f
or t0, t1
xori t0, 0x1e
mtc0 t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+ /*
+ * For SMTC, we need to set privilege
+ * and enable interrupts only for the
+ * current TC, using the TCStatus register.
+ */
+ ehb
+ mfc0 t0,CP0_TCSTATUS
+ /* Fortunately CU 0 is in the same place in both registers */
+ /* Set TCU0, TKSU (for later inversion) and IXMT */
+ li t1, ST0_CU0 | 0x08001c00
+ or t0,t1
+ /* Clear TKSU *and* IXMT */
+ xori t0, 0x00001c00
+ mtc0 t0, CP0_TCSTATUS
+ ehb
+ /* We need to leave the global IE bit set, but clear EXL...*/
+ mfc0 t0, CP0_STATUS
+ ori t0, ST0_EXL
+ xori t0, ST0_EXL
+ mtc0 t0, CP0_STATUS
+ /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
+#endif /* CONFIG_MIPS_MT_SMTC */
irq_enable_hazard
.endm
@@ -328,11 +464,56 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro KMODE
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * This gets baroque in SMTC. We want to
+ * protect the non-atomic clearing of EXL
+ * with DMT/EMT, but we don't want to take
+ * an interrupt while DMT is still in effect.
+ */
+
+ /* KMODE gets invoked from both reorder and noreorder code */
+ .set push
+ .set mips32r2
+ .set noreorder
+ mfc0 v0, CP0_TCSTATUS
+ andi v1, v0, TCSTATUS_IXMT
+ ori v0, TCSTATUS_IXMT
+ mtc0 v0, CP0_TCSTATUS
+ ehb
+ DMT 2 # dmt v0
+ /*
+ * We don't know a priori if ra is "live"
+ */
+ move t0, ra
+ jal mips_ihb
+ nop /* delay slot */
+ move ra, t0
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1e
or t0, t1
xori t0, 0x1e
mtc0 t0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+ ehb
+ andi v0, v0, VPECONTROL_TE
+ beqz v0, 2f
+ nop /* delay slot */
+ emt
+2:
+ mfc0 v0, CP0_TCSTATUS
+ /* Clear IXMT, then OR in previous value */
+ ori v0, TCSTATUS_IXMT
+ xori v0, TCSTATUS_IXMT
+ or v0, v1, v0
+ mtc0 v0, CP0_TCSTATUS
+ /*
+ * irq_disable_hazard below should expand to EHB
+ * on 24K/34K CPUS
+ */
+ .set pop
+#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 4097fac5ac3c..261f71d16a07 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -155,6 +155,37 @@ extern asmlinkage void *resume(void *last, void *next, void *next_ti);
struct task_struct;
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+/*
+ * Handle the scheduler resume end of FPU affinity management. We do this
+ * inline to try to keep the overhead down. If we have been forced to run on
+ * a "CPU" with an FPU because of a previous high level of FP computation,
+ * but did not actually use the FPU during the most recent time-slice (CU1
+ * isn't set), we undo the restriction on cpus_allowed.
+ *
+ * We're not calling set_cpus_allowed() here, because we have no need to
+ * force prompt migration - we're already switching the current CPU to a
+ * different thread.
+ */
+
+#define switch_to(prev,next,last) \
+do { \
+ if (cpu_has_fpu && \
+ (prev->thread.mflags & MF_FPUBOUND) && \
+ (!(KSTK_STATUS(prev) & ST0_CU1))) { \
+ 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, next->thread_info); \
+ if (cpu_has_dsp) \
+ __restore_dsp(current); \
+} while(0)
+
+#else
#define switch_to(prev,next,last) \
do { \
if (cpu_has_dsp) \
@@ -163,6 +194,7 @@ do { \
if (cpu_has_dsp) \
__restore_dsp(current); \
} while(0)
+#endif
/*
* On SMP systems, when the scheduler does migration-cost autodetection,
@@ -440,8 +472,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
extern void set_handler (unsigned long offset, void *addr, unsigned long len);
extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
extern void *set_vi_handler (int n, void *addr);
-extern void *set_vi_srs_handler (int n, void *addr, int regset);
extern void *set_except_vector(int n, void *addr);
+extern unsigned long ebase;
extern void per_cpu_trap_init(void);
extern NORET_TYPE void die(const char *, struct pt_regs *);
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index b5c78a4a0192..1068fe9a0a58 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -324,16 +324,18 @@
#define __NR_pselect6 (__NR_Linux + 301)
#define __NR_ppoll (__NR_Linux + 302)
#define __NR_unshare (__NR_Linux + 303)
+#define __NR_splice (__NR_Linux + 304)
+#define __NR_sync_file_range (__NR_Linux + 305)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 303
+#define __NR_Linux_syscalls 305
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 303
+#define __NR_O32_Linux_syscalls 305
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -604,16 +606,18 @@
#define __NR_pselect6 (__NR_Linux + 260)
#define __NR_ppoll (__NR_Linux + 261)
#define __NR_unshare (__NR_Linux + 262)
+#define __NR_splice (__NR_Linux + 263)
+#define __NR_sync_file_range (__NR_Linux + 264)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 262
+#define __NR_Linux_syscalls 264
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 262
+#define __NR_64_Linux_syscalls 264
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -888,16 +892,18 @@
#define __NR_pselect6 (__NR_Linux + 264)
#define __NR_ppoll (__NR_Linux + 265)
#define __NR_unshare (__NR_Linux + 266)
+#define __NR_splice (__NR_Linux + 267)
+#define __NR_sync_file_range (__NR_Linux + 268)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 266
+#define __NR_Linux_syscalls 268
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 266
+#define __NR_N32_Linux_syscalls 268
#ifndef __ASSEMBLY__
diff --git a/include/asm-mips/vpe.h b/include/asm-mips/vpe.h
new file mode 100644
index 000000000000..c6e1b961537d
--- /dev/null
+++ b/include/asm-mips/vpe.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef _ASM_VPE_H
+#define _ASM_VPE_H
+
+struct vpe_notifications {
+ void (*start)(int vpe);
+ void (*stop)(int vpe);
+
+ struct list_head list;
+};
+
+
+extern int vpe_notify(int index, struct vpe_notifications *notify);
+
+extern void *vpe_get_shared(int index);
+extern int vpe_getuid(int index);
+extern int vpe_getgid(int index);
+extern char *vpe_getcwd(int index);
+
+#endif /* _ASM_VPE_H */
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index 29da31194b91..244f6b8883f4 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -126,24 +126,17 @@ static inline void gsc_writeq(unsigned long long val, unsigned long addr)
extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
-extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
-{
- return __ioremap(offset, size, 0);
-}
-
-/*
- * This one maps high address device memory and turns off caching for that area.
- * it's useful if some control registers are in such an area and write combining
- * or read caching is not desirable:
+/* Most machines react poorly to I/O-space being cacheable... Instead let's
+ * define ioremap() in terms of ioremap_nocache().
*/
-extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
+extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
{
- return __ioremap(offset, size, _PAGE_NO_CACHE /* _PAGE_PCD */);
+ return __ioremap(offset, size, _PAGE_NO_CACHE);
}
+#define ioremap_nocache(off, sz) ioremap((off), (sz))
extern void iounmap(void __iomem *addr);
-
static inline unsigned char __raw_readb(const volatile void __iomem *addr)
{
return (*(volatile unsigned char __force *) (addr));
diff --git a/include/asm-parisc/numnodes.h b/include/asm-parisc/numnodes.h
deleted file mode 100644
index 6c67651efd1c..000000000000
--- a/include/asm-parisc/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 8 Nodes */
-#define NODES_SHIFT 3
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 45e02aa5bf4b..c0dd461fb8f1 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -1,13 +1,30 @@
#ifndef _PARISC_PAGE_H
#define _PARISC_PAGE_H
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#if !defined(__KERNEL__)
+/* this is for userspace applications (4k page size) */
+# define PAGE_SHIFT 12 /* 4k */
+# define PAGE_SIZE (1UL << PAGE_SHIFT)
+# define PAGE_MASK (~(PAGE_SIZE-1))
+#endif
+
#ifdef __KERNEL__
#include <linux/config.h>
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define PAGE_SHIFT 12 /* 4k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define PAGE_SHIFT 14 /* 16k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define PAGE_SHIFT 16 /* 64k */
+#else
+# error "unknown default kernel page size"
+#endif
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+
#ifndef __ASSEMBLY__
#include <asm/types.h>
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index 4e34c6b44059..aec089eb8b85 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -59,16 +59,15 @@
#define ISTACK_SIZE 32768 /* Interrupt Stack Size */
#define ISTACK_ORDER 3
-/* This is the size of the initially mapped kernel memory (i.e. currently
- * 0 to 1<<23 == 8MB */
+/* This is the size of the initially mapped kernel memory */
#ifdef CONFIG_64BIT
-#define KERNEL_INITIAL_ORDER 24
+#define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */
#else
-#define KERNEL_INITIAL_ORDER 23
+#define KERNEL_INITIAL_ORDER 23 /* 0 to 1<<23 = 8MB */
#endif
#define KERNEL_INITIAL_SIZE (1 << KERNEL_INITIAL_ORDER)
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
#define PT_NLEVELS 3
#define PGD_ORDER 1 /* Number of pages per pgd */
#define PMD_ORDER 1 /* Number of pages per pmd */
@@ -111,11 +110,15 @@
#define MAX_ADDRBITS (PGDIR_SHIFT + BITS_PER_PGD)
#define MAX_ADDRESS (1UL << MAX_ADDRBITS)
-#define SPACEID_SHIFT (MAX_ADDRBITS - 32)
+#define SPACEID_SHIFT (MAX_ADDRBITS - 32)
/* This calculates the number of initial pages we need for the initial
* page tables */
-#define PT_INITIAL (1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#if (KERNEL_INITIAL_ORDER) >= (PMD_SHIFT)
+# define PT_INITIAL (1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#else
+# define PT_INITIAL (1) /* all initial PTEs fit into one page */
+#endif
/*
* pgd entries used up by user/kernel:
@@ -160,6 +163,10 @@ extern void *vmalloc_start;
* to zero */
#define PTE_SHIFT xlate_pabit(_PAGE_USER_BIT)
+/* PFN_PTE_SHIFT defines the shift of a PTE value to access the PFN field */
+#define PFN_PTE_SHIFT 12
+
+
/* this is how many bits may be used by the file functions */
#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_SHIFT)
@@ -188,7 +195,8 @@ extern void *vmalloc_start;
/* The pgd/pmd contains a ptr (in phys addr space); since all pgds/pmds
* are page-aligned, we don't care about the PAGE_OFFSET bits, except
* for a few meta-information bits, so we shift the address to be
- * able to effectively address 40-bits of physical address space. */
+ * able to effectively address 40/42/44-bits of physical address space
+ * depending on 4k/16k/64k PAGE_SIZE */
#define _PxD_PRESENT_BIT 31
#define _PxD_ATTACHED_BIT 30
#define _PxD_VALID_BIT 29
@@ -198,7 +206,7 @@ extern void *vmalloc_start;
#define PxD_FLAG_VALID (1 << xlate_pabit(_PxD_VALID_BIT))
#define PxD_FLAG_MASK (0xf)
#define PxD_FLAG_SHIFT (4)
-#define PxD_VALUE_SHIFT (8)
+#define PxD_VALUE_SHIFT (8) /* (PAGE_SHIFT-PxD_FLAG_SHIFT) */
#ifndef __ASSEMBLY__
@@ -246,6 +254,7 @@ extern void *vmalloc_start;
#define __S110 PAGE_RWX
#define __S111 PAGE_RWX
+
extern pgd_t swapper_pg_dir[]; /* declared in init_task.c */
/* initial page tables for 0-8MB for kernel */
@@ -272,7 +281,7 @@ extern unsigned long *empty_zero_page;
#define pgd_flag(x) (pgd_val(x) & PxD_FLAG_MASK)
#define pgd_address(x) ((unsigned long)(pgd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
/* The first entry of the permanent pmd is not there if it contains
* the gateway marker */
#define pmd_none(x) (!pmd_val(x) || pmd_flag(x) == PxD_FLAG_ATTACHED)
@@ -282,7 +291,7 @@ extern unsigned long *empty_zero_page;
#define pmd_bad(x) (!(pmd_flag(x) & PxD_FLAG_VALID))
#define pmd_present(x) (pmd_flag(x) & PxD_FLAG_PRESENT)
static inline void pmd_clear(pmd_t *pmd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
if (pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
/* This is the entry pointing to the permanent pmd
* attached to the pgd; cannot clear it */
@@ -303,7 +312,7 @@ static inline void pmd_clear(pmd_t *pmd) {
#define pgd_bad(x) (!(pgd_flag(x) & PxD_FLAG_VALID))
#define pgd_present(x) (pgd_flag(x) & PxD_FLAG_PRESENT)
static inline void pgd_clear(pgd_t *pgd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
if(pgd_flag(*pgd) & PxD_FLAG_ATTACHED)
/* This is the permanent pmd attached to the pgd; cannot
* free it */
@@ -351,7 +360,7 @@ extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return
({ \
pte_t __pte; \
\
- pte_val(__pte) = ((addr)+pgprot_val(pgprot)); \
+ pte_val(__pte) = ((((addr)>>PAGE_SHIFT)<<PFN_PTE_SHIFT) + pgprot_val(pgprot)); \
\
__pte; \
})
@@ -361,20 +370,16 @@ extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return
static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
{
pte_t pte;
- pte_val(pte) = (pfn << PAGE_SHIFT) | pgprot_val(pgprot);
+ pte_val(pte) = (pfn << PFN_PTE_SHIFT) | pgprot_val(pgprot);
return pte;
}
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
-
extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
/* Permanent address of a page. On parisc we don't have highmem. */
-#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
+#define pte_pfn(x) (pte_val(x) >> PFN_PTE_SHIFT)
#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
@@ -499,6 +504,26 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#endif /* !__ASSEMBLY__ */
+
+/* TLB page size encoding - see table 3-1 in parisc20.pdf */
+#define _PAGE_SIZE_ENCODING_4K 0
+#define _PAGE_SIZE_ENCODING_16K 1
+#define _PAGE_SIZE_ENCODING_64K 2
+#define _PAGE_SIZE_ENCODING_256K 3
+#define _PAGE_SIZE_ENCODING_1M 4
+#define _PAGE_SIZE_ENCODING_4M 5
+#define _PAGE_SIZE_ENCODING_16M 6
+#define _PAGE_SIZE_ENCODING_64M 7
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_16K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_64K
+#endif
+
+
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index c56fccbf34ad..0e1a30be2e30 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -780,8 +780,14 @@
#define __NR_readlinkat (__NR_Linux + 285)
#define __NR_fchmodat (__NR_Linux + 286)
#define __NR_faccessat (__NR_Linux + 287)
+#define __NR_unshare (__NR_Linux + 288)
+#define __NR_set_robust_list (__NR_Linux + 289)
+#define __NR_get_robust_list (__NR_Linux + 290)
+#define __NR_splice (__NR_Linux + 291)
+#define __NR_sync_file_range (__NR_Linux + 292)
+#define __NR_tee (__NR_Linux + 293)
-#define __NR_Linux_syscalls 288
+#define __NR_Linux_syscalls 294
#define HPUX_GATEWAY_ADDR 0xC0000004
#define LINUX_GATEWAY_ADDR 0x100
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h
index 5207758a6dd9..868c7139dbff 100644
--- a/include/asm-powerpc/eeh.h
+++ b/include/asm-powerpc/eeh.h
@@ -60,24 +60,10 @@ void __init pci_addr_cache_build(void);
* device (including config space i/o). Call eeh_add_device_late
* to finish the eeh setup for this device.
*/
-void eeh_add_device_early(struct device_node *);
-void eeh_add_device_late(struct pci_dev *dev);
void eeh_add_device_tree_early(struct device_node *);
void eeh_add_device_tree_late(struct pci_bus *);
/**
- * eeh_remove_device - undo EEH setup for the indicated pci device
- * @dev: pci device to be removed
- *
- * This routine should be called when a device is removed from
- * a running system (e.g. by hotplug or dlpar). It unregisters
- * the PCI device from the EEH subsystem. I/O errors affecting
- * this device will no longer be detected after this call; thus,
- * i/o errors affecting this slot may leave this device unusable.
- */
-void eeh_remove_device(struct pci_dev *);
-
-/**
* eeh_remove_device_recursive - undo EEH for device & children.
* @dev: pci device to be removed
*
@@ -116,12 +102,6 @@ static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *d
static inline void pci_addr_cache_build(void) { }
-static inline void eeh_add_device_early(struct device_node *dn) { }
-
-static inline void eeh_add_device_late(struct pci_dev *dev) { }
-
-static inline void eeh_remove_device(struct pci_dev *dev) { }
-
static inline void eeh_add_device_tree_early(struct device_node *dn) { }
static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index b72c04f3f551..6cc7e1fb7bfd 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -4,47 +4,88 @@
#define HVSC .long 0x44000022
-#define H_Success 0
-#define H_Busy 1 /* Hardware busy -- retry later */
-#define H_Closed 2 /* Resource closed */
-#define H_Constrained 4 /* Resource request constrained to max allowed */
-#define H_InProgress 14 /* Kind of like busy */
-#define H_Pending 17 /* returned from H_POLL_PENDING */
-#define H_Continue 18 /* Returned from H_Join on success */
-#define H_LongBusyStartRange 9900 /* Start of long busy range */
-#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */
-#define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */
-#define H_LongBusyOrder100msec 9902 /* Long busy, hint that 100msec is a good time to retry */
-#define H_LongBusyOrder1sec 9903 /* Long busy, hint that 1sec is a good time to retry */
-#define H_LongBusyOrder10sec 9904 /* Long busy, hint that 10sec is a good time to retry */
-#define H_LongBusyOrder100sec 9905 /* Long busy, hint that 100sec is a good time to retry */
-#define H_LongBusyEndRange 9905 /* End of long busy range */
-#define H_Hardware -1 /* Hardware error */
-#define H_Function -2 /* Function not supported */
-#define H_Privilege -3 /* Caller not privileged */
-#define H_Parameter -4 /* Parameter invalid, out-of-range or conflicting */
-#define H_Bad_Mode -5 /* Illegal msr value */
-#define H_PTEG_Full -6 /* PTEG is full */
-#define H_Not_Found -7 /* PTE was not found" */
-#define H_Reserved_DABR -8 /* DABR address is reserved by the hypervisor on this processor" */
-#define H_NoMem -9
-#define H_Authority -10
-#define H_Permission -11
-#define H_Dropped -12
-#define H_SourceParm -13
-#define H_DestParm -14
-#define H_RemoteParm -15
-#define H_Resource -16
+#define H_SUCCESS 0
+#define H_BUSY 1 /* Hardware busy -- retry later */
+#define H_CLOSED 2 /* Resource closed */
+#define H_NOT_AVAILABLE 3
+#define H_CONSTRAINED 4 /* Resource request constrained to max allowed */
+#define H_PARTIAL 5
+#define H_IN_PROGRESS 14 /* Kind of like busy */
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE 16
+#define H_PENDING 17 /* returned from H_POLL_PENDING */
+#define H_CONTINUE 18 /* Returned from H_Join on success */
+#define H_LONG_BUSY_START_RANGE 9900 /* Start of long busy range */
+#define H_LONG_BUSY_ORDER_1_MSEC 9900 /* Long busy, hint that 1msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_MSEC 9901 /* Long busy, hint that 10msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_MSEC 9902 /* Long busy, hint that 100msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_1_SEC 9903 /* Long busy, hint that 1sec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_SEC 9904 /* Long busy, hint that 10sec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_SEC 9905 /* Long busy, hint that 100sec \
+ is a good time to retry */
+#define H_LONG_BUSY_END_RANGE 9905 /* End of long busy range */
+#define H_HARDWARE -1 /* Hardware error */
+#define H_FUNCTION -2 /* Function not supported */
+#define H_PRIVILEGE -3 /* Caller not privileged */
+#define H_PARAMETER -4 /* Parameter invalid, out-of-range or conflicting */
+#define H_BAD_MODE -5 /* Illegal msr value */
+#define H_PTEG_FULL -6 /* PTEG is full */
+#define H_NOT_FOUND -7 /* PTE was not found" */
+#define H_RESERVED_DABR -8 /* DABR address is reserved by the hypervisor on this processor" */
+#define H_NO_MEM -9
+#define H_AUTHORITY -10
+#define H_PERMISSION -11
+#define H_DROPPED -12
+#define H_SOURCE_PARM -13
+#define H_DEST_PARM -14
+#define H_REMOTE_PARM -15
+#define H_RESOURCE -16
+#define H_ADAPTER_PARM -17
+#define H_RH_PARM -18
+#define H_RCQ_PARM -19
+#define H_SCQ_PARM -20
+#define H_EQ_PARM -21
+#define H_RT_PARM -22
+#define H_ST_PARM -23
+#define H_SIGT_PARM -24
+#define H_TOKEN_PARM -25
+#define H_MLENGTH_PARM -27
+#define H_MEM_PARM -28
+#define H_MEM_ACCESS_PARM -29
+#define H_ATTR_PARM -30
+#define H_PORT_PARM -31
+#define H_MCG_PARM -32
+#define H_VL_PARM -33
+#define H_TSIZE_PARM -34
+#define H_TRACE_PARM -35
+
+#define H_MASK_PARM -37
+#define H_MCG_FULL -38
+#define H_ALIAS_EXIST -39
+#define H_P_COUNTER -40
+#define H_TABLE_FULL -41
+#define H_ALT_TABLE -42
+#define H_MR_CONDITION -43
+#define H_NOT_ENOUGH_RESOURCES -44
+#define H_R_STATE -45
+#define H_RESCINDEND -46
+
/* Long Busy is a condition that can be returned by the firmware
* when a call cannot be completed now, but the identical call
* should be retried later. This prevents calls blocking in the
- * firmware for long periods of time. Annoyingly the firmware can return
+ * firmware for long periods of time. Annoyingly the firmware can return
* a range of return codes, hinting at how long we should wait before
* retrying. If you don't care for the hint, the macro below is a good
* way to check for the long_busy return codes
*/
-#define H_isLongBusy(x) ((x >= H_LongBusyStartRange) && (x <= H_LongBusyEndRange))
+#define H_IS_LONG_BUSY(x) ((x >= H_LONG_BUSY_START_RANGE) \
+ && (x <= H_LONG_BUSY_END_RANGE))
/* Flags */
#define H_LARGE_PAGE (1UL<<(63-16))
@@ -66,6 +107,9 @@
#define H_DABRX_KERNEL (1UL<<(63-62))
#define H_DABRX_USER (1UL<<(63-63))
+/* Each control block has to be on a 4K bondary */
+#define H_CB_ALIGNMENT 4096
+
/* pSeries hypervisor opcodes */
#define H_REMOVE 0x04
#define H_ENTER 0x08
@@ -99,25 +143,52 @@
#define H_PERFMON 0x7c
#define H_MIGRATE_DMA 0x78
#define H_REGISTER_VPA 0xDC
-#define H_CEDE 0xE0
+#define H_CEDE 0xE0
#define H_CONFER 0xE4
-#define H_PROD 0xE8
+#define H_PROD 0xE8
#define H_GET_PPP 0xEC
#define H_SET_PPP 0xF0
#define H_PURR 0xF4
-#define H_PIC 0xF8
+#define H_PIC 0xF8
#define H_REG_CRQ 0xFC
#define H_FREE_CRQ 0x100
#define H_VIO_SIGNAL 0x104
#define H_SEND_CRQ 0x108
-#define H_COPY_RDMA 0x110
+#define H_COPY_RDMA 0x110
#define H_SET_XDABR 0x134
#define H_STUFF_TCE 0x138
#define H_PUT_TCE_INDIRECT 0x13C
#define H_VTERM_PARTNER_INFO 0x150
#define H_REGISTER_VTERM 0x154
#define H_FREE_VTERM 0x158
-#define H_POLL_PENDING 0x1D8
+#define H_RESET_EVENTS 0x15C
+#define H_ALLOC_RESOURCE 0x160
+#define H_FREE_RESOURCE 0x164
+#define H_MODIFY_QP 0x168
+#define H_QUERY_QP 0x16C
+#define H_REREGISTER_PMR 0x170
+#define H_REGISTER_SMR 0x174
+#define H_QUERY_MR 0x178
+#define H_QUERY_MW 0x17C
+#define H_QUERY_HCA 0x180
+#define H_QUERY_PORT 0x184
+#define H_MODIFY_PORT 0x188
+#define H_DEFINE_AQP1 0x18C
+#define H_GET_TRACE_BUFFER 0x190
+#define H_DEFINE_AQP0 0x194
+#define H_RESIZE_MR 0x198
+#define H_ATTACH_MCQP 0x19C
+#define H_DETACH_MCQP 0x1A0
+#define H_CREATE_RPT 0x1A4
+#define H_REMOVE_RPT 0x1A8
+#define H_REGISTER_RPAGES 0x1AC
+#define H_DISABLE_AND_GETC 0x1B0
+#define H_ERROR_DATA 0x1B4
+#define H_GET_HCA_INFO 0x1B8
+#define H_GET_PERF_COUNT 0x1BC
+#define H_MANAGE_TRACE 0x1C0
+#define H_QUERY_INT_STATE 0x1E4
+#define H_POLL_PENDING 0x1D8
#define H_JOIN 0x298
#define H_ENABLE_CRQ 0x2B0
@@ -152,7 +223,7 @@ long plpar_hcall_norets(unsigned long opcode, ...);
*/
long plpar_hcall_8arg_2ret(unsigned long opcode,
unsigned long arg1,
- unsigned long arg2,
+ unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5,
@@ -176,6 +247,42 @@ long plpar_hcall_4out(unsigned long opcode,
unsigned long *out3,
unsigned long *out4);
+long plpar_hcall_7arg_7ret(unsigned long opcode,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4,
+ unsigned long arg5,
+ unsigned long arg6,
+ unsigned long arg7,
+ unsigned long *out1,
+ unsigned long *out2,
+ unsigned long *out3,
+ unsigned long *out4,
+ unsigned long *out5,
+ unsigned long *out6,
+ unsigned long *out7);
+
+long plpar_hcall_9arg_9ret(unsigned long opcode,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4,
+ unsigned long arg5,
+ unsigned long arg6,
+ unsigned long arg7,
+ unsigned long arg8,
+ unsigned long arg9,
+ unsigned long *out1,
+ unsigned long *out2,
+ unsigned long *out3,
+ unsigned long *out4,
+ unsigned long *out5,
+ unsigned long *out6,
+ unsigned long *out7,
+ unsigned long *out8,
+ unsigned long *out9);
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HVCALL_H */
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index d5677cbec200..18ca29e9105a 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -70,17 +70,18 @@ extern void iommu_free_table(struct device_node *dn);
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
- struct scatterlist *sglist, int nelems,
+ struct scatterlist *sglist, int nelems, unsigned long mask,
enum dma_data_direction direction);
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction);
extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
+ dma_addr_t *dma_handle, unsigned long mask, gfp_t flag);
extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, enum dma_data_direction direction);
+ size_t size, unsigned long mask,
+ enum dma_data_direction direction);
extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction);
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 51f87d9993b6..7bc6d73b2823 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -54,6 +54,13 @@
*/
extern unsigned int virt_irq_to_real_map[NR_IRQS];
+/* The maximum virtual IRQ number that we support. This
+ * can be set by the platform and will be reduced by the
+ * value of __irq_offset_value. It defaults to and is
+ * capped by (NR_IRQS - 1).
+ */
+extern unsigned int virt_irq_max;
+
/* Create a mapping for a real_irq if it doesn't already exist.
* Return the virtual irq as a convenience.
*/
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5ed847680754..0f9254c18914 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -253,7 +253,11 @@ extern struct machdep_calls *machine_id;
#define __machine_desc __attribute__ ((__section__ (".machine.desc")))
-#define define_machine(name) struct machdep_calls mach_##name __machine_desc =
+#define define_machine(name) \
+ extern struct machdep_calls mach_##name; \
+ EXPORT_SYMBOL(mach_##name); \
+ struct machdep_calls mach_##name __machine_desc =
+
#define machine_is(name) \
({ \
extern struct machdep_calls mach_##name \
diff --git a/include/asm-powerpc/numnodes.h b/include/asm-powerpc/numnodes.h
deleted file mode 100644
index e138edae09dd..000000000000
--- a/include/asm-powerpc/numnodes.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_POWERPC_MAX_NUMNODES_H
-#define _ASM_POWERPC_MAX_NUMNODES_H
-#ifdef __KERNEL__
-
-/* Max 16 Nodes */
-#define NODES_SHIFT 4
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_MAX_NUMNODES_H */
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index ffc7462d77ba..88b553c6b26c 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -37,6 +37,8 @@ struct thread_info {
int preempt_count; /* 0 => preemptable,
<0 => BUG */
struct restart_block restart_block;
+ unsigned long local_flags; /* private flags for thread */
+
/* low level flags - has atomic operations done on it */
unsigned long flags ____cacheline_aligned_in_smp;
};
@@ -143,6 +145,12 @@ static inline struct thread_info *current_thread_info(void)
_TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
+/* Bits in local_flags */
+/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
+#define TLF_NAPPING 0 /* idle thread enabled NAP mode */
+
+#define _TLF_NAPPING (1 << TLF_NAPPING)
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_THREAD_INFO_H */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 536ba0873052..34325e292596 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -302,8 +302,10 @@
#define __NR_ppoll 281
#define __NR_unshare 282
#define __NR_splice 283
+#define __NR_tee 284
+#define __NR_vmsplice 285
-#define __NR_syscalls 284
+#define __NR_syscalls 286
#ifdef __KERNEL__
#define __NR__exit __NR_exit
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index de1d9926aa60..399bf02894dd 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -1,6 +1,8 @@
#ifndef __ARCH_S390_ATOMIC__
#define __ARCH_S390_ATOMIC__
+#include <linux/compiler.h>
+
/*
* include/asm-s390/atomic.h
*
diff --git a/include/asm-s390/cache.h b/include/asm-s390/cache.h
index e20cdd9074db..cdf431b061bb 100644
--- a/include/asm-s390/cache.h
+++ b/include/asm-s390/cache.h
@@ -16,4 +16,6 @@
#define ARCH_KMALLOC_MINALIGN 8
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
#endif
diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h
index 4cbc336e4d60..15fd2eda6c90 100644
--- a/include/asm-s390/ebcdic.h
+++ b/include/asm-s390/ebcdic.h
@@ -14,12 +14,12 @@
#include <types.h>
#endif
-extern __u8 _ascebc_500[]; /* ASCII -> EBCDIC 500 conversion table */
-extern __u8 _ebcasc_500[]; /* EBCDIC 500 -> ASCII conversion table */
-extern __u8 _ascebc[]; /* ASCII -> EBCDIC conversion table */
-extern __u8 _ebcasc[]; /* EBCDIC -> ASCII conversion table */
-extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
-extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */
+extern __u8 _ascebc_500[256]; /* ASCII -> EBCDIC 500 conversion table */
+extern __u8 _ebcasc_500[256]; /* EBCDIC 500 -> ASCII conversion table */
+extern __u8 _ascebc[256]; /* ASCII -> EBCDIC conversion table */
+extern __u8 _ebcasc[256]; /* EBCDIC -> ASCII conversion table */
+extern __u8 _ebc_tolower[256]; /* EBCDIC -> lowercase */
+extern __u8 _ebc_toupper[256]; /* EBCDIC -> uppercase */
static inline void
codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr)
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
index 6a332a9f099c..40c25e166a9b 100644
--- a/include/asm-s390/futex.h
+++ b/include/asm-s390/futex.h
@@ -1,6 +1,121 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_S390_FUTEX_H
+#define _ASM_S390_FUTEX_H
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
-#endif
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+#ifndef __s390x__
+#define __futex_atomic_fixup \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 0b,2b,1b,2b\n" \
+ ".previous"
+#else /* __s390x__ */
+#define __futex_atomic_fixup \
+ ".section __ex_table,\"a\"\n" \
+ " .align 8\n" \
+ " .quad 0b,2b,1b,2b\n" \
+ ".previous"
+#endif /* __s390x__ */
+
+#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \
+ asm volatile(" l %1,0(%6)\n" \
+ "0: " insn \
+ " cs %1,%2,0(%6)\n" \
+ "1: jl 0b\n" \
+ " lhi %0,0\n" \
+ "2:\n" \
+ __futex_atomic_fixup \
+ : "=d" (ret), "=&d" (oldval), "=&d" (newval), \
+ "=m" (*uaddr) \
+ : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
+ "m" (*uaddr) : "cc" );
+
+static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, newval, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ inc_preempt_count();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("lr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("lr %2,%1\nar %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("lr %2,%1\nor %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ dec_preempt_count();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+ case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ default: ret = -ENOSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ int ret;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+ asm volatile(" cs %1,%4,0(%5)\n"
+ "0: lr %0,%1\n"
+ "1:\n"
+#ifndef __s390x__
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,1b\n"
+ ".previous"
+#else /* __s390x__ */
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,1b\n"
+ ".previous"
+#endif /* __s390x__ */
+ : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+ : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+ : "cc", "memory" );
+ return oldval;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_S390_FUTEX_H */
diff --git a/include/asm-sh/numnodes.h b/include/asm-sh/numnodes.h
deleted file mode 100644
index f73e85b72ecb..000000000000
--- a/include/asm-sh/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 2 Nodes */
-#define NODES_SHIFT 1
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index f2c8e14d1fd9..05520cebda12 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -290,7 +290,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
#define __NR_add_key 285
#define __NR_request_key 286
diff --git a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h
index 2a1cfa404ea4..1f8f394ae371 100644
--- a/include/asm-sh64/unistd.h
+++ b/include/asm-sh64/unistd.h
@@ -333,7 +333,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 311
+#define __NR_kexec_load 311
#define __NR_waitid 312
#define __NR_add_key 313
#define __NR_request_key 314
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 64ec640a40ee..32a48f623e2b 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -180,7 +180,7 @@
#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS */
#define __NR_getdomainname 162 /* SunOS Specific */
#define __NR_setdomainname 163 /* Common */
-/* #define __NR_ni_syscall 164 ENOSYS under SunOS */
+/* #define __NR_utrap_install 164 Linux sparc64 specific */
#define __NR_quotactl 165 /* Common */
#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */
#define __NR_mount 167 /* Common */
@@ -248,7 +248,7 @@
#define __NR_setfsgid 229 /* Linux Specific */
#define __NR__newselect 230 /* Linux Specific */
#define __NR_time 231 /* Linux Specific */
-/* #define __NR_oldstat 232 Linux Specific */
+#define __NR_splice 232 /* Linux Specific */
#define __NR_stime 233 /* Linux Specific */
#define __NR_statfs64 234 /* Linux Specific */
#define __NR_fstatfs64 235 /* Linux Specific */
@@ -271,7 +271,7 @@
#define __NR_getsid 252
#define __NR_fdatasync 253
#define __NR_nfsservctl 254
-#define __NR_aplib 255
+#define __NR_sync_file_range 255
#define __NR_clock_settime 256
#define __NR_clock_gettime 257
#define __NR_clock_getres 258
@@ -296,7 +296,7 @@
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
-#define __NR_sys_setaltroot 280
+#define __NR_tee 280
#define __NR_add_key 281
#define __NR_request_key 282
#define __NR_keyctl 283
diff --git a/include/asm-sparc/vga.h b/include/asm-sparc/vga.h
new file mode 100644
index 000000000000..c69d5b2ba19a
--- /dev/null
+++ b/include/asm-sparc/vga.h
@@ -0,0 +1,33 @@
+/*
+ * Access to VGA videoram
+ *
+ * (c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _LINUX_ASM_VGA_H_
+#define _LINUX_ASM_VGA_H_
+
+#include <asm/types.h>
+
+#define VT_BUF_HAVE_RW
+
+#undef scr_writew
+#undef scr_readw
+
+static inline void scr_writew(u16 val, u16 *addr)
+{
+ BUG_ON((long) addr >= 0);
+
+ *addr = val;
+}
+
+static inline u16 scr_readw(const u16 *addr)
+{
+ BUG_ON((long) addr >= 0);
+
+ return *addr;
+}
+
+#define VGA_MAP_MEM(x,s) (x)
+
+#endif
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index 82032e159a76..baef13b58952 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -26,7 +26,7 @@ register unsigned long __local_per_cpu_offset asm("g5");
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
} while (0)
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index a284986b1541..ca80e8aca128 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -250,7 +250,7 @@
#ifdef __KERNEL__
#define __NR_time 231 /* Linux sparc32 */
#endif
-/* #define __NR_oldstat 232 Linux Specific */
+#define __NR_splice 232 /* Linux Specific */
#define __NR_stime 233 /* Linux Specific */
#define __NR_statfs64 234 /* Linux Specific */
#define __NR_fstatfs64 235 /* Linux Specific */
@@ -273,7 +273,7 @@
#define __NR_getsid 252
#define __NR_fdatasync 253
#define __NR_nfsservctl 254
-#define __NR_aplib 255
+#define __NR_sync_file_range 255
#define __NR_clock_settime 256
#define __NR_clock_gettime 257
#define __NR_clock_getres 258
@@ -298,7 +298,7 @@
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
-/*#define __NR_sys_setaltroot 280 available (was setaltroot) */
+#define __NR_tee 280
#define __NR_add_key 281
#define __NR_request_key 282
#define __NR_keyctl 283
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index 30656c962d74..6e2528bb0083 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -56,6 +56,9 @@ extern int do_get_thread_area_tt(struct user_desc *info);
extern int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to);
extern int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
+
static inline int do_get_thread_area(struct user_desc *info)
{
return CHOOSE_MODE_PROC(do_get_thread_area_tt, do_get_thread_area_skas, info);
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
index 107decbd6e6c..7091af4b7866 100644
--- a/include/asm-v850/system.h
+++ b/include/asm-v850/system.h
@@ -18,8 +18,6 @@
#include <asm/ptrace.h>
-#define prepare_to_switch() do { } while (0)
-
/*
* switch_to(n) should switch tasks to task ptr, first checking that
* ptr isn't the current task, in which case it does nothing.
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h
index c8043a16152e..f8dff1c67538 100644
--- a/include/asm-x86_64/cache.h
+++ b/include/asm-x86_64/cache.h
@@ -20,8 +20,8 @@
__attribute__((__section__(".data.page_aligned")))
#endif
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
#endif
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
#endif
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 76bb6193ae91..662964b74e34 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -64,6 +64,7 @@
#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 */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 8dcc32665240..93b51df51687 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -47,7 +47,8 @@ extern void contig_e820_setup(void);
extern unsigned long e820_end_of_ram(void);
extern void e820_reserve_resources(void);
extern void e820_print_map(char *who);
-extern int e820_mapped(unsigned long start, unsigned long end, unsigned type);
+extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
+extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
extern void e820_setup_gap(void);
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index 08b75c15269a..18ff7ee9e774 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -51,6 +51,8 @@
#define HPET_TN_ROUTE_SHIFT 9
+#define HPET_TICK_RATE (HZ * 100000UL)
+
extern int is_hpet_enabled(void);
extern int hpet_rtc_timer_init(void);
extern int oem_force_hpet_timer(void);
diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
index 876eb9a2fe78..cba8a3b0cded 100644
--- a/include/asm-x86_64/i387.h
+++ b/include/asm-x86_64/i387.h
@@ -72,6 +72,23 @@ extern int set_fpregs(struct task_struct *tsk,
#define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
#define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
+#define X87_FSW_ES (1 << 7) /* Exception Summary */
+
+/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. The kernel data segment can be sometimes 0 and sometimes
+ new user value. Both should be ok.
+ Use the PDA as safe address because it should be already in L1. */
+static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+{
+ if (unlikely(fx->swd & X87_FSW_ES))
+ asm volatile("fnclex");
+ alternative_input(ASM_NOP8 ASM_NOP2,
+ " emms\n" /* clear stack tags */
+ " fildl %%gs:0", /* load to clear state */
+ X86_FEATURE_FXSAVE_LEAK);
+}
+
static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
{
int err;
@@ -119,6 +136,7 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
#endif
if (unlikely(err))
__clear_user(fx, sizeof(struct i387_fxsave_struct));
+ /* No need to clear here because the caller clears USED_MATH */
return err;
}
@@ -149,7 +167,7 @@ static inline void __fxsave_clear(struct task_struct *tsk)
"i" (offsetof(__typeof__(*tsk),
thread.i387.fxsave)));
#endif
- __asm__ __volatile__("fnclex");
+ clear_fpu_state(&tsk->thread.i387.fxsave);
}
static inline void kernel_fpu_begin(void)
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index eeb2bcd635de..b4f4b172b15a 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -317,6 +317,4 @@
#define __NR_ia32_ppoll 309
#define __NR_ia32_unshare 310
-#define IA32_NR_syscalls 315 /* must be > than biggest syscall! */
-
#endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index cafdfb37f0d8..a05da8a50bfd 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -177,7 +177,7 @@ static inline __u16 __readw(const volatile void __iomem *addr)
{
return *(__force volatile __u16 *)addr;
}
-static inline __u32 __readl(const volatile void __iomem *addr)
+static __always_inline __u32 __readl(const volatile void __iomem *addr)
{
return *(__force volatile __u32 *)addr;
}
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h
index 5d298b799a9f..7229785094e3 100644
--- a/include/asm-x86_64/mce.h
+++ b/include/asm-x86_64/mce.h
@@ -70,6 +70,9 @@ struct mce_log {
#define MCE_THRESHOLD_BASE MCE_EXTENDED_BANK + 1 /* MCE_AMD */
#define MCE_THRESHOLD_DRAM_ECC MCE_THRESHOLD_BASE + 4
+#ifdef __KERNEL__
+#include <asm/atomic.h>
+
void mce_log(struct mce *m);
#ifdef CONFIG_X86_MCE_INTEL
void mce_intel_feature_init(struct cpuinfo_x86 *c);
@@ -87,4 +90,8 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c)
}
#endif
+extern atomic_t mce_entry;
+
+#endif
+
#endif
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 6b18cd8f293d..6944e7122df5 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -12,7 +12,8 @@
#include <asm/smp.h>
-#define NODEMAPSIZE 0xfff
+/* Should really switch to dynamic allocation at some point */
+#define NODEMAPSIZE 0x4fff
/* Simple perfect hash to map physical addresses to node numbers */
struct memnode {
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index f6cbb4cbb5a3..1cc92fe02503 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -2,7 +2,6 @@
#define _ASM_X8664_NUMA_H 1
#include <linux/nodemask.h>
-#include <asm/numnodes.h>
struct bootnode {
u64 start,end;
@@ -18,6 +17,8 @@ extern void numa_init_array(void);
extern int numa_off;
extern void numa_set_node(int cpu, int node);
+extern void srat_reserve_add_area(int nodeid);
+extern int hotadd_percent;
extern unsigned char apicid_to_node[256];
#ifdef CONFIG_NUMA
diff --git a/include/asm-x86_64/numnodes.h b/include/asm-x86_64/numnodes.h
deleted file mode 100644
index 32be16b8ae96..000000000000
--- a/include/asm-x86_64/numnodes.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_X8664_NUMNODES_H
-#define _ASM_X8664_NUMNODES_H 1
-
-#include <linux/config.h>
-
-#ifdef CONFIG_NUMA
-#define NODES_SHIFT 6
-#else
-#define NODES_SHIFT 0
-#endif
-
-#endif
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 4405b4adeaba..7f33aaf9f7b1 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -26,7 +26,7 @@
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
} while (0)
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index f18443fcdf04..b9e5320b7625 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -33,7 +33,7 @@ static __always_inline cycles_t get_cycles_sync(void)
unsigned eax;
/* Don't do an additional sync on CPUs where we know
RDTSC is already synchronous. */
- alternative_io(ASM_NOP2, "cpuid", X86_FEATURE_SYNC_RDTSC,
+ alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
"=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
rdtscll(ret);
return ret;
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index f21ff2c1e960..feb77cb8c044 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -611,8 +611,14 @@ __SYSCALL(__NR_set_robust_list, sys_set_robust_list)
__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
#define __NR_splice 275
__SYSCALL(__NR_splice, sys_splice)
-
-#define __NR_syscall_max __NR_splice
+#define __NR_tee 276
+__SYSCALL(__NR_tee, sys_tee)
+#define __NR_sync_file_range 277
+__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
+#define __NR_vmsplice 278
+__SYSCALL(__NR_vmsplice, sys_vmsplice)
+
+#define __NR_syscall_max __NR_vmsplice
#ifndef __NO_STUBS
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
index 10c443435c11..3b89a772d0a0 100644
--- a/include/asm-xtensa/ioctls.h
+++ b/include/asm-xtensa/ioctls.h
@@ -107,6 +107,6 @@
#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT _IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#endif /* _XTENSA_IOCTLS_H */
diff --git a/include/asm-xtensa/signal.h b/include/asm-xtensa/signal.h
index 5d6fc9cdf58d..a99c9aec64ec 100644
--- a/include/asm-xtensa/signal.h
+++ b/include/asm-xtensa/signal.h
@@ -118,9 +118,9 @@ typedef struct {
* SA_INTERRUPT is also used by the irq handling routines.
* SA_SHIRQ is for shared interrupt support on PCI and EISA.
*/
-#define SA_PROBE SA_ONESHOT
#define SA_SAMPLE_RANDOM SA_RESTART
#define SA_SHIRQ 0x04000000
+#define SA_PROBEIRQ 0x08000000
#endif
#define SIG_BLOCK 0 /* for blocking signals */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
index 9284867f1cb9..b29f7ae6a08a 100644
--- a/include/asm-xtensa/system.h
+++ b/include/asm-xtensa/system.h
@@ -111,8 +111,6 @@ extern void *_switch_to(void *last, void *next);
#endif /* __ASSEMBLY__ */
-#define prepare_to_switch() do { } while(0)
-
#define switch_to(prev,next,last) \
do { \
clear_cpenable(); \
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d0cac8b58de7..59e1259b1c40 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -17,6 +17,8 @@
#include <asm/scatterlist.h>
+struct scsi_ioctl_command;
+
struct request_queue;
typedef struct request_queue request_queue_t;
struct elevator_queue;
@@ -611,6 +613,8 @@ extern void blk_plug_device(request_queue_t *);
extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
+extern int sg_scsi_ioctl(struct file *, struct request_queue *,
+ struct gendisk *, struct scsi_ioctl_command __user *);
extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q);
extern void blk_sync_queue(struct request_queue *q);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index de3eb8d8ae26..da2d107fe2cf 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -45,6 +45,7 @@ extern unsigned long __init bootmem_bootmap_pages (unsigned long);
extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
extern void __init free_bootmem (unsigned long addr, unsigned long size);
extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal);
+extern void * __init __alloc_bootmem_nopanic (unsigned long size, unsigned long align, unsigned long goal);
extern void * __init __alloc_bootmem_low(unsigned long size,
unsigned long align,
unsigned long goal);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 176e2d371577..047567d34ca7 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -58,9 +58,8 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
*/
static inline struct dentry *debugfs_create_file(const char *name, mode_t mode,
- struct dentry *parent,
- void *data,
- struct file_operations *fops)
+ struct dentry *parent, void *data,
+ const struct file_operations *fops)
{
return ERR_PTR(-ENODEV);
}
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9b4751aecc23..ff61817082fa 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -21,7 +21,7 @@ enum dma_data_direction {
#define DMA_30BIT_MASK 0x000000003fffffffULL
#define DMA_29BIT_MASK 0x000000001fffffffULL
#define DMA_28BIT_MASK 0x000000000fffffffULL
-#define DMA_24BIT_MASK 0x0000000000ffffffULL
+#define DMA_24BIT_MASK 0x0000000000ffffffULL
#include <asm/dma-mapping.h>
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4ed7e602d703..3de2bfb2410f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -762,7 +762,7 @@ extern int fcntl_getlease(struct file *filp);
#define SYNC_FILE_RANGE_WRITE 2
#define SYNC_FILE_RANGE_WAIT_AFTER 4
extern int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
- int flags);
+ unsigned int flags);
/* fs/locks.c */
extern void locks_init_lock(struct file_lock *);
@@ -864,7 +864,7 @@ struct super_block {
*/
struct mutex s_vfs_rename_mutex; /* Kludge */
- /* Granuality of c/m/atime in ns.
+ /* Granularity of c/m/atime in ns.
Cannot be worse than a second */
u32 s_time_gran;
};
@@ -1039,8 +1039,8 @@ struct file_operations {
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
- ssize_t (*splice_write)(struct inode *, struct file *, size_t, unsigned int);
- ssize_t (*splice_read)(struct file *, struct inode *, size_t, unsigned int);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
+ ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
};
struct inode_operations {
@@ -1611,8 +1611,17 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor
extern void do_generic_mapping_read(struct address_space *mapping,
struct file_ra_state *, struct file *,
loff_t *, read_descriptor_t *, read_actor_t);
-extern ssize_t generic_file_splice_read(struct file *, struct inode *, size_t, unsigned int);
-extern ssize_t generic_file_splice_write(struct inode *, struct file *, size_t, unsigned int);
+
+/* fs/splice.c */
+extern ssize_t generic_file_splice_read(struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, unsigned int);
+extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
+ struct file *, loff_t *, size_t, unsigned int);
+extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
+ struct file *out, loff_t *, size_t len, unsigned int flags);
+extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+ size_t len, unsigned int flags);
+
extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 10a27f29d692..2ef845b35175 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -105,6 +105,7 @@ struct gendisk {
* disks that can't be partitioned. */
char disk_name[32]; /* name of major driver */
struct hd_struct **part; /* [indexed by minor] */
+ int part_uevent_suppress;
struct block_device_operations *fops;
struct request_queue *queue;
void *private_data;
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 7851e6b520cf..3ac452945a7d 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -57,6 +57,8 @@ struct vm_area_struct;
__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
__GFP_NOMEMALLOC|__GFP_HARDWALL)
+/* This equals 0, but use constants in case they ever change */
+#define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH)
/* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */
#define GFP_ATOMIC (__GFP_HIGH)
#define GFP_NOIO (__GFP_WAIT)
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index b20939287613..306acf1dc6d5 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -80,7 +80,7 @@ struct hrtimer_sleeper {
* @first: pointer to the timer node which expires first
* @resolution: the resolution of the clock, in nanoseconds
* @get_time: function to retrieve the current time of the clock
- * @get_sofirq_time: function to retrieve the current time from the softirq
+ * @get_softirq_time: function to retrieve the current time from the softirq
* @curr_timer: the timer which is executing a callback right now
* @softirq_time: the time when running the hrtimer queue in the softirq
*/
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 8d2db412ba9c..a8bef1d1371c 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1220,7 +1220,6 @@ typedef struct ide_pci_enablebit_s {
enum {
/* Uses ISA control ports not PCI ones. */
IDEPCI_FLAG_ISA_PORTS = (1 << 0),
- IDEPCI_FLAG_FORCE_PDC = (1 << 1),
};
typedef struct ide_pci_device_s {
diff --git a/include/linux/init.h b/include/linux/init.h
index ed0ac7c39fdc..93dcbe1abb4c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -245,7 +245,8 @@ void __init parse_early_param(void);
#define __cpuexitdata __exitdata
#endif
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+ || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
#define __meminit
#define __meminitdata
#define __memexit
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 99905e180532..043376920f51 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -36,6 +36,8 @@
/* LATCH is used in the interval timer and ftape setup. */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+#define LATCH_HPET ((HPET_TICK_RATE + HZ/2) / HZ)
+
/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can
* improve accuracy by shifting LSH bits, hence calculating:
* (NOM << LSH) / DEN
@@ -51,9 +53,13 @@
/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */
#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8))
+#define ACTHZ_HPET (SH_DIV (HPET_TICK_RATE, LATCH_HPET, 8))
+
/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */
#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8))
+#define TICK_NSEC_HPET (SH_DIV(1000000UL * 1000, ACTHZ_HPET, 8))
+
/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index a3720f973ea5..e1bd0842f6a1 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -176,7 +176,7 @@ static inline void console_verbose(void)
extern void bust_spinlocks(int yes);
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
-extern __deprecated_for_modules int panic_timeout;
+extern int panic_timeout;
extern int panic_on_oops;
extern int tainted;
extern const char *print_tainted(void);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 4cb1214ec290..c187c53cecd0 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -24,6 +24,7 @@
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <linux/kernel.h>
+#include <linux/wait.h>
#include <asm/atomic.h>
#define KOBJ_NAME_LEN 20
@@ -56,6 +57,7 @@ struct kobject {
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry;
+ wait_queue_head_t poll;
};
extern int kobject_set_name(struct kobject *, const char *, ...)
@@ -255,9 +257,8 @@ struct subsys_attribute {
};
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
-extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
-#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG)
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 4617e75903b0..dc23c7c639f3 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -19,39 +19,38 @@ struct class_device;
*/
enum led_brightness {
- LED_OFF = 0,
- LED_HALF = 127,
- LED_FULL = 255,
+ LED_OFF = 0,
+ LED_HALF = 127,
+ LED_FULL = 255,
};
struct led_classdev {
- const char *name;
- int brightness;
- int flags;
-#define LED_SUSPENDED (1 << 0)
+ const char *name;
+ int brightness;
+ int flags;
- /* A function to set the brightness of the led */
- void (*brightness_set)(struct led_classdev *led_cdev,
- enum led_brightness brightness);
+#define LED_SUSPENDED (1 << 0)
- struct class_device *class_dev;
- /* LED Device linked list */
- struct list_head node;
+ /* Set LED brightness level */
+ void (*brightness_set)(struct led_classdev *led_cdev,
+ enum led_brightness brightness);
+
+ struct class_device *class_dev;
+ struct list_head node; /* LED Device list */
+ char *default_trigger; /* Trigger to use */
- /* Trigger data */
- char *default_trigger;
#ifdef CONFIG_LEDS_TRIGGERS
- rwlock_t trigger_lock;
/* Protects the trigger data below */
+ rwlock_t trigger_lock;
- struct led_trigger *trigger;
- struct list_head trig_list;
- void *trigger_data;
+ struct led_trigger *trigger;
+ struct list_head trig_list;
+ void *trigger_data;
#endif
};
extern int led_classdev_register(struct device *parent,
- struct led_classdev *led_cdev);
+ struct led_classdev *led_cdev);
extern void led_classdev_unregister(struct led_classdev *led_cdev);
extern void led_classdev_suspend(struct led_classdev *led_cdev);
extern void led_classdev_resume(struct led_classdev *led_cdev);
@@ -65,16 +64,16 @@ extern void led_classdev_resume(struct led_classdev *led_cdev);
struct led_trigger {
/* Trigger Properties */
- const char *name;
- void (*activate)(struct led_classdev *led_cdev);
- void (*deactivate)(struct led_classdev *led_cdev);
+ const char *name;
+ void (*activate)(struct led_classdev *led_cdev);
+ void (*deactivate)(struct led_classdev *led_cdev);
/* LEDs under control by this trigger (for simple triggers) */
- rwlock_t leddev_list_lock;
- struct list_head led_cdevs;
+ rwlock_t leddev_list_lock;
+ struct list_head led_cdevs;
/* Link to next registered trigger */
- struct list_head next_trig;
+ struct list_head next_trig;
};
/* Registration functions for complex triggers */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0d61357604d5..b80d2e7fa6d2 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -523,7 +523,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(struct scsi_host_template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
-extern int ata_scsi_error(struct Scsi_Host *host);
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
extern int ata_scsi_release(struct Scsi_Host *host);
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 968b1aa3732c..911206386171 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -58,8 +58,6 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
/* need some defines for these for archs that don't support it */
extern void online_page(struct page *page);
/* VM interface that may be used by firmware interface */
-extern int add_memory(u64 start, u64 size);
-extern int remove_memory(u64 start, u64 size);
extern int online_pages(unsigned long, unsigned long);
/* reasonably generic interface to expand the physical pages in a zone */
@@ -92,11 +90,6 @@ static inline int mhp_notimplemented(const char *func)
return -ENOSYS;
}
-static inline int __add_pages(struct zone *zone, unsigned long start_pfn,
- unsigned long nr_pages)
-{
- return mhp_notimplemented(__FUNCTION__);
-}
#endif /* ! CONFIG_MEMORY_HOTPLUG */
static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
unsigned long nr_pages)
@@ -105,4 +98,8 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
dump_stack();
return -ENOSYS;
}
+
+extern int add_memory(u64 start, u64 size);
+extern int remove_memory(u64 start, u64 size);
+
#endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6aa016f1d3ae..1154684209a4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -229,10 +229,9 @@ struct page {
unsigned long private; /* Mapping-private opaque data:
* usually used for buffer_heads
* if PagePrivate set; used for
- * swp_entry_t if PageSwapCache.
- * When page is free, this
+ * swp_entry_t if PageSwapCache;
* indicates order in the buddy
- * system.
+ * system if PG_buddy is set.
*/
struct address_space *mapping; /* If low bit clear, points to
* inode address_space, or NULL.
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index 955d3069d727..edfa012fad3a 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,7 +13,7 @@
#ifndef __ASM_MV643XX_H
#define __ASM_MV643XX_H
-#ifdef __MIPS__
+#ifdef __mips__
#include <asm/addrspace.h>
#include <asm/marvell.h>
#endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 40ccf8cc4239..01db7b88a2b1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -829,19 +829,21 @@ static inline void netif_rx_schedule(struct net_device *dev)
__netif_rx_schedule(dev);
}
-/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete().
- * Do not inline this?
- */
+
+static inline void __netif_rx_reschedule(struct net_device *dev, int undo)
+{
+ dev->quota += undo;
+ list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
+ __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+}
+
+/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */
static inline int netif_rx_reschedule(struct net_device *dev, int undo)
{
if (netif_rx_schedule_prep(dev)) {
unsigned long flags;
-
- dev->quota += undo;
-
local_irq_save(flags);
- list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
- __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+ __netif_rx_reschedule(dev, undo);
local_irq_restore(flags);
return 1;
}
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 412e52ca9720..b31a9bca9361 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -110,6 +110,8 @@ struct nf_info
/* Function to register/unregister hook points. */
int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
+int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
+void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
/* Functions to register get/setsockopt ranges (non-inclusive). You
need to check permissions yourself! */
@@ -281,16 +283,42 @@ extern void nf_invalidate_cache(int pf);
Returns true or false. */
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
-struct nf_queue_rerouter {
- void (*save)(const struct sk_buff *skb, struct nf_info *info);
- int (*reroute)(struct sk_buff **skb, const struct nf_info *info);
- int rer_size;
+struct nf_afinfo {
+ unsigned short family;
+ unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
+ void (*saveroute)(const struct sk_buff *skb,
+ struct nf_info *info);
+ int (*reroute)(struct sk_buff **skb,
+ const struct nf_info *info);
+ int route_key_size;
};
-#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
+extern struct nf_afinfo *nf_afinfo[];
+static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
+{
+ return rcu_dereference(nf_afinfo[family]);
+}
+
+static inline unsigned int
+nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
+ u_int8_t protocol, unsigned short family)
+{
+ struct nf_afinfo *afinfo;
+ unsigned int csum = 0;
+
+ rcu_read_lock();
+ afinfo = nf_get_afinfo(family);
+ if (afinfo)
+ csum = afinfo->checksum(skb, hook, dataoff, protocol);
+ rcu_read_unlock();
+ return csum;
+}
-extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
-extern int nf_unregister_queue_rerouter(int pf);
+extern int nf_register_afinfo(struct nf_afinfo *afinfo);
+extern void nf_unregister_afinfo(struct nf_afinfo *afinfo);
+
+#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
#include <net/flow.h>
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 1350e47b0234..38701454e197 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -142,6 +142,12 @@ struct xt_counters_info
#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h>
+#ifdef CONFIG_COMPAT
+#define COMPAT_TO_USER 1
+#define COMPAT_FROM_USER -1
+#define COMPAT_CALC_SIZE 0
+#endif
+
struct xt_match
{
struct list_head list;
@@ -175,6 +181,9 @@ struct xt_match
void (*destroy)(const struct xt_match *match, void *matchinfo,
unsigned int matchinfosize);
+ /* Called when userspace align differs from kernel space one */
+ int (*compat)(void *match, void **dstptr, int *size, int convert);
+
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
@@ -220,6 +229,9 @@ struct xt_target
void (*destroy)(const struct xt_target *target, void *targinfo,
unsigned int targinfosize);
+ /* Called when userspace align differs from kernel space one */
+ int (*compat)(void *target, void **dstptr, int *size, int convert);
+
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
@@ -314,6 +326,65 @@ extern void xt_proto_fini(int af);
extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
extern void xt_free_table_info(struct xt_table_info *info);
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_xt_entry_match
+{
+ union {
+ struct {
+ u_int16_t match_size;
+ char name[XT_FUNCTION_MAXNAMELEN - 1];
+ u_int8_t revision;
+ } user;
+ u_int16_t match_size;
+ } u;
+ unsigned char data[0];
+};
+
+struct compat_xt_entry_target
+{
+ union {
+ struct {
+ u_int16_t target_size;
+ char name[XT_FUNCTION_MAXNAMELEN - 1];
+ u_int8_t revision;
+ } user;
+ u_int16_t target_size;
+ } u;
+ unsigned char data[0];
+};
+
+/* FIXME: this works only on 32 bit tasks
+ * need to change whole approach in order to calculate align as function of
+ * current task alignment */
+
+struct compat_xt_counters
+{
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+ u_int32_t cnt[4];
+#else
+ u_int64_t cnt[2];
+#endif
+};
+
+struct compat_xt_counters_info
+{
+ char name[XT_TABLE_MAXNAMELEN];
+ compat_uint_t num_counters;
+ struct compat_xt_counters counters[0];
+};
+
+#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \
+ & ~(__alignof__(struct compat_xt_counters)-1))
+
+extern void xt_compat_lock(int af);
+extern void xt_compat_unlock(int af);
+extern int xt_compat_match(void *match, void **dstptr, int *size, int convert);
+extern int xt_compat_target(void *target, void **dstptr, int *size,
+ int convert);
+
+#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_esp.h b/include/linux/netfilter/xt_esp.h
new file mode 100644
index 000000000000..9380fb1c27da
--- /dev/null
+++ b/include/linux/netfilter/xt_esp.h
@@ -0,0 +1,14 @@
+#ifndef _XT_ESP_H
+#define _XT_ESP_H
+
+struct xt_esp
+{
+ u_int32_t spis[2]; /* Security Parameter Index */
+ u_int8_t invflags; /* Inverse flags */
+};
+
+/* Values for "invflags" field in struct xt_esp. */
+#define XT_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
+#define XT_ESP_INV_MASK 0x01 /* All possible flags. */
+
+#endif /*_XT_ESP_H*/
diff --git a/include/linux/netfilter/xt_multiport.h b/include/linux/netfilter/xt_multiport.h
new file mode 100644
index 000000000000..d49ee4183710
--- /dev/null
+++ b/include/linux/netfilter/xt_multiport.h
@@ -0,0 +1,30 @@
+#ifndef _XT_MULTIPORT_H
+#define _XT_MULTIPORT_H
+
+enum xt_multiport_flags
+{
+ XT_MULTIPORT_SOURCE,
+ XT_MULTIPORT_DESTINATION,
+ XT_MULTIPORT_EITHER
+};
+
+#define XT_MULTI_PORTS 15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct xt_multiport
+{
+ u_int8_t flags; /* Type of comparison */
+ u_int8_t count; /* Number of ports */
+ u_int16_t ports[XT_MULTI_PORTS]; /* Ports */
+};
+
+struct xt_multiport_v1
+{
+ u_int8_t flags; /* Type of comparison */
+ u_int8_t count; /* Number of ports */
+ u_int16_t ports[XT_MULTI_PORTS]; /* Ports */
+ u_int8_t pflags[XT_MULTI_PORTS]; /* Port flags */
+ u_int8_t invert; /* Invert flag */
+};
+
+#endif /*_XT_MULTIPORT_H*/
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 43c09d790b83..85301c5e8d24 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -80,6 +80,8 @@ enum nf_ip_hook_priorities {
#ifdef __KERNEL__
extern int ip_route_me_harder(struct sk_buff **pskb);
extern int ip_xfrm_me_harder(struct sk_buff **pskb);
+extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
#endif /*__KERNEL__*/
#endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 0987cea53840..eace86bd2adb 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -3,6 +3,8 @@
#ifdef __KERNEL__
+#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
+
#define RAS_PORT 1719
#define Q931_PORT 1720
#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
@@ -25,6 +27,56 @@ struct ip_ct_h323_master {
};
};
+struct ip_conntrack_expect;
+
+extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port);
+extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int16_t port, u_int16_t rtp_port,
+ struct ip_conntrack_expect * rtp_exp,
+ struct ip_conntrack_expect * rtcp_exp);
+extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress * addr,
+ int idx, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+
#endif
#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
index 0bd828081c0c..0bd828081c0c 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
index cc98f7aa5abe..cc98f7aa5abe 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index d5b8c0d6a12b..c0dac16e1902 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -316,5 +316,23 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
void *userdata);
#define IPT_ALIGN(s) XT_ALIGN(s)
+
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_ipt_entry
+{
+ struct ipt_ip ip;
+ compat_uint_t nfcache;
+ u_int16_t target_offset;
+ u_int16_t next_offset;
+ compat_uint_t comefrom;
+ struct compat_xt_counters counters;
+ unsigned char elems[0];
+};
+
+#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
+
+#endif /* CONFIG_COMPAT */
#endif /*__KERNEL__*/
#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ipt_esp.h b/include/linux/netfilter_ipv4/ipt_esp.h
index c782a83e53e0..78296e7eeff9 100644
--- a/include/linux/netfilter_ipv4/ipt_esp.h
+++ b/include/linux/netfilter_ipv4/ipt_esp.h
@@ -1,16 +1,10 @@
#ifndef _IPT_ESP_H
#define _IPT_ESP_H
-struct ipt_esp
-{
- u_int32_t spis[2]; /* Security Parameter Index */
- u_int8_t invflags; /* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
-
-
-/* Values for "invflags" field in struct ipt_esp. */
-#define IPT_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
-#define IPT_ESP_INV_MASK 0x01 /* All possible flags. */
+#define ipt_esp xt_esp
+#define IPT_ESP_INV_SPI XT_ESP_INV_SPI
+#define IPT_ESP_INV_MASK XT_ESP_INV_MASK
#endif /*_IPT_ESP_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_multiport.h b/include/linux/netfilter_ipv4/ipt_multiport.h
index e6b6fff811df..55fe85eca88c 100644
--- a/include/linux/netfilter_ipv4/ipt_multiport.h
+++ b/include/linux/netfilter_ipv4/ipt_multiport.h
@@ -1,30 +1,15 @@
#ifndef _IPT_MULTIPORT_H
#define _IPT_MULTIPORT_H
-#include <linux/netfilter_ipv4/ip_tables.h>
-enum ipt_multiport_flags
-{
- IPT_MULTIPORT_SOURCE,
- IPT_MULTIPORT_DESTINATION,
- IPT_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
-#define IPT_MULTI_PORTS 15
+#define IPT_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE
+#define IPT_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION
+#define IPT_MULTIPORT_EITHER XT_MULTIPORT_EITHER
-/* Must fit inside union ipt_matchinfo: 16 bytes */
-struct ipt_multiport
-{
- u_int8_t flags; /* Type of comparison */
- u_int8_t count; /* Number of ports */
- u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
-};
+#define IPT_MULTI_PORTS XT_MULTI_PORTS
+
+#define ipt_multiport xt_multiport
+#define ipt_multiport_v1 xt_multiport_v1
-struct ipt_multiport_v1
-{
- u_int8_t flags; /* Type of comparison */
- u_int8_t count; /* Number of ports */
- u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
- u_int8_t pflags[IPT_MULTI_PORTS]; /* Port flags */
- u_int8_t invert; /* Invert flag */
-};
#endif /*_IPT_MULTIPORT_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 14f2bd010884..52a7b9e76428 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities {
};
#ifdef CONFIG_NETFILTER
+extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
+
extern int ipv6_netfilter_init(void);
extern void ipv6_netfilter_fini(void);
#else /* CONFIG_NETFILTER */
diff --git a/include/linux/netfilter_ipv6/ip6t_esp.h b/include/linux/netfilter_ipv6/ip6t_esp.h
index a91b6abc8079..f62eaf53c16c 100644
--- a/include/linux/netfilter_ipv6/ip6t_esp.h
+++ b/include/linux/netfilter_ipv6/ip6t_esp.h
@@ -1,14 +1,10 @@
#ifndef _IP6T_ESP_H
#define _IP6T_ESP_H
-struct ip6t_esp
-{
- u_int32_t spis[2]; /* Security Parameter Index */
- u_int8_t invflags; /* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
-/* Values for "invflags" field in struct ip6t_esp. */
-#define IP6T_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
-#define IP6T_ESP_INV_MASK 0x01 /* All possible flags. */
+#define ip6t_esp xt_esp
+#define IP6T_ESP_INV_SPI XT_ESP_INV_SPI
+#define IP6T_ESP_INV_MASK XT_ESP_INV_MASK
#endif /*_IP6T_ESP_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_multiport.h b/include/linux/netfilter_ipv6/ip6t_multiport.h
index efe4954a8681..042c92661cee 100644
--- a/include/linux/netfilter_ipv6/ip6t_multiport.h
+++ b/include/linux/netfilter_ipv6/ip6t_multiport.h
@@ -1,21 +1,14 @@
#ifndef _IP6T_MULTIPORT_H
#define _IP6T_MULTIPORT_H
-#include <linux/netfilter_ipv6/ip6_tables.h>
-enum ip6t_multiport_flags
-{
- IP6T_MULTIPORT_SOURCE,
- IP6T_MULTIPORT_DESTINATION,
- IP6T_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
-#define IP6T_MULTI_PORTS 15
+#define IP6T_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE
+#define IP6T_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION
+#define IP6T_MULTIPORT_EITHER XT_MULTIPORT_EITHER
-/* Must fit inside union ip6t_matchinfo: 16 bytes */
-struct ip6t_multiport
-{
- u_int8_t flags; /* Type of comparison */
- u_int8_t count; /* Number of ports */
- u_int16_t ports[IP6T_MULTI_PORTS]; /* Ports */
-};
-#endif /*_IPT_MULTIPORT_H*/
+#define IP6T_MULTI_PORTS XT_MULTI_PORTS
+
+#define ip6t_multiport xt_multiport
+
+#endif /*_IP6T_MULTIPORT_H*/
diff --git a/include/linux/numa.h b/include/linux/numa.h
index f0c539bd3cfc..e481feb1bfd8 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -3,11 +3,9 @@
#include <linux/config.h>
-#ifndef CONFIG_FLATMEM
-#include <asm/numnodes.h>
-#endif
-
-#ifndef NODES_SHIFT
+#ifdef CONFIG_NODES_SHIFT
+#define NODES_SHIFT CONFIG_NODES_SHIFT
+#else
#define NODES_SHIFT 0
#endif
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 9ea629c02a4b..d276a4e2f825 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -48,8 +48,20 @@
/*
* Don't use the *_dontuse flags. Use the macros. Otherwise you'll break
- * locked- and dirty-page accounting. The top eight bits of page->flags are
- * used for page->zone, so putting flag bits there doesn't work.
+ * locked- and dirty-page accounting.
+ *
+ * The page flags field is split into two parts, the main flags area
+ * which extends from the low bits upwards, and the fields area which
+ * extends from the high bits downwards.
+ *
+ * | FIELD | ... | FLAGS |
+ * N-1 ^ 0
+ * (N-FLAGS_RESERVED)
+ *
+ * The fields area is reserved for fields mapping zone, node and SPARSEMEM
+ * section. The boundry between these two areas is defined by
+ * FLAGS_RESERVED which defines the width of the fields section
+ * (see linux/mmzone.h). New flags must _not_ overlap with this area.
*/
#define PG_locked 0 /* Page is locked. Don't touch. */
#define PG_error 1
@@ -74,7 +86,9 @@
#define PG_mappedtodisk 16 /* Has blocks allocated on-disk */
#define PG_reclaim 17 /* To be reclaimed asap */
#define PG_nosave_free 18 /* Free, should not be written */
-#define PG_uncached 19 /* Page has been mapped as uncached */
+#define PG_buddy 19 /* Page is free, on buddy lists */
+
+#define PG_uncached 20 /* Page has been mapped as uncached */
/*
* Global page accounting. One instance per CPU. Only unsigned longs are
@@ -317,6 +331,10 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta);
#define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags)
#define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags)
+#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags)
+#define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags)
+#define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags)
+
#define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags)
#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 9539efd4f7e6..7a1af574dedf 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -78,6 +78,8 @@ extern struct page * find_or_create_page(struct address_space *mapping,
unsigned long index, gfp_t gfp_mask);
unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
unsigned int nr_pages, struct page **pages);
+unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
+ unsigned int nr_pages, struct page **pages);
unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
int tag, unsigned int nr_pages, struct page **pages);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0aad5a378e95..3a6a4e37a482 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -97,7 +97,13 @@ enum pci_channel_state {
typedef unsigned short __bitwise pci_bus_flags_t;
enum pci_bus_flags {
- PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1,
+ PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+};
+
+struct pci_cap_saved_state {
+ struct hlist_node next;
+ char cap_nr;
+ u32 data[0];
};
/*
@@ -159,6 +165,7 @@ struct pci_dev {
unsigned int block_ucfg_access:1; /* userspace config space access is blocked */
u32 saved_config_space[16]; /* config space saved at suspend time */
+ struct hlist_head saved_cap_space;
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
int rom_attr_enabled; /* has display of the rom attribute been enabled? */
struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
@@ -169,6 +176,30 @@ struct pci_dev {
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+static inline struct pci_cap_saved_state *pci_find_saved_cap(
+ struct pci_dev *pci_dev,char cap)
+{
+ struct pci_cap_saved_state *tmp;
+ struct hlist_node *pos;
+
+ hlist_for_each_entry(tmp, pos, &pci_dev->saved_cap_space, next) {
+ if (tmp->cap_nr == cap)
+ return tmp;
+ }
+ return NULL;
+}
+
+static inline void pci_add_saved_cap(struct pci_dev *pci_dev,
+ struct pci_cap_saved_state *new_cap)
+{
+ hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
+}
+
+static inline void pci_remove_saved_cap(struct pci_cap_saved_state *cap)
+{
+ hlist_del(&cap->next);
+}
+
/*
* For PCI devices, the region numbers are assigned this way:
*
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 870fe38378b1..d6fe048376ab 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -356,6 +356,10 @@
#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e
#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376
#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379
+#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a
+#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380
+#define PCI_DEVICE_ID_ATI_IXP600_SRAID 0x4381
+#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c
#define PCI_VENDOR_ID_VLSI 0x1004
#define PCI_DEVICE_ID_VLSI_82C592 0x0005
@@ -497,7 +501,8 @@
#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b
#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d
#define PCI_DEVICE_ID_AMD_8151_0 0x7454
-#define PCI_DEVICE_ID_AMD_8131_APIC 0x7450
+#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450
+#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451
#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090
#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091
#define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 75c7f55023ab..0008d4bd4059 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -5,11 +5,14 @@
#define PIPE_BUFFERS (16)
+#define PIPE_BUF_FLAG_STOLEN 0x01
+#define PIPE_BUF_FLAG_LRU 0x02
+
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
struct pipe_buf_operations *ops;
- unsigned int stolen;
+ unsigned int flags;
};
struct pipe_buf_operations {
@@ -18,6 +21,7 @@ struct pipe_buf_operations {
void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *);
void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
+ void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
struct pipe_inode_info {
@@ -33,32 +37,45 @@ struct pipe_inode_info {
unsigned int w_counter;
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
+ struct inode *inode;
};
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
#define PIPE_SIZE PAGE_SIZE
-#define PIPE_MUTEX(inode) (&(inode).i_mutex)
-#define PIPE_WAIT(inode) (&(inode).i_pipe->wait)
-#define PIPE_READERS(inode) ((inode).i_pipe->readers)
-#define PIPE_WRITERS(inode) ((inode).i_pipe->writers)
-#define PIPE_WAITING_WRITERS(inode) ((inode).i_pipe->waiting_writers)
-#define PIPE_RCOUNTER(inode) ((inode).i_pipe->r_counter)
-#define PIPE_WCOUNTER(inode) ((inode).i_pipe->w_counter)
-#define PIPE_FASYNC_READERS(inode) (&((inode).i_pipe->fasync_readers))
-#define PIPE_FASYNC_WRITERS(inode) (&((inode).i_pipe->fasync_writers))
-
/* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct inode * inode);
+void pipe_wait(struct pipe_inode_info *pipe);
-struct inode* pipe_new(struct inode* inode);
-void free_pipe_info(struct inode* inode);
+struct pipe_inode_info * alloc_pipe_info(struct inode * inode);
+void free_pipe_info(struct inode * inode);
+void __free_pipe_info(struct pipe_inode_info *);
/*
* 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 */
+
+/*
+ * 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 *);
#endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 6df2585c0169..66be58902b17 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state);
extern int dpm_runtime_suspend(struct device *, pm_message_t);
extern void dpm_runtime_resume(struct device *);
+extern void __suspend_report_result(const char *function, void *fn, int ret);
+
+#define suspend_report_result(fn, ret) \
+ do { \
+ __suspend_report_result(__FUNCTION__, fn, ret); \
+ } while (0)
#else /* !CONFIG_PM */
@@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev)
{
}
+#define suspend_report_result(fn, ret) do { } while (0)
+
#endif
/* changes to device_may_wakeup take effect on the next pm state change.
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h
index 1252b45face1..008932d73c35 100644
--- a/include/linux/pm_legacy.h
+++ b/include/linux/pm_legacy.h
@@ -16,11 +16,6 @@ struct pm_dev __deprecated *
pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
/*
- * Unregister a device with power management
- */
-void __deprecated pm_unregister(struct pm_dev *dev);
-
-/*
* Unregister all devices with matching callback
*/
void __deprecated pm_unregister_all(pm_callback callback);
@@ -41,8 +36,6 @@ static inline struct pm_dev *pm_register(pm_dev_t type,
return NULL;
}
-static inline void pm_unregister(struct pm_dev *dev) {}
-
static inline void pm_unregister_all(pm_callback callback) {}
static inline int pm_send_all(pm_request_t rqst, void *data)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 135871df9911..4b47a0253425 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -79,7 +79,7 @@ struct kcore_list {
struct vmcore {
struct list_head list;
unsigned long long paddr;
- unsigned long size;
+ unsigned long long size;
loff_t offset;
};
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 774e1acfb8c4..f1fbae7e390e 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -227,8 +227,8 @@ struct mdp_superblock_1 {
*/
/* These are only valid with feature bit '4' */
- __u64 reshape_position; /* next address in array-space for reshape */
__u32 new_level; /* new level we are reshaping to */
+ __u64 reshape_position; /* next address in array-space for reshape */
__u32 delta_disks; /* change in number of raid_disks */
__u32 new_layout; /* new layout */
__u32 new_chunk; /* new chunk size (bytes) */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 541f4828f5e7..29b7d4f87d20 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -684,6 +684,7 @@ static inline void prefetch_stack(struct task_struct *t) { }
struct audit_context; /* See audit.c */
struct mempolicy;
+struct pipe_inode_info;
enum sleep_type {
SLEEP_NORMAL,
@@ -882,6 +883,11 @@ struct task_struct {
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
+
+ /*
+ * cache last used pipe for splice
+ */
+ struct pipe_inode_info *splice_pipe;
};
static inline pid_t process_group(struct task_struct *tsk)
@@ -905,7 +911,6 @@ static inline int pid_alive(struct task_struct *p)
extern void free_task(struct task_struct *tsk);
#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
-extern void __put_task_struct_cb(struct rcu_head *rhp);
extern void __put_task_struct(struct task_struct *t);
static inline void put_task_struct(struct task_struct *t)
@@ -1187,8 +1192,7 @@ extern void wait_task_inactive(task_t * p);
#define remove_parent(p) list_del_init(&(p)->sibling)
#define add_parent(p) list_add_tail(&(p)->sibling,&(p)->parent->children)
-#define next_task(p) list_entry((p)->tasks.next, struct task_struct, tasks)
-#define prev_task(p) list_entry((p)->tasks.prev, struct task_struct, tasks)
+#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
@@ -1203,9 +1207,10 @@ extern void wait_task_inactive(task_t * p);
#define while_each_thread(g, t) \
while ((t = next_thread(t)) != g)
-#define thread_group_leader(p) (p->pid == p->tgid)
+/* de_thread depends on thread_group_leader not being a pid based check */
+#define thread_group_leader(p) (p == p->group_leader)
-static inline task_t *next_thread(task_t *p)
+static inline task_t *next_thread(const task_t *p)
{
return list_entry(rcu_dereference(p->thread_group.next),
task_t, thread_group);
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 6336987dae62..2925e66a6732 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -41,7 +41,8 @@ struct screen_info {
u16 vesapm_off; /* 0x30 */
u16 pages; /* 0x32 */
u16 vesa_attributes; /* 0x34 */
- /* 0x36 -- 0x3f reserved for future expansion */
+ u32 capabilities; /* 0x36 */
+ /* 0x3a -- 0x3f reserved for future expansion */
};
extern struct screen_info screen_info;
diff --git a/include/linux/sdla_asy.h b/include/linux/sdla_asy.h
deleted file mode 100644
index f62242537c86..000000000000
--- a/include/linux/sdla_asy.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*****************************************************************************
-* sdla_asy.h Header file for the Sangoma S508/S514 asynchronous code API
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 2000 Sangoma Technologies 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.
-* ============================================================================
-*
-* Jan 28, 2000 Gideon Hack Initial Version
-*
-*****************************************************************************/
-
-
-#ifndef _WANPIPE_ASYNC_H
-#define _WANPIPE_ASYNC_H
-
-/* ----------------------------------------------------------------------------
- * Interface commands
- * --------------------------------------------------------------------------*/
-
-#define SET_ASY_CONFIGURATION 0xE2 /* set the asychronous operational configuration */
-#define READ_ASY_CONFIGURATION 0xE3 /* read the current asychronous operational configuration */
-#define ENABLE_ASY_COMMUNICATIONS 0xE4 /* enable asychronous communications */
-#define DISABLE_ASY_COMMUNICATIONS 0xE5 /* disable asychronous communications */
-#define READ_ASY_OPERATIONAL_STATS 0xE7 /* retrieve the asychronous operational statistics */
-#define FLUSH_ASY_OPERATIONAL_STATS 0xE8 /* flush the asychronous operational statistics */
-#define TRANSMIT_ASY_BREAK_SIGNAL 0xEC /* transmit an asychronous break signal */
-
-
-
-/* ----------------------------------------------------------------------------
- * Return codes from interface commands
- * --------------------------------------------------------------------------*/
-
-#define COMMAND_INVALID_FOR_PORT 0x50 /* the command is invalid for the selected port */
-#define DISABLE_ASY_COMMS_BEFORE_CFG 0xE1 /* communications must be disabled before setting the configuration */
-#define ASY_COMMS_ENABLED 0xE1 /* communications are currently enabled */
-#define ASY_COMMS_DISABLED 0xE1 /* communications are currently disabled */
-#define ASY_CFG_BEFORE_COMMS_ENABLED 0xE2 /* perform a SET_ASY_CONFIGURATION before enabling comms */
-#define LGTH_ASY_CFG_DATA_INVALID 0xE2 /* the length of the passed configuration data is invalid */
-#define INVALID_ASY_CFG_DATA 0xE3 /* the passed configuration data is invalid */
-#define ASY_BREAK_SIGNAL_BUSY 0xEC /* a break signal is being transmitted */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_ASY_CONFIGURATION/READ_ASY_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the asynchronous configuration structure */
-typedef struct {
- unsigned long baud_rate PACKED; /* the baud rate */
- unsigned short line_config_options PACKED; /* line configuration options */
- unsigned short modem_config_options PACKED; /* modem configuration options */
- unsigned short asy_API_options PACKED; /* asynchronous API options */
- unsigned short asy_protocol_options PACKED; /* asynchronous protocol options */
- unsigned short Tx_bits_per_char PACKED; /* number of bits per tx character */
- unsigned short Rx_bits_per_char PACKED; /* number of bits per received character */
- unsigned short stop_bits PACKED; /* number of stop bits per character */
- unsigned short parity PACKED; /* parity definition */
- unsigned short break_timer PACKED; /* the break signal timer */
- unsigned short asy_Rx_inter_char_timer PACKED; /* the receive inter-character timer */
- unsigned short asy_Rx_complete_length PACKED; /* the receive 'buffer complete' length */
- unsigned short XON_char PACKED; /* the XON character */
- unsigned short XOFF_char PACKED; /* the XOFF character */
- unsigned short asy_statistics_options PACKED; /* async operational stat options */
- unsigned long ptr_shared_mem_info_struct PACKED;/* ptr to the shared memory area information structure */
- unsigned long ptr_asy_Tx_stat_el_cfg_struct PACKED;/* ptr to the transmit status element configuration structure */
- unsigned long ptr_asy_Rx_stat_el_cfg_struct PACKED;/* ptr to the receive status element configuration structure */
-} ASY_CONFIGURATION_STRUCT;
-
-/* permitted minimum and maximum values for setting the asynchronous configuration */
-#define MIN_ASY_BAUD_RATE 50 /* maximum baud rate */
-#define MAX_ASY_BAUD_RATE 250000 /* minimum baud rate */
-#define MIN_ASY_BITS_PER_CHAR 5 /* minimum number of bits per character */
-#define MAX_ASY_BITS_PER_CHAR 8 /* maximum number of bits per character */
-#define MIN_BREAK_TMR_VAL 0 /* minimum break signal timer */
-#define MAX_BREAK_TMR_VAL 5000 /* maximum break signal timer */
-#define MIN_ASY_RX_INTER_CHAR_TMR 0 /* minimum receive inter-character timer */
-#define MAX_ASY_RX_INTER_CHAR_TMR 30000 /* maximum receive inter-character timer */
-#define MIN_ASY_RX_CPLT_LENGTH 0 /* minimum receive 'length complete' value */
-#define MAX_ASY_RX_CPLT_LENGTH 2000 /* maximum receive 'length complete' value */
-
-/* bit settings for the 'asy_API_options' */
-#define ASY_RX_DATA_TRANSPARENT 0x0001 /* do not strip parity and unused bits from received characters */
-
-/* bit settings for the 'asy_protocol_options' */
-#define ASY_RTS_HS_FOR_RX 0x0001 /* RTS handshaking is used for reception control */
-#define ASY_XON_XOFF_HS_FOR_RX 0x0002 /* XON/XOFF handshaking is used for reception control */
-#define ASY_XON_XOFF_HS_FOR_TX 0x0004 /* XON/XOFF handshaking is used for transmission control */
-#define ASY_DCD_HS_FOR_TX 0x0008 /* DCD handshaking is used for transmission control */
-#define ASY_CTS_HS_FOR_TX 0x0020 /* CTS handshaking is used for transmission control */
-
-/* bit settings for the 'stop_bits' definition */
-#define ONE_STOP_BIT 1 /* representation for 1 stop bit */
-#define TWO_STOP_BITS 2 /* representation for 2 stop bits */
-#define ONE_AND_A_HALF_STOP_BITS 3 /* representation for 1.5 stop bits */
-
-/* bit settings for the 'parity' definition */
-#define NO_PARITY 0 /* representation for no parity */
-#define ODD_PARITY 1 /* representation for odd parity */
-#define EVEN_PARITY 2 /* representation for even parity */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_COMMS_ERROR_STATS command (asynchronous mode)
- * --------------------------------------------------------------------------*/
-
-/* the communications error statistics structure */
-typedef struct {
- unsigned short Rx_overrun_err_count PACKED; /* receiver overrun error count */
- unsigned short Rx_parity_err_count PACKED; /* parity errors received count */
- unsigned short Rx_framing_err_count PACKED; /* framing errors received count */
- unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_2 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_3 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_4 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_5 PACKED;/* reserved for later use */
- unsigned short DCD_state_change_count PACKED; /* DCD state change count */
- unsigned short CTS_state_change_count PACKED; /* CTS state change count */
-} ASY_COMMS_ERROR_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_ASY_OPERATIONAL_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the asynchronous operational statistics structure */
-typedef struct {
-
- /* Data transmission statistics */
- unsigned long Data_blocks_Tx_count PACKED;/* number of blocks transmitted */
- unsigned long Data_bytes_Tx_count PACKED;/* number of bytes transmitted */
- unsigned long Data_Tx_throughput PACKED;/* transmit throughput */
- unsigned long no_ms_for_Data_Tx_thruput_comp PACKED;/* millisecond time used for the Tx throughput computation */
- unsigned long Tx_Data_discard_lgth_err_count PACKED;/* number of Data blocks discarded (length error) */
- unsigned long reserved_Data_frm_Tx_stat1 PACKED;/* reserved for later use */
- unsigned long reserved_Data_frm_Tx_stat2 PACKED;/* reserved for later use */
- unsigned long reserved_Data_frm_Tx_stat3 PACKED;/* reserved for later use */
-
- /* Data reception statistics */
- unsigned long Data_blocks_Rx_count PACKED;/* number of blocks received */
- unsigned long Data_bytes_Rx_count PACKED;/* number of bytes received */
- unsigned long Data_Rx_throughput PACKED;/* receive throughput */
- unsigned long no_ms_for_Data_Rx_thruput_comp PACKED;/* millisecond time used for the Rx throughput computation */
- unsigned long Rx_Data_bytes_discard_count PACKED;/* received Data bytes discarded */
- unsigned long reserved_Data_frm_Rx_stat1 PACKED;/* reserved for later use */
-
- /* handshaking protocol statistics */
- unsigned short XON_chars_Tx_count PACKED; /* number of XON characters transmitted */
- unsigned short XOFF_chars_Tx_count PACKED; /* number of XOFF characters transmitted */
- unsigned short XON_chars_Rx_count PACKED; /* number of XON characters received */
- unsigned short XOFF_chars_Rx_count PACKED; /* number of XOFF characters received */
- unsigned short Tx_halt_modem_low_count PACKED; /* number of times Tx halted (modem line low) */
- unsigned short Rx_halt_RTS_low_count PACKED; /* number of times Rx halted by setting RTS low */
- unsigned long reserved_handshaking_stat1 PACKED;/* reserved for later use */
-
- /* break statistics */
- unsigned short break_Tx_count PACKED; /* number of break sequences transmitted */
- unsigned short break_Rx_count PACKED; /* number of break sequences received */
- unsigned long reserved_break_stat1 PACKED;/* reserved for later use */
-
- /* miscellaneous statistics */
- unsigned long reserved_misc_stat1 PACKED; /* reserved for later use */
- unsigned long reserved_misc_stat2 PACKED; /* reserved for later use */
-
-} ASY_OPERATIONAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data transmission
- * --------------------------------------------------------------------------*/
-
-/* the Data block transmit status element configuration structure */
-typedef struct {
- unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */
- unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */
- unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */
-} ASY_TX_STATUS_EL_CFG_STRUCT;
-
-
-/* the Data block transmit status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short data_length PACKED; /* length of the block to be transmitted */
- unsigned char reserved_1 PACKED; /* reserved for internal use */
- unsigned long reserved_2 PACKED; /* reserved for internal use */
- unsigned long reserved_3 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} ASY_DATA_TX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data reception
- * --------------------------------------------------------------------------*/
-
-/* the Data block receive status element configuration structure */
-typedef struct {
- unsigned short number_Rx_status_elements PACKED;/* number of receive status elements */
- unsigned long base_addr_Rx_status_elements PACKED;/* base address of the receive element list */
- unsigned long next_Rx_status_element_to_use PACKED;/* pointer to the next receive element to be used */
- unsigned long base_addr_Rx_buffer PACKED;/* base address of the receive data buffer */
- unsigned long end_addr_Rx_buffer PACKED;/* end address of the receive data buffer */
-} ASY_RX_STATUS_EL_CFG_STRUCT;
-
-/* the Data block receive status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short data_length PACKED; /* length of the received data block */
- unsigned char reserved_1 PACKED; /* reserved for internal use */
- unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
- unsigned short data_buffered PACKED; /* the number of data bytes still buffered */
- unsigned long reserved_2 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} ASY_DATA_RX_STATUS_EL_STRUCT;
-
-#endif
diff --git a/include/linux/sdla_chdlc.h b/include/linux/sdla_chdlc.h
deleted file mode 100644
index d2e35a299034..000000000000
--- a/include/linux/sdla_chdlc.h
+++ /dev/null
@@ -1,813 +0,0 @@
-/*************************************************************************
- sdla_chdlc.h Sangoma Cisco HDLC firmware API definitions
-
- Author: Gideon Hack
- Nenad Corbic <ncorbic@sangoma.com>
-
- Copyright: (c) 1995-2000 Sangoma Technologies Inc.
-
- This program is free software; you can redistribute it and/or
- modify it under the term of the GNU General Public License
- as published by the Free Software Foundation; either version
- 2 of the License, or (at your option) any later version.
-
-===========================================================================
- Oct 04, 1999 Nenad Corbic Updated API support
- Jun 02, 1999 Gideon Hack Changes for S514 usage.
- Oct 28, 1998 Jaspreet Singh Made changes for Dual Port CHDLC.
- Jun 11, 1998 David Fong Initial version.
-===========================================================================
-
- Organization
- - Compatibility notes
- - Constants defining the shared memory control block (mailbox)
- - Interface commands
- - Return code from interface commands
- - Constants for the commands (structures for casting data)
- - UDP Management constants and structures
-
-*************************************************************************/
-
-#ifndef _SDLA_CHDLC_H
-# define _SDLC_CHDLC_H
-
-/*------------------------------------------------------------------------
- Notes:
-
- All structres defined in this file are byte-aligned.
-
- Compiler Platform
- ------------------------
- GNU C Linux
-
-------------------------------------------------------------------------*/
-
-#ifndef PACKED
-#define PACKED __attribute__((packed))
-#endif /* PACKED */
-
-
-/* ----------------------------------------------------------------------------
- * Constants defining the shared memory control block (mailbox)
- * --------------------------------------------------------------------------*/
-
-#define PRI_BASE_ADDR_MB_STRUCT 0xE000 /* the base address of the mailbox structure on the adapter */
-#define SEC_BASE_ADDR_MB_STRUCT 0xE800 /* the base address of the mailbox structure on the adapter */
-#define SIZEOF_MB_DATA_BFR 2032 /* the size of the actual mailbox data area */
-#define NUMBER_MB_RESERVED_BYTES 0x0B /* the number of reserved bytes in the mailbox header area */
-
-
-#define MIN_LGTH_CHDLC_DATA_CFG 300 /* min length of the CHDLC data field (for configuration purposes) */
-#define PRI_MAX_NO_DATA_BYTES_IN_FRAME 15354 /* PRIMARY - max length of the CHDLC data field */
-
-typedef struct {
- unsigned char opp_flag PACKED; /* the opp flag */
- unsigned char command PACKED; /* the user command */
- unsigned short buffer_length PACKED; /* the data length */
- unsigned char return_code PACKED; /* the return code */
- unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; /* the data area */
-} CHDLC_MAILBOX_STRUCT;
-
-typedef struct {
- pid_t pid_num PACKED;
- CHDLC_MAILBOX_STRUCT cmdarea PACKED;
-
-} CMDBLOCK_STRUCT;
-
-
-
-
-/* ----------------------------------------------------------------------------
- * Interface commands
- * --------------------------------------------------------------------------*/
-
-/* global interface commands */
-#define READ_GLOBAL_EXCEPTION_CONDITION 0x01
-#define SET_GLOBAL_CONFIGURATION 0x02
-#define READ_GLOBAL_CONFIGURATION 0x03
-#define READ_GLOBAL_STATISTICS 0x04
-#define FLUSH_GLOBAL_STATISTICS 0x05
-#define SET_MODEM_STATUS 0x06 /* set status of DTR or RTS */
-#define READ_MODEM_STATUS 0x07 /* read status of CTS and DCD */
-#define READ_COMMS_ERROR_STATS 0x08
-#define FLUSH_COMMS_ERROR_STATS 0x09
-#define SET_TRACE_CONFIGURATION 0x0A /* set the line trace config */
-#define READ_TRACE_CONFIGURATION 0x0B /* read the line trace config */
-#define READ_TRACE_STATISTICS 0x0C /* read the trace statistics */
-#define FLUSH_TRACE_STATISTICS 0x0D /* flush the trace statistics */
-#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the S508/FT1 monitoring */
-#define SET_FT1_CONFIGURATION 0x18 /* set the FT1 configuration */
-#define READ_FT1_CONFIGURATION 0x19 /* read the FT1 configuration */
-#define TRANSMIT_ASYNC_DATA_TO_FT1 0x1A /* output asynchronous data to the FT1 */
-#define RECEIVE_ASYNC_DATA_FROM_FT1 0x1B /* receive asynchronous data from the FT1 */
-#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the FT1 monitoring */
-
-#define READ_FT1_OPERATIONAL_STATS 0x1D /* read the S508/FT1 operational statistics */
-#define SET_FT1_MODE 0x1E /* set the operational mode of the S508/FT1 module */
-
-/* CHDLC-level interface commands */
-#define READ_CHDLC_CODE_VERSION 0x20
-#define READ_CHDLC_EXCEPTION_CONDITION 0x21 /* read exception condition from the adapter */
-#define SET_CHDLC_CONFIGURATION 0x22
-#define READ_CHDLC_CONFIGURATION 0x23
-#define ENABLE_CHDLC_COMMUNICATIONS 0x24
-#define DISABLE_CHDLC_COMMUNICATIONS 0x25
-#define READ_CHDLC_LINK_STATUS 0x26
-#define READ_CHDLC_OPERATIONAL_STATS 0x27
-#define FLUSH_CHDLC_OPERATIONAL_STATS 0x28
-#define SET_CHDLC_INTERRUPT_TRIGGERS 0x30 /* set application interrupt triggers */
-#define READ_CHDLC_INTERRUPT_TRIGGERS 0x31 /* read application interrupt trigger configuration */
-
-/* Special UDP drivers management commands */
-#define CPIPE_ENABLE_TRACING 0x50
-#define CPIPE_DISABLE_TRACING 0x51
-#define CPIPE_GET_TRACE_INFO 0x52
-#define CPIPE_GET_IBA_DATA 0x53
-#define CPIPE_FT1_READ_STATUS 0x54
-#define CPIPE_DRIVER_STAT_IFSEND 0x55
-#define CPIPE_DRIVER_STAT_INTR 0x56
-#define CPIPE_DRIVER_STAT_GEN 0x57
-#define CPIPE_FLUSH_DRIVER_STATS 0x58
-#define CPIPE_ROUTER_UP_TIME 0x59
-
-/* Driver specific commands for API */
-#define CHDLC_READ_TRACE_DATA 0xE4 /* read trace data */
-#define TRACE_ALL 0x00
-#define TRACE_PROT 0x01
-#define TRACE_DATA 0x02
-
-#define DISCARD_RX_ERROR_FRAMES 0x0001
-
-/* ----------------------------------------------------------------------------
- * Return codes from interface commands
- * --------------------------------------------------------------------------*/
-
-#define COMMAND_OK 0x00
-
-/* return codes from global interface commands */
-#define NO_GLOBAL_EXCEP_COND_TO_REPORT 0x01 /* there is no CHDLC exception condition to report */
-#define LGTH_GLOBAL_CFG_DATA_INVALID 0x01 /* the length of the passed global configuration data is invalid */
-#define LGTH_TRACE_CFG_DATA_INVALID 0x01 /* the length of the passed trace configuration data is invalid */
-#define IRQ_TIMEOUT_VALUE_INVALID 0x02 /* an invalid application IRQ timeout value was selected */
-#define TRACE_CONFIG_INVALID 0x02 /* the passed line trace configuration is invalid */
-#define ADAPTER_OPERATING_FREQ_INVALID 0x03 /* an invalid adapter operating frequency was selected */
-#define TRC_DEAC_TMR_INVALID 0x03 /* the trace deactivation timer is invalid */
-#define S508_FT1_ADPTR_NOT_PRESENT 0x0C /* the S508/FT1 adapter is not present */
-#define INVALID_FT1_STATUS_SELECTION 0x0D /* the S508/FT1 status selection is invalid */
-#define FT1_OP_STATS_NOT_ENABLED 0x0D /* the FT1 operational statistics have not been enabled */
-#define FT1_OP_STATS_NOT_AVAILABLE 0x0E /* the FT1 operational statistics are not currently available */
-#define S508_FT1_MODE_SELECTION_BUSY 0x0E /* the S508/FT1 adapter is busy selecting the operational mode */
-
-/* return codes from command READ_GLOBAL_EXCEPTION_CONDITION */
-#define EXCEP_MODEM_STATUS_CHANGE 0x10 /* a modem status change occurred */
-#define EXCEP_TRC_DISABLED 0x11 /* the trace has been disabled */
-#define EXCEP_IRQ_TIMEOUT 0x12 /* IRQ timeout */
-
-/* return codes from CHDLC-level interface commands */
-#define NO_CHDLC_EXCEP_COND_TO_REPORT 0x21 /* there is no CHDLC exception condition to report */
-#define CHDLC_COMMS_DISABLED 0x21 /* communications are not currently enabled */
-#define CHDLC_COMMS_ENABLED 0x21 /* communications are currently enabled */
-#define DISABLE_CHDLC_COMMS_BEFORE_CFG 0x21 /* CHDLC communications must be disabled before setting the configuration */
-#define ENABLE_CHDLC_COMMS_BEFORE_CONN 0x21 /* communications must be enabled before using the CHDLC_CONNECT conmmand */
-#define CHDLC_CFG_BEFORE_COMMS_ENABLED 0x22 /* perform a SET_CHDLC_CONFIGURATION before enabling comms */
-#define LGTH_CHDLC_CFG_DATA_INVALID 0x22 /* the length of the passed CHDLC configuration data is invalid */
-#define LGTH_INT_TRIGGERS_DATA_INVALID 0x22 /* the length of the passed interrupt trigger data is invalid */
-#define INVALID_IRQ_SELECTED 0x23 /* in invalid IRQ was selected in the SET_CHDLC_INTERRUPT_TRIGGERS */
-#define INVALID_CHDLC_CFG_DATA 0x23 /* the passed CHDLC configuration data is invalid */
-#define IRQ_TMR_VALUE_INVALID 0x24 /* an invalid application IRQ timer value was selected */
-#define LARGER_PERCENT_TX_BFR_REQUIRED 0x24 /* a larger Tx buffer percentage is required */
-#define LARGER_PERCENT_RX_BFR_REQUIRED 0x25 /* a larger Rx buffer percentage is required */
-#define S514_BOTH_PORTS_SAME_CLK_MODE 0x26 /* S514 - both ports must have same clock mode */
-#define INVALID_CMND_HDLC_STREAM_MODE 0x4E /* the CHDLC interface command is invalid for HDLC streaming mode */
-#define INVALID_CHDLC_COMMAND 0x4F /* the defined CHDLC interface command is invalid */
-
-/* return codes from command READ_CHDLC_EXCEPTION_CONDITION */
-#define EXCEP_LINK_ACTIVE 0x30 /* the CHDLC link has become active */
-#define EXCEP_LINK_INACTIVE_MODEM 0x31 /* the CHDLC link has become inactive (modem status) */
-#define EXCEP_LINK_INACTIVE_KPALV 0x32 /* the CHDLC link has become inactive (keepalive status) */
-#define EXCEP_IP_ADDRESS_DISCOVERED 0x33 /* the IP address has been discovered */
-#define EXCEP_LOOPBACK_CONDITION 0x34 /* a loopback condition has occurred */
-
-
-/* return code from command CHDLC_SEND_WAIT and CHDLC_SEND_NO_WAIT */
-#define LINK_DISCONNECTED 0x21
-#define NO_TX_BFRS_AVAIL 0x24
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_GLOBAL_CONFIGURATION/READ_GLOBAL_CONFIGURATION commands
- * --------------------------------------------------------------------------*/
-
-/* the global configuration structure */
-typedef struct {
- unsigned short adapter_config_options PACKED; /* adapter config options */
- unsigned short app_IRQ_timeout PACKED; /* application IRQ timeout */
- unsigned long adapter_operating_frequency PACKED; /* adapter operating frequency */
-} GLOBAL_CONFIGURATION_STRUCT;
-
-/* settings for the 'app_IRQ_timeout' */
-#define MAX_APP_IRQ_TIMEOUT_VALUE 5000 /* the maximum permitted IRQ timeout */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_GLOBAL_STATISTICS command
- * --------------------------------------------------------------------------*/
-
-/* the global statistics structure */
-typedef struct {
- unsigned short app_IRQ_timeout_count PACKED;
-} GLOBAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_COMMS_ERROR_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the communications error statistics structure */
-typedef struct {
- unsigned short Rx_overrun_err_count PACKED;
- unsigned short CRC_err_count PACKED; /* receiver CRC error count */
- unsigned short Rx_abort_count PACKED; /* abort frames recvd count */
- unsigned short Rx_dis_pri_bfrs_full_count PACKED;/* receiver disabled */
- unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later */
- unsigned short sec_Tx_abort_msd_Tx_int_count PACKED; /* secondary - abort frames transmitted count (missed Tx interrupt) */
- unsigned short missed_Tx_und_int_count PACKED; /* missed tx underrun interrupt count */
- unsigned short sec_Tx_abort_count PACKED; /*secondary-abort frames tx count */
- unsigned short DCD_state_change_count PACKED; /* DCD state change */
- unsigned short CTS_state_change_count PACKED; /* CTS state change */
-} COMMS_ERROR_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants used for line tracing
- * --------------------------------------------------------------------------*/
-
-/* the trace configuration structure (SET_TRACE_CONFIGURATION/READ_TRACE_CONFIGURATION commands) */
-typedef struct {
- unsigned char trace_config PACKED; /* trace configuration */
- unsigned short trace_deactivation_timer PACKED; /* trace deactivation timer */
- unsigned long ptr_trace_stat_el_cfg_struct PACKED; /* a pointer to the line trace element configuration structure */
-} LINE_TRACE_CONFIG_STRUCT;
-
-/* 'trace_config' bit settings */
-#define TRACE_INACTIVE 0x00 /* trace is inactive */
-#define TRACE_ACTIVE 0x01 /* trace is active */
-#define TRACE_DELAY_MODE 0x04 /* operate the trace in delay mode */
-#define TRACE_DATA_FRAMES 0x08 /* trace Data frames */
-#define TRACE_SLARP_FRAMES 0x10 /* trace SLARP frames */
-#define TRACE_CDP_FRAMES 0x20 /* trace CDP frames */
-
-/* the line trace status element configuration structure */
-typedef struct {
- unsigned short number_trace_status_elements PACKED; /* number of line trace elements */
- unsigned long base_addr_trace_status_elements PACKED; /* base address of the trace element list */
- unsigned long next_trace_element_to_use PACKED; /* pointer to the next trace element to be used */
- unsigned long base_addr_trace_buffer PACKED; /* base address of the trace data buffer */
- unsigned long end_addr_trace_buffer PACKED; /* end address of the trace data buffer */
-} TRACE_STATUS_EL_CFG_STRUCT;
-
-/* the line trace status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short trace_length PACKED; /* trace length */
- unsigned char trace_type PACKED; /* trace type */
- unsigned short trace_time_stamp PACKED; /* time stamp */
- unsigned short trace_reserved_1 PACKED; /* reserved for later use */
- unsigned long trace_reserved_2 PACKED; /* reserved for later use */
- unsigned long ptr_data_bfr PACKED; /* ptr to the trace data buffer */
-} TRACE_STATUS_ELEMENT_STRUCT;
-
-/* "trace_type" bit settings */
-#define TRACE_INCOMING 0x00
-#define TRACE_OUTGOINGING 0x01
-#define TRACE_INCOMING_ABORTED 0x10
-#define TRACE_INCOMING_CRC_ERROR 0x20
-#define TRACE_INCOMING_OVERRUN_ERROR 0x40
-
-
-
-/* the line trace statistics structure */
-typedef struct {
- unsigned long frames_traced_count PACKED; /* number of frames traced */
- unsigned long trc_frms_not_recorded_count PACKED; /* number of trace frames discarded */
-} LINE_TRACE_STATS_STRUCT;
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the FT1_MONITOR_STATUS_CTRL command
- * --------------------------------------------------------------------------*/
-
-#define DISABLE_FT1_STATUS_STATISTICS 0x00 /* disable the FT1 status and statistics monitoring */
-#define ENABLE_READ_FT1_STATUS 0x01 /* read the FT1 operational status */
-#define ENABLE_READ_FT1_OP_STATS 0x02 /* read the FT1 operational statistics */
-#define FLUSH_FT1_OP_STATS 0x04 /* flush the FT1 operational statistics */
-
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_CHDLC_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC configuration structure */
-typedef struct {
- unsigned long baud_rate PACKED; /* the baud rate */
- unsigned short line_config_options PACKED; /* line configuration options */
- unsigned short modem_config_options PACKED; /* modem configration options */
- unsigned short modem_status_timer PACKED; /* timer for monitoring modem status changes */
- unsigned short CHDLC_API_options PACKED; /* CHDLC API options */
- unsigned short CHDLC_protocol_options PACKED; /* CHDLC protocol options */
- unsigned short percent_data_buffer_for_Tx PACKED; /* percentage data buffering used for Tx */
- unsigned short CHDLC_statistics_options PACKED; /* CHDLC operational statistics options */
- unsigned short max_CHDLC_data_field_length PACKED; /* the maximum length of the CHDLC Data field */
- unsigned short transmit_keepalive_timer PACKED; /* the transmit keepalive timer */
- unsigned short receive_keepalive_timer PACKED; /* the receive keepalive timer */
- unsigned short keepalive_error_tolerance PACKED; /* the receive keepalive error tolerance */
- unsigned short SLARP_request_timer PACKED; /* the SLARP request timer */
- unsigned long IP_address PACKED; /* the IP address */
- unsigned long IP_netmask PACKED; /* the IP netmask */
- unsigned long ptr_shared_mem_info_struct PACKED; /* a pointer to the shared memory area information structure */
- unsigned long ptr_CHDLC_Tx_stat_el_cfg_struct PACKED; /* a pointer to the transmit status element configuration structure */
- unsigned long ptr_CHDLC_Rx_stat_el_cfg_struct PACKED; /* a pointer to the receive status element configuration structure */
-} CHDLC_CONFIGURATION_STRUCT;
-
-/* settings for the 'line_config_options' */
-#define INTERFACE_LEVEL_V35 0x0000 /* V.35 interface level */
-#define INTERFACE_LEVEL_RS232 0x0001 /* RS-232 interface level */
-
-/* settings for the 'modem_config_options' */
-
-#define DONT_RAISE_DTR_RTS_ON_EN_COMMS 0x0001
-/* don't automatically raise DTR and RTS when performing an
- ENABLE_CHDLC_COMMUNICATIONS command */
-
-#define DONT_REPORT_CHG_IN_MODEM_STAT 0x0002
-/* don't report changes in modem status to the application */
-
-
-/* bit settings for the 'CHDLC_protocol_options' byte */
-
-#define IGNORE_DCD_FOR_LINK_STAT 0x0001
-/* ignore DCD in determining the CHDLC link status */
-
-#define IGNORE_CTS_FOR_LINK_STAT 0x0002
-/* ignore CTS in determining the CHDLC link status */
-
-#define IGNORE_KPALV_FOR_LINK_STAT 0x0004
-/* ignore keepalive frames in determining the CHDLC link status */
-
-#define SINGLE_TX_BUFFER 0x4000
-/* configure a single transmit buffer */
-
-#define HDLC_STREAMING_MODE 0x8000
-
-/* settings for the 'CHDLC_statistics_options' */
-
-#define CHDLC_TX_DATA_BYTE_COUNT_STAT 0x0001
-/* record the number of Data bytes transmitted */
-
-#define CHDLC_RX_DATA_BYTE_COUNT_STAT 0x0002
-/* record the number of Data bytes received */
-
-#define CHDLC_TX_THROUGHPUT_STAT 0x0004
-/* compute the Data frame transmit throughput */
-
-#define CHDLC_RX_THROUGHPUT_STAT 0x0008
-/* compute the Data frame receive throughput */
-
-
-/* permitted minimum and maximum values for setting the CHDLC configuration */
-#define PRI_MAX_BAUD_RATE_S508 2666666 /* PRIMARY - maximum baud rate (S508) */
-#define SEC_MAX_BAUD_RATE_S508 258064 /* SECONDARY - maximum baud rate (S508) */
-#define PRI_MAX_BAUD_RATE_S514 2750000 /* PRIMARY - maximum baud rate (S508) */
-#define SEC_MAX_BAUD_RATE_S514 515625 /* SECONDARY - maximum baud rate (S508) */
-
-#define MIN_MODEM_TIMER 0 /* minimum modem status timer */
-#define MAX_MODEM_TIMER 5000 /* maximum modem status timer */
-
-#define SEC_MAX_NO_DATA_BYTES_IN_FRAME 2048 /* SECONDARY - max length of the CHDLC data field */
-
-#define MIN_Tx_KPALV_TIMER 0 /* minimum transmit keepalive timer */
-#define MAX_Tx_KPALV_TIMER 60000 /* maximum transmit keepalive timer */
-#define DEFAULT_Tx_KPALV_TIMER 10000 /* default transmit keepalive timer */
-
-#define MIN_Rx_KPALV_TIMER 10 /* minimum receive keepalive timer */
-#define MAX_Rx_KPALV_TIMER 60000 /* maximum receive keepalive timer */
-#define DEFAULT_Rx_KPALV_TIMER 10000 /* default receive keepalive timer */
-
-#define MIN_KPALV_ERR_TOL 1 /* min kpalv error tolerance count */
-#define MAX_KPALV_ERR_TOL 20 /* max kpalv error tolerance count */
-#define DEFAULT_KPALV_ERR_TOL 3 /* default value */
-
-#define MIN_SLARP_REQ_TIMER 0 /* min transmit SLARP Request timer */
-#define MAX_SLARP_REQ_TIMER 60000 /* max transmit SLARP Request timer */
-#define DEFAULT_SLARP_REQ_TIMER 0 /* default value -- no SLARP */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_CHDLC_LINK_STATUS command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC status structure */
-typedef struct {
- unsigned char CHDLC_link_status PACKED; /* CHDLC link status */
- unsigned char no_Data_frms_for_app PACKED; /* number of Data frames available for the application */
- unsigned char receiver_status PACKED; /* enabled/disabled */
- unsigned char SLARP_state PACKED; /* internal SLARP state */
-} CHDLC_LINK_STATUS_STRUCT;
-
-/* settings for the 'CHDLC_link_status' variable */
-#define CHDLC_LINK_INACTIVE 0x00 /* the CHDLC link is inactive */
-#define CHDLC_LINK_ACTIVE 0x01 /* the CHDLC link is active */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_CHDLC_OPERATIONAL_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC operational statistics structure */
-typedef struct {
-
- /* Data frame transmission statistics */
- unsigned long Data_frames_Tx_count PACKED; /* # of frames transmitted */
- unsigned long Data_bytes_Tx_count PACKED; /* # of bytes transmitted */
- unsigned long Data_Tx_throughput PACKED; /* transmit throughput */
- unsigned long no_ms_for_Data_Tx_thruput_comp PACKED; /* millisecond time used for the Tx throughput computation */
- unsigned long Tx_Data_discard_lgth_err_count PACKED; /* number of Data frames discarded (length error) */
- unsigned long reserved_Data_frm_Tx_stat1 PACKED; /* reserved for later */
- unsigned long reserved_Data_frm_Tx_stat2 PACKED; /* reserved for later */
- unsigned long reserved_Data_frm_Tx_stat3 PACKED; /* reserved for later */
-
- /* Data frame reception statistics */
- unsigned long Data_frames_Rx_count PACKED; /* number of frames received */
- unsigned long Data_bytes_Rx_count PACKED; /* number of bytes received */
- unsigned long Data_Rx_throughput PACKED; /* receive throughput */
- unsigned long no_ms_for_Data_Rx_thruput_comp PACKED; /* millisecond time used for the Rx throughput computation */
- unsigned long Rx_Data_discard_short_count PACKED; /* received Data frames discarded (too short) */
- unsigned long Rx_Data_discard_long_count PACKED; /* received Data frames discarded (too long) */
- unsigned long Rx_Data_discard_inactive_count PACKED; /* received Data frames discarded (link inactive) */
- unsigned long reserved_Data_frm_Rx_stat1 PACKED; /* reserved for later */
-
- /* SLARP frame transmission/reception statistics */
- unsigned long CHDLC_SLARP_REQ_Tx_count PACKED; /* number of SLARP Request frames transmitted */
- unsigned long CHDLC_SLARP_REQ_Rx_count PACKED; /* number of SLARP Request frames received */
- unsigned long CHDLC_SLARP_REPLY_Tx_count PACKED; /* number of SLARP Reply frames transmitted */
- unsigned long CHDLC_SLARP_REPLY_Rx_count PACKED; /* number of SLARP Reply frames received */
- unsigned long CHDLC_SLARP_KPALV_Tx_count PACKED; /* number of SLARP keepalive frames transmitted */
- unsigned long CHDLC_SLARP_KPALV_Rx_count PACKED; /* number of SLARP keepalive frames received */
- unsigned long reserved_SLARP_stat1 PACKED; /* reserved for later */
- unsigned long reserved_SLARP_stat2 PACKED; /* reserved for later */
-
- /* CDP frame transmission/reception statistics */
- unsigned long CHDLC_CDP_Tx_count PACKED; /* number of CDP frames transmitted */
- unsigned long CHDLC_CDP_Rx_count PACKED; /* number of CDP frames received */
- unsigned long reserved_CDP_stat1 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat2 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat3 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat4 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat5 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat6 PACKED; /* reserved for later */
-
- /* Incoming frames with a format error statistics */
- unsigned short Rx_frm_incomp_CHDLC_hdr_count PACKED; /* frames received of with incomplete Cisco HDLC header */
- unsigned short Rx_frms_too_long_count PACKED; /* frames received of excessive length count */
- unsigned short Rx_invalid_CHDLC_addr_count PACKED; /* frames received with an invalid CHDLC address count */
- unsigned short Rx_invalid_CHDLC_ctrl_count PACKED; /* frames received with an invalid CHDLC control field count */
- unsigned short Rx_invalid_CHDLC_type_count PACKED; /* frames received of an invalid CHDLC frame type count */
- unsigned short Rx_SLARP_invalid_code_count PACKED; /* SLARP frame received with an invalid packet code */
- unsigned short Rx_SLARP_Reply_bad_IP_addr PACKED; /* SLARP Reply received - bad IP address */
- unsigned short Rx_SLARP_Reply_bad_netmask PACKED; /* SLARP Reply received - bad netmask */
- unsigned long reserved_frm_format_err1 PACKED; /* reserved for later */
- unsigned long reserved_frm_format_err2 PACKED; /* reserved for later */
- unsigned long reserved_frm_format_err3 PACKED; /* reserved for later */
- unsigned long reserved_frm_format_err4 PACKED; /* reserved for later */
-
- /* CHDLC timeout/retry statistics */
- unsigned short SLARP_Rx_keepalive_TO_count PACKED; /* timeout count for incoming SLARP frames */
- unsigned short SLARP_Request_TO_count PACKED; /* timeout count for SLARP Request frames */
- unsigned long To_retry_reserved_stat1 PACKED; /* reserved for later */
- unsigned long To_retry_reserved_stat2 PACKED; /* reserved for later */
- unsigned long To_retry_reserved_stat3 PACKED; /* reserved for later */
-
- /* CHDLC link active/inactive and loopback statistics */
- unsigned short link_active_count PACKED; /* number of times that the link went active */
- unsigned short link_inactive_modem_count PACKED; /* number of times that the link went inactive (modem failure) */
- unsigned short link_inactive_keepalive_count PACKED; /* number of times that the link went inactive (keepalive failure) */
- unsigned short link_looped_count PACKED; /* link looped count */
- unsigned long link_status_reserved_stat1 PACKED; /* reserved for later use */
- unsigned long link_status_reserved_stat2 PACKED; /* reserved for later use */
-
- /* miscellaneous statistics */
- unsigned long reserved_misc_stat1 PACKED; /* reserved for later */
- unsigned long reserved_misc_stat2 PACKED; /* reserved for later */
- unsigned long reserved_misc_stat3 PACKED; /* reserved for later */
- unsigned long reserved_misc_stat4 PACKED; /* reserved for later */
-
-} CHDLC_OPERATIONAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for using application interrupts
- * --------------------------------------------------------------------------*/
-
-/* the structure used for the SET_CHDLC_INTERRUPT_TRIGGERS/READ_CHDLC_INTERRUPT_TRIGGERS command */
-typedef struct {
- unsigned char CHDLC_interrupt_triggers PACKED; /* CHDLC interrupt trigger configuration */
- unsigned char IRQ PACKED; /* IRQ to be used */
- unsigned short interrupt_timer PACKED; /* interrupt timer */
- unsigned short misc_interrupt_bits PACKED; /* miscellaneous bits */
-} CHDLC_INT_TRIGGERS_STRUCT;
-
-/* 'CHDLC_interrupt_triggers' bit settings */
-#define APP_INT_ON_RX_FRAME 0x01 /* interrupt on Data frame reception */
-#define APP_INT_ON_TX_FRAME 0x02 /* interrupt when an Data frame may be transmitted */
-#define APP_INT_ON_COMMAND_COMPLETE 0x04 /* interrupt when an interface command is complete */
-#define APP_INT_ON_TIMER 0x08 /* interrupt on a defined millisecond timeout */
-#define APP_INT_ON_GLOBAL_EXCEP_COND 0x10 /* interrupt on a global exception condition */
-#define APP_INT_ON_CHDLC_EXCEP_COND 0x20 /* interrupt on an CHDLC exception condition */
-#define APP_INT_ON_TRACE_DATA_AVAIL 0x80 /* interrupt when trace data is available */
-
-/* interrupt types indicated at 'interrupt_type' byte of the INTERRUPT_INFORMATION_STRUCT */
-#define NO_APP_INTS_PEND 0x00 /* no interrups are pending */
-#define RX_APP_INT_PEND 0x01 /* a receive interrupt is pending */
-#define TX_APP_INT_PEND 0x02 /* a transmit interrupt is pending */
-#define COMMAND_COMPLETE_APP_INT_PEND 0x04 /* a 'command complete' interrupt is pending */
-#define TIMER_APP_INT_PEND 0x08 /* a timer interrupt is pending */
-#define GLOBAL_EXCEP_COND_APP_INT_PEND 0x10 /* a global exception condition interrupt is pending */
-#define CHDLC_EXCEP_COND_APP_INT_PEND 0x20 /* an CHDLC exception condition interrupt is pending */
-#define TRACE_DATA_AVAIL_APP_INT_PEND 0x80 /* a trace data available interrupt is pending */
-
-
-/* modem status changes */
-#define DCD_HIGH 0x08
-#define CTS_HIGH 0x20
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data frame transmission
- * --------------------------------------------------------------------------*/
-
-/* the Data frame transmit status element configuration structure */
-typedef struct {
- unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */
- unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */
- unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */
-} CHDLC_TX_STATUS_EL_CFG_STRUCT;
-
-/* the Data frame transmit status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short frame_length PACKED; /* length of the frame to be transmitted */
- unsigned char reserved_1 PACKED; /* reserved for internal use */
- unsigned long reserved_2 PACKED; /* reserved for internal use */
- unsigned long reserved_3 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} CHDLC_DATA_TX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data frame reception
- * --------------------------------------------------------------------------*/
-
-/* the Data frame receive status element configuration structure */
-typedef struct {
- unsigned short number_Rx_status_elements PACKED; /* number of receive status elements */
- unsigned long base_addr_Rx_status_elements PACKED; /* base address of the receive element list */
- unsigned long next_Rx_status_element_to_use PACKED; /* pointer to the next receive element to be used */
- unsigned long base_addr_Rx_buffer PACKED; /* base address of the receive data buffer */
- unsigned long end_addr_Rx_buffer PACKED; /* end address of the receive data buffer */
-} CHDLC_RX_STATUS_EL_CFG_STRUCT;
-
-/* the Data frame receive status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short frame_length PACKED; /* length of the received frame */
- unsigned char error_flag PACKED; /* frame errors (HDLC_STREAMING_MODE)*/
- unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
- unsigned long reserved_1 PACKED; /* reserved for internal use */
- unsigned short reserved_2 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} CHDLC_DATA_RX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants defining the shared memory information area
- * --------------------------------------------------------------------------*/
-
-/* the global information structure */
-typedef struct {
- unsigned char global_status PACKED; /* global status */
- unsigned char modem_status PACKED; /* current modem status */
- unsigned char global_excep_conditions PACKED; /* global exception conditions */
- unsigned char glob_info_reserved[5] PACKED; /* reserved */
- unsigned char codename[4] PACKED; /* Firmware name */
- unsigned char codeversion[4] PACKED; /* Firmware version */
-} GLOBAL_INFORMATION_STRUCT;
-
-/* the CHDLC information structure */
-typedef struct {
- unsigned char CHDLC_status PACKED; /* CHDLC status */
- unsigned char CHDLC_excep_conditions PACKED; /* CHDLC exception conditions */
- unsigned char CHDLC_info_reserved[14] PACKED; /* reserved */
-} CHDLC_INFORMATION_STRUCT;
-
-/* the interrupt information structure */
-typedef struct {
- unsigned char interrupt_type PACKED; /* type of interrupt triggered */
- unsigned char interrupt_permission PACKED; /* interrupt permission mask */
- unsigned char int_info_reserved[14] PACKED; /* reserved */
-} INTERRUPT_INFORMATION_STRUCT;
-
-/* the S508/FT1 information structure */
-typedef struct {
- unsigned char parallel_port_A_input PACKED; /* input - parallel port A */
- unsigned char parallel_port_B_input PACKED; /* input - parallel port B */
- unsigned char FT1_info_reserved[14] PACKED; /* reserved */
-} FT1_INFORMATION_STRUCT;
-
-/* the shared memory area information structure */
-typedef struct {
- GLOBAL_INFORMATION_STRUCT global_info_struct PACKED; /* the global information structure */
- CHDLC_INFORMATION_STRUCT CHDLC_info_struct PACKED; /* the CHDLC information structure */
- INTERRUPT_INFORMATION_STRUCT interrupt_info_struct PACKED; /* the interrupt information structure */
- FT1_INFORMATION_STRUCT FT1_info_struct PACKED; /* the S508/FT1 information structure */
-} SHARED_MEMORY_INFO_STRUCT;
-
-/* ----------------------------------------------------------------------------
- * UDP Management constants and structures
- * --------------------------------------------------------------------------*/
-
-/* The embedded control block for UDP mgmt
- This is essentially a mailbox structure, without the large data field */
-
-typedef struct {
- unsigned char opp_flag PACKED; /* the opp flag */
- unsigned char command PACKED; /* the user command */
- unsigned short buffer_length PACKED; /* the data length */
- unsigned char return_code PACKED; /* the return code */
- unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */
-} cblock_t;
-
-
-/* UDP management packet layout (data area of ip packet) */
-/*
-typedef struct {
- unsigned char signature[8] PACKED;
- unsigned char request_reply PACKED;
- unsigned char id PACKED;
- unsigned char reserved[6] PACKED;
- cblock_t cblock PACKED;
- unsigned char num_frames PACKED;
- unsigned char ismoredata PACKED;
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
-} udp_management_packet_t;
-
-*/
-
-typedef struct {
- unsigned char num_frames PACKED;
- unsigned char ismoredata PACKED;
-} trace_info_t;
-
-typedef struct {
- ip_pkt_t ip_pkt PACKED;
- udp_pkt_t udp_pkt PACKED;
- wp_mgmt_t wp_mgmt PACKED;
- cblock_t cblock PACKED;
- trace_info_t trace_info PACKED;
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
-} chdlc_udp_pkt_t;
-
-typedef struct ft1_exec_cmd{
- unsigned char command PACKED; /* the user command */
- unsigned short buffer_length PACKED; /* the data length */
- unsigned char return_code PACKED; /* the return code */
- unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED;
-} ft1_exec_cmd_t;
-
-typedef struct {
- unsigned char opp_flag PACKED;
- ft1_exec_cmd_t cmd PACKED;
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
-} ft1_exec_t;
-
-#define UDPMGMT_SIGNATURE "CTPIPEAB"
-
-
-/* UDP/IP packet (for UDP management) layout */
-/*
-typedef struct {
- unsigned char reserved[2] PACKED;
- unsigned short ip_length PACKED;
- unsigned char reserved2[4] PACKED;
- unsigned char ip_ttl PACKED;
- unsigned char ip_protocol PACKED;
- unsigned short ip_checksum PACKED;
- unsigned long ip_src_address PACKED;
- unsigned long ip_dst_address PACKED;
- unsigned short udp_src_port PACKED;
- unsigned short udp_dst_port PACKED;
- unsigned short udp_length PACKED;
- unsigned short udp_checksum PACKED;
- udp_management_packet_t um_packet PACKED;
-} ip_packet_t;
-*/
-
-/* valid ip_protocol for UDP management */
-#define UDPMGMT_UDP_PROTOCOL 0x11
-
-
-typedef struct {
- unsigned char status PACKED;
- unsigned char data_avail PACKED;
- unsigned short real_length PACKED;
- unsigned short time_stamp PACKED;
- unsigned char data[1] PACKED;
-} trace_pkt_t;
-
-typedef struct {
- unsigned char error_flag PACKED;
- unsigned short time_stamp PACKED;
- unsigned char reserved[13] PACKED;
-} api_rx_hdr_t;
-
-typedef struct {
- api_rx_hdr_t api_rx_hdr PACKED;
- void * data PACKED;
-} api_rx_element_t;
-
-typedef struct {
- unsigned char attr PACKED;
- unsigned char reserved[15] PACKED;
-} api_tx_hdr_t;
-
-typedef struct {
- api_tx_hdr_t api_tx_hdr PACKED;
- void * data PACKED;
-} api_tx_element_t;
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_FT1_CONFIGURATION/READ_FT1_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the FT1 configuration structure */
-typedef struct {
- unsigned short framing_mode;
- unsigned short encoding_mode;
- unsigned short line_build_out;
- unsigned short channel_base;
- unsigned short baud_rate_kbps; /* the baud rate (in kbps) */
- unsigned short clock_mode;
-} ft1_config_t;
-
-/* settings for the 'framing_mode' */
-#define ESF_FRAMING 0x00 /* ESF framing */
-#define D4_FRAMING 0x01 /* D4 framing */
-
-/* settings for the 'encoding_mode' */
-#define B8ZS_ENCODING 0x00 /* B8ZS encoding */
-#define AMI_ENCODING 0x01 /* AMI encoding */
-
-/* settings for the 'line_build_out' */
-#define LN_BLD_CSU_0dB_DSX1_0_to_133 0x00 /* set build out to CSU (0db) or DSX-1 (0-133ft) */
-#define LN_BLD_DSX1_133_to_266 0x01 /* set build out DSX-1 (133-266ft) */
-#define LN_BLD_DSX1_266_to_399 0x02 /* set build out DSX-1 (266-399ft) */
-#define LN_BLD_DSX1_399_to_533 0x03 /* set build out DSX-1 (399-533ft) */
-#define LN_BLD_DSX1_533_to_655 0x04 /* set build out DSX-1 (533-655ft) */
-#define LN_BLD_CSU_NEG_7dB 0x05 /* set build out to CSU (-7.5db) */
-#define LN_BLD_CSU_NEG_15dB 0x06 /* set build out to CSU (-15db) */
-#define LN_BLD_CSU_NEG_22dB 0x07 /* set build out to CSU (-22.5db) */
-
-/* settings for the 'channel_base' */
-#define MIN_CHANNEL_BASE_VALUE 1 /* the minimum permitted channel base value */
-#define MAX_CHANNEL_BASE_VALUE 24 /* the maximum permitted channel base value */
-
-/* settings for the 'baud_rate_kbps' */
-#define MIN_BAUD_RATE_KBPS 0 /* the minimum permitted baud rate (kbps) */
-#define MAX_BAUD_RATE_KBPS 1536 /* the maximum permitted baud rate (kbps) */
-#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF /* the baud rate used to trigger an automatic FT1 configuration */
-
-/* settings for the 'clock_mode' */
-#define CLOCK_MODE_NORMAL 0x00 /* clock mode set to normal (slave) */
-#define CLOCK_MODE_MASTER 0x01 /* clock mode set to master */
-
-
-#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF
-#define AUTO_FT1_CONFIG_NOT_COMPLETE 0x08
-#define AUTO_FT1_CFG_FAIL_OP_MODE 0x0C
-#define AUTO_FT1_CFG_FAIL_INVALID_LINE 0x0D
-
-
-#ifdef _MSC_
-# pragma pack()
-#endif
-#endif /* _SDLA_CHDLC_H */
diff --git a/include/linux/sdla_ppp.h b/include/linux/sdla_ppp.h
deleted file mode 100644
index 6f3923179c29..000000000000
--- a/include/linux/sdla_ppp.h
+++ /dev/null
@@ -1,575 +0,0 @@
-/*****************************************************************************
-* sdla_ppp.h Sangoma PPP firmware API definitions.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-1997 Sangoma Technologies 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.
-* ============================================================================
-* Feb 24, 2000 Nenad Corbic v2.1.2
-* Jan 06, 1997 Gene Kozin v2.0
-* Apr 11, 1996 Gene Kozin Initial version.
-*****************************************************************************/
-#ifndef _SDLA_PPP_H
-#define _SDLA_PPP_H
-
-/*----------------------------------------------------------------------------
- * Notes:
- * ------
- * 1. All structures defined in this file are byte-alined.
- *
- * Compiler Platform
- * -------- --------
- * GNU C Linux
- */
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif /* PACKED */
-
-/* Adapter memory layout and important constants */
-#define PPP508_MB_VECT 0xE000 /* mailbox window vector */
-#define PPP508_MB_OFFS 0 /* mailbox offset */
-#define PPP508_FLG_OFFS 0x1000 /* status flags offset */
-#define PPP508_BUF_OFFS 0x1100 /* buffer info block offset */
-#define PPP514_MB_OFFS 0xE000 /* mailbox offset */
-#define PPP514_FLG_OFFS 0xF000 /* status flags offset */
-#define PPP514_BUF_OFFS 0xF100 /* buffer info block offset */
-
-#define PPP_MAX_DATA 1008 /* command block data buffer length */
-
-/****** Data Structures *****************************************************/
-
-/*----------------------------------------------------------------------------
- * PPP Command Block.
- */
-typedef struct ppp_cmd{
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* length of data buffer */
- unsigned char result PACKED; /* return code */
- unsigned char rsrv[11] PACKED; /* reserved for future use */
-} ppp_cmd_t;
-
-typedef struct cblock{
- unsigned char opp_flag PACKED;
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* length of data buffer */
- unsigned char result PACKED; /* return code */
- unsigned char rsrv[11] PACKED; /* reserved for future use */
-} cblock_t;
-
-typedef struct ppp_udp_pkt{
- ip_pkt_t ip_pkt PACKED;
- udp_pkt_t udp_pkt PACKED;
- wp_mgmt_t wp_mgmt PACKED;
- cblock_t cblock PACKED;
- unsigned char data[MAX_LGTH_UDP_MGNT_PKT] PACKED;
-} ppp_udp_pkt_t;
-
-typedef struct {
- unsigned char status PACKED;
- unsigned char data_avail PACKED;
- unsigned short real_length PACKED;
- unsigned short time_stamp PACKED;
- unsigned char data[1] PACKED;
-} trace_pkt_t;
-
-
-typedef struct {
- unsigned char opp_flag PACKED;
- unsigned char trace_type PACKED;
- unsigned short trace_length PACKED;
- unsigned short trace_data_ptr PACKED;
- unsigned short trace_time_stamp PACKED;
-} trace_element_t;
-
-/* 'command' field defines */
-#define PPP_READ_CODE_VERSION 0x10 /* configuration commands */
-#define PPP_SET_CONFIG 0x05
-#define PPP_READ_CONFIG 0x06
-#define PPP_SET_INTR_FLAGS 0x20
-#define PPP_READ_INTR_FLAGS 0x21
-#define PPP_SET_INBOUND_AUTH 0x30
-#define PPP_SET_OUTBOUND_AUTH 0x31
-#define PPP_GET_CONNECTION_INFO 0x32
-
-#define PPP_COMM_ENABLE 0x03 /* operational commands */
-#define PPP_COMM_DISABLE 0x04
-#define PPP_SEND_SIGN_FRAME 0x23
-#define PPP_READ_SIGN_RESPONSE 0x24
-#define PPP_DATALINE_MONITOR 0x33
-
-#define PPP_READ_STATISTICS 0x07 /* statistics commands */
-#define PPP_FLUSH_STATISTICS 0x08
-#define PPP_READ_ERROR_STATS 0x09
-#define PPP_FLUSH_ERROR_STATS 0x0A
-#define PPP_READ_PACKET_STATS 0x12
-#define PPP_FLUSH_PACKET_STATS 0x13
-#define PPP_READ_LCP_STATS 0x14
-#define PPP_FLUSH_LCP_STATS 0x15
-#define PPP_READ_LPBK_STATS 0x16
-#define PPP_FLUSH_LPBK_STATS 0x17
-#define PPP_READ_IPCP_STATS 0x18
-#define PPP_FLUSH_IPCP_STATS 0x19
-#define PPP_READ_IPXCP_STATS 0x1A
-#define PPP_FLUSH_IPXCP_STATS 0x1B
-#define PPP_READ_PAP_STATS 0x1C
-#define PPP_FLUSH_PAP_STATS 0x1D
-#define PPP_READ_CHAP_STATS 0x1E
-#define PPP_FLUSH_CHAP_STATS 0x1F
-
-/* 'result' field defines */
-#define PPPRES_OK 0x00 /* command executed successfully */
-#define PPPRES_INVALID_STATE 0x09 /* invalid command in this context */
-
-/*----------------------------------------------------------------------------
- * PPP Mailbox.
- * This structure is located at offset PPP???_MB_OFFS into PPP???_MB_VECT
- */
-typedef struct ppp_mbox
-{
- unsigned char flag PACKED; /* 00h: command execution flag */
- ppp_cmd_t cmd PACKED; /* 01h: command block */
- unsigned char data[1] PACKED; /* 10h: variable length data buffer */
-} ppp_mbox_t;
-
-/*----------------------------------------------------------------------------
- * PPP Status Flags.
- * This structure is located at offset PPP???_FLG_OFFS into
- * PPP???_MB_VECT.
- */
-typedef struct ppp_flags
-{
- unsigned char iflag PACKED; /* 00: interrupt flag */
- unsigned char imask PACKED; /* 01: interrupt mask */
- unsigned char resrv PACKED;
- unsigned char mstatus PACKED; /* 03: modem status */
- unsigned char lcp_state PACKED; /* 04: LCP state */
- unsigned char ppp_phase PACKED; /* 05: PPP phase */
- unsigned char ip_state PACKED; /* 06: IPCP state */
- unsigned char ipx_state PACKED; /* 07: IPXCP state */
- unsigned char pap_state PACKED; /* 08: PAP state */
- unsigned char chap_state PACKED; /* 09: CHAP state */
- unsigned short disc_cause PACKED; /* 0A: disconnection cause */
-} ppp_flags_t;
-
-/* 'iflag' defines */
-#define PPP_INTR_RXRDY 0x01 /* Rx ready */
-#define PPP_INTR_TXRDY 0x02 /* Tx ready */
-#define PPP_INTR_MODEM 0x04 /* modem status change (DCD, CTS) */
-#define PPP_INTR_CMD 0x08 /* interface command completed */
-#define PPP_INTR_DISC 0x10 /* data link disconnected */
-#define PPP_INTR_OPEN 0x20 /* data link open */
-#define PPP_INTR_DROP_DTR 0x40 /* DTR drop timeout expired */
-#define PPP_INTR_TIMER 0x80 /* timer interrupt */
-
-
-/* 'mstatus' defines */
-#define PPP_MDM_DCD 0x08 /* mdm_status: DCD */
-#define PPP_MDM_CTS 0x20 /* mdm_status: CTS */
-
-/* 'disc_cause' defines */
-#define PPP_LOCAL_TERMINATION 0x0001 /* Local Request by PPP termination phase */
-#define PPP_DCD_CTS_DROP 0x0002 /* DCD and/or CTS dropped. Link down */
-#define PPP_REMOTE_TERMINATION 0x0800 /* Remote Request by PPP termination phase */
-
-/* 'misc_config_bits' defines */
-#define DONT_RE_TX_ABORTED_I_FRAMES 0x01
-#define TX_FRM_BYTE_COUNT_STATS 0x02
-#define RX_FRM_BYTE_COUNT_STATS 0x04
-#define TIME_STAMP_IN_RX_FRAMES 0x08
-#define NON_STD_ADPTR_FREQ 0x10
-#define INTERFACE_LEVEL_RS232 0x20
-#define AUTO_LINK_RECOVERY 0x100
-#define DONT_TERMINATE_LNK_MAX_CONFIG 0x200
-
-/* 'authentication options' defines */
-#define NO_AUTHENTICATION 0x00
-#define INBOUND_AUTH 0x80
-#define PAP_AUTH 0x01
-#define CHAP_AUTH 0x02
-
-/* 'ip options' defines */
-#define L_AND_R_IP_NO_ASSIG 0x00
-#define L_IP_LOCAL_ASSIG 0x01
-#define L_IP_REMOTE_ASSIG 0x02
-#define R_IP_LOCAL_ASSIG 0x04
-#define R_IP_REMOTE_ASSIG 0x08
-#define ENABLE_IP 0x80
-
-/* 'ipx options' defines */
-#define ROUTING_PROT_DEFAULT 0x20
-#define ENABLE_IPX 0x80
-#define DISABLE_IPX 0x00
-
-/*----------------------------------------------------------------------------
- * PPP Buffer Info.
- * This structure is located at offset PPP508_BUF_OFFS into
- * PPP508_MB_VECT.
- */
-typedef struct ppp508_buf_info
-{
- unsigned short txb_num PACKED; /* 00: number of transmit buffers */
- unsigned long txb_ptr PACKED; /* 02: pointer to the buffer ctl. */
- unsigned long txb_nxt PACKED;
- unsigned char rsrv1[22] PACKED;
- unsigned short rxb_num PACKED; /* 20: number of receive buffers */
- unsigned long rxb_ptr PACKED; /* 22: pointer to the buffer ctl. */
- unsigned long rxb1_ptr PACKED; /* 26: pointer to the first buf.ctl. */
- unsigned long rxb_base PACKED; /* 2A: pointer to the buffer base */
- unsigned char rsrv2[2] PACKED;
- unsigned long rxb_end PACKED; /* 30: pointer to the buffer end */
-} ppp508_buf_info_t;
-
-/*----------------------------------------------------------------------------
- * Transmit/Receive Buffer Control Block.
- */
-typedef struct ppp_buf_ctl
-{
- unsigned char flag PACKED; /* 00: 'buffer ready' flag */
- unsigned short length PACKED; /* 01: length of data */
- unsigned char reserved1[1] PACKED; /* 03: */
- unsigned char proto PACKED; /* 04: protocol */
- unsigned short timestamp PACKED; /* 05: time stamp (Rx only) */
- unsigned char reserved2[5] PACKED; /* 07: */
- union
- {
- unsigned short o_p[2]; /* 1C: buffer offset & page (S502) */
- unsigned long ptr; /* 1C: buffer pointer (S508) */
- } buf PACKED;
-} ppp_buf_ctl_t;
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Configuration Block (passed to the PPP_SET_CONFIG command).
- */
-typedef struct ppp508_conf
-{
- unsigned long line_speed PACKED; /* 00: baud rate, bps */
- unsigned short txbuf_percent PACKED; /* 04: % of Tx buffer */
- unsigned short conf_flags PACKED; /* 06: configuration bits */
- unsigned short mtu_local PACKED; /* 08: local MTU */
- unsigned short mtu_remote PACKED; /* 0A: remote MTU */
- unsigned short restart_tmr PACKED; /* 0C: restart timer */
- unsigned short auth_rsrt_tmr PACKED; /* 0E: authentication timer */
- unsigned short auth_wait_tmr PACKED; /* 10: authentication timer */
- unsigned short mdm_fail_tmr PACKED; /* 12: modem failure timer */
- unsigned short dtr_drop_tmr PACKED; /* 14: DTR drop timer */
- unsigned short connect_tmout PACKED; /* 16: connection timeout */
- unsigned short conf_retry PACKED; /* 18: max. retry */
- unsigned short term_retry PACKED; /* 1A: max. retry */
- unsigned short fail_retry PACKED; /* 1C: max. retry */
- unsigned short auth_retry PACKED; /* 1E: max. retry */
- unsigned char auth_options PACKED; /* 20: authentication opt. */
- unsigned char ip_options PACKED; /* 21: IP options */
- unsigned long ip_local PACKED; /* 22: local IP address */
- unsigned long ip_remote PACKED; /* 26: remote IP address */
- unsigned char ipx_options PACKED; /* 2A: IPX options */
- unsigned char ipx_netno[4] PACKED; /* 2B: IPX net number */
- unsigned char ipx_local[6] PACKED; /* 2F: local IPX node number*/
- unsigned char ipx_remote[6] PACKED; /* 35: remote IPX node num.*/
- unsigned char ipx_router[48] PACKED; /* 3B: IPX router name*/
- unsigned long alt_cpu_clock PACKED; /* 6B: */
-} ppp508_conf_t;
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Read Connection Information Block
- * Returned by the PPP_GET_CONNECTION_INFO command
- */
-typedef struct ppp508_connect_info
-{
- unsigned short mru PACKED; /* 00-01 Remote Max Rec' Unit */
- unsigned char ip_options PACKED; /* 02: Negotiated ip options */
- unsigned long ip_local PACKED; /* 03-06: local IP address */
- unsigned long ip_remote PACKED; /* 07-0A: remote IP address */
- unsigned char ipx_options PACKED; /* 0B: Negotiated ipx options */
- unsigned char ipx_netno[4] PACKED; /* 0C-0F: IPX net number */
- unsigned char ipx_local[6] PACKED; /* 10-1F: local IPX node # */
- unsigned char ipx_remote[6] PACKED; /* 16-1B: remote IPX node # */
- unsigned char ipx_router[48] PACKED; /* 1C-4B: IPX router name */
- unsigned char auth_status PACKED; /* 4C: Authentication Status */
- unsigned char inbd_auth_peerID[1] PACKED; /* 4D: variable length inbound authenticated peer ID */
-} ppp508_connect_info_t;
-
-/* 'line_speed' field */
-#define PPP_BITRATE_1200 0x01
-#define PPP_BITRATE_2400 0x02
-#define PPP_BITRATE_4800 0x03
-#define PPP_BITRATE_9600 0x04
-#define PPP_BITRATE_19200 0x05
-#define PPP_BITRATE_38400 0x06
-#define PPP_BITRATE_45000 0x07
-#define PPP_BITRATE_56000 0x08
-#define PPP_BITRATE_64000 0x09
-#define PPP_BITRATE_74000 0x0A
-#define PPP_BITRATE_112000 0x0B
-#define PPP_BITRATE_128000 0x0C
-#define PPP_BITRATE_156000 0x0D
-
-/* Defines for the 'conf_flags' field */
-#define PPP_IGNORE_TX_ABORT 0x01 /* don't re-transmit aborted frames */
-#define PPP_ENABLE_TX_STATS 0x02 /* enable Tx statistics */
-#define PPP_ENABLE_RX_STATS 0x04 /* enable Rx statistics */
-#define PPP_ENABLE_TIMESTAMP 0x08 /* enable timestamp */
-
-/* 'ip_options' defines */
-#define PPP_LOCAL_IP_LOCAL 0x01
-#define PPP_LOCAL_IP_REMOTE 0x02
-#define PPP_REMOTE_IP_LOCAL 0x04
-#define PPP_REMOTE_IP_REMOTE 0x08
-
-/* 'ipx_options' defines */
-#define PPP_REMOTE_IPX_NETNO 0x01
-#define PPP_REMOTE_IPX_LOCAL 0x02
-#define PPP_REMOTE_IPX_REMOTE 0x04
-#define PPP_IPX_ROUTE_RIP_SAP 0x08
-#define PPP_IPX_ROUTE_NLSP 0x10
-#define PPP_IPX_ROUTE_DEFAULT 0x20
-#define PPP_IPX_CONF_COMPLETE 0x40
-#define PPP_IPX_ENABLE 0x80
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Configuration Block (returned by the PPP_READ_CONFIG command).
- */
-typedef struct ppp508_get_conf
-{
- unsigned long bps PACKED; /* 00: baud rate, bps */
- ppp508_conf_t conf PACKED; /* 04: requested config. */
- unsigned short txb_num PACKED; /* 6F: number of Tx buffers */
- unsigned short rxb_num PACKED; /* 71: number of Rx buffers */
-} ppp508_get_conf_t;
-
-/*----------------------------------------------------------------------------
- * S508 Operational Statistics (returned by the PPP_READ_STATISTIC command).
- */
-typedef struct ppp508_stats
-{
- unsigned short reserved1 PACKED; /* 00: */
- unsigned short rx_bad_len PACKED; /* 02: */
- unsigned short reserved2 PACKED; /* 04: */
- unsigned long tx_frames PACKED; /* 06: */
- unsigned long tx_bytes PACKED; /* 0A: */
- unsigned long rx_frames PACKED; /* 0E: */
- unsigned long rx_bytes PACKED; /* 12: */
-} ppp508_stats_t;
-
-/*----------------------------------------------------------------------------
- * Adapter Error Statistics (returned by the PPP_READ_ERROR_STATS command).
- */
-typedef struct ppp_err_stats
-{
- unsigned char rx_overrun PACKED; /* 00: Rx overrun errors */
- unsigned char rx_bad_crc PACKED; /* 01: Rx CRC errors */
- unsigned char rx_abort PACKED; /* 02: Rx aborted frames */
- unsigned char rx_lost PACKED; /* 03: Rx frames lost */
- unsigned char tx_abort PACKED; /* 04: Tx aborted frames */
- unsigned char tx_underrun PACKED; /* 05: Tx underrun errors */
- unsigned char tx_missed_intr PACKED; /* 06: Tx underruns missed */
- unsigned char reserved PACKED; /* 07: Tx underruns missed */
- unsigned char dcd_trans PACKED; /* 08: DCD transitions */
- unsigned char cts_trans PACKED; /* 09: CTS transitions */
-} ppp_err_stats_t;
-
-/*----------------------------------------------------------------------------
- * Packet Statistics (returned by the PPP_READ_PACKET_STATS command).
- */
-typedef struct ppp_pkt_stats
-{
- unsigned short rx_bad_header PACKED; /* 00: */
- unsigned short rx_prot_unknwn PACKED; /* 02: */
- unsigned short rx_too_large PACKED; /* 04: */
- unsigned short rx_lcp PACKED; /* 06: */
- unsigned short tx_lcp PACKED; /* 08: */
- unsigned short rx_ipcp PACKED; /* 0A: */
- unsigned short tx_ipcp PACKED; /* 0C: */
- unsigned short rx_ipxcp PACKED; /* 0E: */
- unsigned short tx_ipxcp PACKED; /* 10: */
- unsigned short rx_pap PACKED; /* 12: */
- unsigned short tx_pap PACKED; /* 14: */
- unsigned short rx_chap PACKED; /* 16: */
- unsigned short tx_chap PACKED; /* 18: */
- unsigned short rx_lqr PACKED; /* 1A: */
- unsigned short tx_lqr PACKED; /* 1C: */
- unsigned short rx_ip PACKED; /* 1E: */
- unsigned short tx_ip PACKED; /* 20: */
- unsigned short rx_ipx PACKED; /* 22: */
- unsigned short tx_ipx PACKED; /* 24: */
-} ppp_pkt_stats_t;
-
-/*----------------------------------------------------------------------------
- * LCP Statistics (returned by the PPP_READ_LCP_STATS command).
- */
-typedef struct ppp_lcp_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown LCP type */
- unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
- unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
- unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
- unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
- unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
- unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
- unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
- unsigned short rx_proto_rej PACKED; /* 10: Protocol-Reject */
- unsigned short rx_echo_rqst PACKED; /* 12: Echo-Request */
- unsigned short rx_echo_reply PACKED; /* 14: Echo-Reply */
- unsigned short rx_disc_rqst PACKED; /* 16: Discard-Request */
- unsigned short tx_conf_rqst PACKED; /* 18: Configure-Request */
- unsigned short tx_conf_ack PACKED; /* 1A: Configure-Ack */
- unsigned short tx_conf_nak PACKED; /* 1C: Configure-Nak */
- unsigned short tx_conf_rej PACKED; /* 1E: Configure-Reject */
- unsigned short tx_term_rqst PACKED; /* 20: Terminate-Request */
- unsigned short tx_term_ack PACKED; /* 22: Terminate-Ack */
- unsigned short tx_code_rej PACKED; /* 24: Code-Reject */
- unsigned short tx_proto_rej PACKED; /* 26: Protocol-Reject */
- unsigned short tx_echo_rqst PACKED; /* 28: Echo-Request */
- unsigned short tx_echo_reply PACKED; /* 2A: Echo-Reply */
- unsigned short tx_disc_rqst PACKED; /* 2E: Discard-Request */
- unsigned short rx_too_large PACKED; /* 30: packets too large */
- unsigned short rx_ack_inval PACKED; /* 32: invalid Conf-Ack */
- unsigned short rx_rej_inval PACKED; /* 34: invalid Conf-Reject */
- unsigned short rx_rej_badid PACKED; /* 36: Conf-Reject w/bad ID */
-} ppp_lcp_stats_t;
-
-/*----------------------------------------------------------------------------
- * Loopback Error Statistics (returned by the PPP_READ_LPBK_STATS command).
- */
-typedef struct ppp_lpbk_stats
-{
- unsigned short conf_magic PACKED; /* 00: */
- unsigned short loc_echo_rqst PACKED; /* 02: */
- unsigned short rem_echo_rqst PACKED; /* 04: */
- unsigned short loc_echo_reply PACKED; /* 06: */
- unsigned short rem_echo_reply PACKED; /* 08: */
- unsigned short loc_disc_rqst PACKED; /* 0A: */
- unsigned short rem_disc_rqst PACKED; /* 0C: */
- unsigned short echo_tx_collsn PACKED; /* 0E: */
- unsigned short echo_rx_collsn PACKED; /* 10: */
-} ppp_lpbk_stats_t;
-
-/*----------------------------------------------------------------------------
- * Protocol Statistics (returned by the PPP_READ_IPCP_STATS and
- * PPP_READ_IPXCP_STATS commands).
- */
-typedef struct ppp_prot_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown type */
- unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
- unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
- unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
- unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
- unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
- unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
- unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
- unsigned short reserved PACKED; /* 10: */
- unsigned short tx_conf_rqst PACKED; /* 12: Configure-Request */
- unsigned short tx_conf_ack PACKED; /* 14: Configure-Ack */
- unsigned short tx_conf_nak PACKED; /* 16: Configure-Nak */
- unsigned short tx_conf_rej PACKED; /* 18: Configure-Reject */
- unsigned short tx_term_rqst PACKED; /* 1A: Terminate-Request */
- unsigned short tx_term_ack PACKED; /* 1C: Terminate-Ack */
- unsigned short tx_code_rej PACKED; /* 1E: Code-Reject */
- unsigned short rx_too_large PACKED; /* 20: packets too large */
- unsigned short rx_ack_inval PACKED; /* 22: invalid Conf-Ack */
- unsigned short rx_rej_inval PACKED; /* 24: invalid Conf-Reject */
- unsigned short rx_rej_badid PACKED; /* 26: Conf-Reject w/bad ID */
-} ppp_prot_stats_t;
-
-/*----------------------------------------------------------------------------
- * PAP Statistics (returned by the PPP_READ_PAP_STATS command).
- */
-typedef struct ppp_pap_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown type */
- unsigned short rx_auth_rqst PACKED; /* 02: Authenticate-Request */
- unsigned short rx_auth_ack PACKED; /* 04: Authenticate-Ack */
- unsigned short rx_auth_nak PACKED; /* 06: Authenticate-Nak */
- unsigned short reserved PACKED; /* 08: */
- unsigned short tx_auth_rqst PACKED; /* 0A: Authenticate-Request */
- unsigned short tx_auth_ack PACKED; /* 0C: Authenticate-Ack */
- unsigned short tx_auth_nak PACKED; /* 0E: Authenticate-Nak */
- unsigned short rx_too_large PACKED; /* 10: packets too large */
- unsigned short rx_bad_peerid PACKED; /* 12: invalid peer ID */
- unsigned short rx_bad_passwd PACKED; /* 14: invalid password */
-} ppp_pap_stats_t;
-
-/*----------------------------------------------------------------------------
- * CHAP Statistics (returned by the PPP_READ_CHAP_STATS command).
- */
-typedef struct ppp_chap_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown type */
- unsigned short rx_challenge PACKED; /* 02: Authenticate-Request */
- unsigned short rx_response PACKED; /* 04: Authenticate-Ack */
- unsigned short rx_success PACKED; /* 06: Authenticate-Nak */
- unsigned short rx_failure PACKED; /* 08: Authenticate-Nak */
- unsigned short reserved PACKED; /* 0A: */
- unsigned short tx_challenge PACKED; /* 0C: Authenticate-Request */
- unsigned short tx_response PACKED; /* 0E: Authenticate-Ack */
- unsigned short tx_success PACKED; /* 10: Authenticate-Nak */
- unsigned short tx_failure PACKED; /* 12: Authenticate-Nak */
- unsigned short rx_too_large PACKED; /* 14: packets too large */
- unsigned short rx_bad_peerid PACKED; /* 16: invalid peer ID */
- unsigned short rx_bad_passwd PACKED; /* 18: invalid password */
- unsigned short rx_bad_md5 PACKED; /* 1A: invalid MD5 format */
- unsigned short rx_bad_resp PACKED; /* 1C: invalid response */
-} ppp_chap_stats_t;
-
-/*----------------------------------------------------------------------------
- * Connection Information (returned by the PPP_GET_CONNECTION_INFO command).
- */
-typedef struct ppp_conn_info
-{
- unsigned short remote_mru PACKED; /* 00: */
- unsigned char ip_options PACKED; /* 02: */
- unsigned char ip_local[4] PACKED; /* 03: */
- unsigned char ip_remote[4] PACKED; /* 07: */
- unsigned char ipx_options PACKED; /* 0B: */
- unsigned char ipx_network[4] PACKED; /* 0C: */
- unsigned char ipx_local[6] PACKED; /* 10: */
- unsigned char ipx_remote[6] PACKED; /* 16: */
- unsigned char ipx_router[48] PACKED; /* 1C: */
- unsigned char auth_status PACKED; /* 4C: */
- unsigned char peer_id[0] PACKED; /* 4D: */
-} ppp_conn_info_t;
-
-/* Data structure for SET_TRIGGER_INTR command
- */
-
-typedef struct ppp_intr_info{
- unsigned char i_enable PACKED; /* 0 Interrupt enable bits */
- unsigned char irq PACKED; /* 1 Irq number */
- unsigned short timer_len PACKED; /* 2 Timer delay */
-} ppp_intr_info_t;
-
-
-#define FT1_MONITOR_STATUS_CTRL 0x80
-#define SET_FT1_MODE 0x81
-
-
-
-/* Special UDP drivers management commands */
-#define PPIPE_ENABLE_TRACING 0x20
-#define PPIPE_DISABLE_TRACING 0x21
-#define PPIPE_GET_TRACE_INFO 0x22
-#define PPIPE_GET_IBA_DATA 0x23
-#define PPIPE_KILL_BOARD 0x24
-#define PPIPE_FT1_READ_STATUS 0x25
-#define PPIPE_DRIVER_STAT_IFSEND 0x26
-#define PPIPE_DRIVER_STAT_INTR 0x27
-#define PPIPE_DRIVER_STAT_GEN 0x28
-#define PPIPE_FLUSH_DRIVER_STATS 0x29
-#define PPIPE_ROUTER_UP_TIME 0x30
-
-#define DISABLE_TRACING 0x00
-#define TRACE_SIGNALLING_FRAMES 0x01
-#define TRACE_DATA_FRAMES 0x02
-
-
-
-#ifdef _MSC_
-# pragma pack()
-#endif
-#endif /* _SDLA_PPP_H */
diff --git a/include/linux/sdla_x25.h b/include/linux/sdla_x25.h
deleted file mode 100644
index 57db980e27ad..000000000000
--- a/include/linux/sdla_x25.h
+++ /dev/null
@@ -1,772 +0,0 @@
-/*****************************************************************************
-* sdla_x25.h Sangoma X.25 firmware API definitions.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Feb 28, 2000 Nenad Corbic Updated for socket based x25api
-* Dec 13, 1996 Gene Kozin Initial version
-*****************************************************************************/
-#ifndef _SDLA_X25_H
-#define _SDLA_X25_H
-
-/*----------------------------------------------------------------------------
- * Notes:
- * ------
- * 1. All structures defined in this file are byte-alined.
- * Compiler Platform
- * -------- --------
- * GNU C Linux
- *
- */
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif /* PACKED */
-
-/****** CONSTANTS DEFINITIONS ***********************************************/
-
-#define X25_MAX_CHAN 255 /* max number of open X.25 circuits */
-#define X25_MAX_DATA 1024 /* max length of X.25 data buffer */
-/*
- * X.25 shared memory layout.
- */
-#define X25_MBOX_OFFS 0x16B0 /* general mailbox block */
-#define X25_RXMBOX_OFFS 0x1AD0 /* receive mailbox */
-#define X25_STATUS_OFFS 0x1EF0 /* X.25 status structure */
-#define X25_MB_VECTOR 0xE000 /* S514 mailbox window vecotr */
-#define X25_MISC_HDLC_BITS 0x1F00 /*X.25 miscallaneous HDLC bits */
-
-/* code levels */
-#define HDLC_LEVEL 0x01
-#define X25_LEVEL 0x02
-#define X25_AND_HDLC_LEVEL 0x03
-#define DO_HDLC_LEVEL_ERROR_CHECKING 0x04
-
-/****** DATA STRUCTURES *****************************************************/
-
-/*----------------------------------------------------------------------------
- * X.25 Command Block.
- */
-typedef struct X25Cmd
-{
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* transfer data length */
- unsigned char result PACKED; /* return code */
- unsigned char pf PACKED; /* P/F bit */
- unsigned short lcn PACKED; /* logical channel */
- unsigned char qdm PACKED; /* Q/D/M bits */
- unsigned char cause PACKED; /* cause field */
- unsigned char diagn PACKED; /* diagnostics */
- unsigned char pktType PACKED; /* packet type */
- unsigned char resrv[4] PACKED; /* reserved */
-} TX25Cmd;
-
-/*
- * Defines for the 'command' field.
- */
-/*----- General commands --------------*/
-#define X25_SET_GLOBAL_VARS 0x0B /* set global variables */
-#define X25_READ_MODEM_STATUS 0x0C /* read modem status */
-#define X25_READ_CODE_VERSION 0x15 /* read firmware version number */
-#define X25_TRACE_CONFIGURE 0x14 /* configure trace facility */
-#define X25_READ_TRACE_DATA 0x16 /* read trace data */
-#define X25_SET_INTERRUPT_MODE 0x17 /* set interrupt generation mode */
-#define X25_READ_INTERRUPT_MODE 0x18 /* read interrupt generation mode */
-/*----- HDLC-level commands -----------*/
-#define X25_HDLC_LINK_CONFIGURE 0x01 /* configure HDLC link level */
-#define X25_HDLC_LINK_OPEN 0x02 /* open HDLC link */
-#define X25_HDLC_LINK_CLOSE 0x03 /* close HDLC link */
-#define X25_HDLC_LINK_SETUP 0x04 /* set up HDLC link */
-#define X25_HDLC_LINK_DISC 0x05 /* disconnect DHLC link */
-#define X25_HDLC_LINK_STATUS 0x06 /* read DHLC link status */
-#define X25_HDLC_READ_STATS 0x07 /* read operational statistics */
-#define X25_HDLC_FLUSH_STATS 0x08 /* flush operational statistics */
-#define X25_HDLC_READ_COMM_ERR 0x09 /* read error statistics */
-#define X25_HDLC_FLUSH_COMM_ERR 0x0A /* flush error statistics */
-#define X25_HDLC_FLUSH_BUFFERS 0x0D /* flush HDLC-level data buffers */
-#define X25_HDLC_SPRVS_CNT_STAT 0x0F /* read surervisory count status */
-#define X25_HDLC_SEND_UI_FRAME 0x10 /* send unnumbered information frame */
-#define X25_HDLC_WRITE 0x11 /* send HDLC information frame */
-#define X25_HDLC_READ 0x21 /* read HDLC information frame */
-#define X25_HDLC_READ_CONFIG 0x12 /* read HDLC configuration */
-#define X25_HDLC_SET_CONFIG 0x13 /* set HDLC configuration */
-#define SET_PROTOCOL_LEVEL 0x1F /* set protocol level */
-/*----- X.25-level commands -----------*/
-#define X25_READ 0x22 /* read X.25 packet */
-#define X25_WRITE 0x23 /* send X.25 packet */
-#define X25_PLACE_CALL 0x30 /* place a call on SVC */
-#define X25_ACCEPT_CALL 0x31 /* accept incomming call */
-#define X25_CLEAR_CALL 0x32 /* clear call */
-#define X25_CLEAR_CONFRM 0x33 /* send clear confirmation packet */
-#define X25_RESET 0x34 /* send reset request packet */
-#define X25_RESET_CONFRM 0x35 /* send reset confirmation packet */
-#define X25_RESTART 0x36 /* send restart request packet */
-#define X25_RESTART_CONFRM 0x37 /* send restart confirmation packet */
-#define X25_INTERRUPT 0x38 /* send interrupt request packet */
-#define X25_INTERRUPT_CONFRM 0x39 /* send interrupt confirmation pkt */
-#define X25_REGISTRATION_RQST 0x3A /* send registration request packet */
-#define X25_REGISTRATION_CONFRM 0x3B /* send registration confirmation */
-#define X25_IS_DATA_AVAILABLE 0x40 /* querry receive queue */
-#define X25_INCOMMING_CALL_CTL 0x41 /* select incomming call options */
-#define X25_CONFIGURE_PVC 0x42 /* configure PVC */
-#define X25_GET_ACTIVE_CHANNELS 0x43 /* get a list of active circuits */
-#define X25_READ_CHANNEL_CONFIG 0x44 /* read virt. circuit configuration */
-#define X25_FLUSH_DATA_BUFFERS 0x45 /* flush X.25-level data buffers */
-#define X25_READ_HISTORY_TABLE 0x46 /* read asynchronous event log */
-#define X25_HISTORY_TABLE_CTL 0x47 /* control asynchronous event log */
-#define X25_GET_TX_D_BIT_STATUS 0x48 /* is packet with D-bit acknowleged */
-#define X25_READ_STATISTICS 0x49 /* read X.25-level statistics */
-#define X25_FLUSH_STATISTICS 0x4A /* flush X.25-level statistics */
-#define X25_READ_CONFIGURATION 0x50 /* read HDLC & X.25 configuration */
-#define X25_SET_CONFIGURATION 0x51 /* set HDLC & X.25 configuration */
-
-/*
- * Defines for the 'result' field.
- */
-/*----- General results ---------------*/
-#define X25RES_OK 0x00
-#define X25RES_ERROR 0x01
-#define X25RES_LINK_NOT_IN_ABM 0x02 /* link is not in ABM mode */
-#define X25RES_LINK_CLOSED 0x03
-#define X25RES_INVAL_LENGTH 0x04
-#define X25RES_INVAL_CMD 0x05
-#define X25RES_UNNUMBERED_FRAME 0x06 /* unnunbered frame received */
-#define X25RES_FRM_REJECT_MODE 0x07 /* link is in Frame Reject mode */
-#define X25RES_MODEM_FAILURE 0x08 /* DCD and/or CTS dropped */
-#define X25RES_N2_RETRY_LIMIT 0x09 /* N2 retry limit has been exceeded */
-#define X25RES_INVAL_LCN 0x30 /* invalid logical channel number */
-#define X25RES_INVAL_STATE 0x31 /* channel is not in data xfer mode */
-#define X25RES_INVAL_DATA_LEN 0x32 /* invalid data length */
-#define X25RES_NOT_READY 0x33 /* no data available / buffers full */
-#define X25RES_NETWORK_DOWN 0x34
-#define X25RES_CHANNEL_IN_USE 0x35 /* there is data queued on this LCN */
-#define X25RES_REGST_NOT_SUPPRT 0x36 /* registration not supported */
-#define X25RES_INVAL_FORMAT 0x37 /* invalid packet format */
-#define X25RES_D_BIT_NOT_SUPPRT 0x38 /* D-bit pragmatics not supported */
-#define X25RES_FACIL_NOT_SUPPRT 0x39 /* Call facility not supported */
-#define X25RES_INVAL_CALL_ARG 0x3A /* errorneous call arguments */
-#define X25RES_INVAL_CALL_DATA 0x3B /* errorneous call user data */
-#define X25RES_ASYNC_PACKET 0x40 /* asynchronous packet received */
-#define X25RES_PROTO_VIOLATION 0x41 /* protocol violation occurred */
-#define X25RES_PKT_TIMEOUT 0x42 /* X.25 packet time out */
-#define X25RES_PKT_RETRY_LIMIT 0x43 /* X.25 packet retry limit exceeded */
-/*----- Command-dependent results -----*/
-#define X25RES_LINK_DISC 0x00 /* HDLC_LINK_STATUS */
-#define X25RES_LINK_IN_ABM 0x01 /* HDLC_LINK_STATUS */
-#define X25RES_NO_DATA 0x01 /* HDLC_READ/READ_TRACE_DATA*/
-#define X25RES_TRACE_INACTIVE 0x02 /* READ_TRACE_DATA */
-#define X25RES_LINK_IS_OPEN 0x01 /* HDLC_LINK_OPEN */
-#define X25RES_LINK_IS_DISC 0x02 /* HDLC_LINK_DISC */
-#define X25RES_LINK_IS_CLOSED 0x03 /* HDLC_LINK_CLOSE */
-#define X25RES_INVAL_PARAM 0x31 /* INCOMMING_CALL_CTL */
-#define X25RES_INVAL_CONFIG 0x35 /* REGISTR_RQST/CONFRM */
-
-/*
- * Defines for the 'qdm_bits' field.
- */
-#define X25CMD_Q_BIT_MASK 0x04
-#define X25CMD_D_BIT_MASK 0x02
-#define X25CMD_M_BIT_MASK 0x01
-
-/*
- * Defines for the 'pkt_type' field.
- */
-/*----- Asynchronous events ------*/
-#define ASE_CLEAR_RQST 0x02
-#define ASE_RESET_RQST 0x04
-#define ASE_RESTART_RQST 0x08
-#define ASE_INTERRUPT 0x10
-#define ASE_DTE_REGISTR_RQST 0x20
-#define ASE_CALL_RQST 0x30
-#define ASE_CALL_ACCEPTED 0x31
-#define ASE_CLEAR_CONFRM 0x32
-#define ASE_RESET_CONFRM 0x33
-#define ASE_RESTART_CONFRM 0x34
-#define ASE_INTERRUPT_CONFRM 0x35
-#define ASE_DCE_REGISTR_CONFRM 0x36
-#define ASE_DIAGNOSTIC 0x37
-#define ASE_CALL_AUTO_CLEAR 0x38
-#define AUTO_RESPONSE_FLAG 0x80
-/*----- Time-Out events ----------*/
-#define TOE_RESTART_RQST 0x03
-#define TOE_CALL_RQST 0x05
-#define TOE_CLEAR_RQST 0x08
-#define TOE_RESET_RQST 0x0A
-/*----- Protocol Violation events */
-#define PVE_CLEAR_RQST 0x32
-#define PVE_RESET_RQST 0x33
-#define PVE_RESTART_RQST 0x34
-#define PVE_DIAGNOSTIC 0x37
-
-#define INTR_ON_RX_FRAME 0x01
-#define INTR_ON_TX_FRAME 0x02
-#define INTR_ON_MODEM_STATUS_CHANGE 0x04
-#define INTR_ON_COMMAND_COMPLETE 0x08
-#define INTR_ON_X25_ASY_TRANSACTION 0x10
-#define INTR_ON_TIMER 0x40
-#define DIRECT_RX_INTR_USAGE 0x80
-
-#define NO_INTR_PENDING 0x00
-#define RX_INTR_PENDING 0x01
-#define TX_INTR_PENDING 0x02
-#define MODEM_INTR_PENDING 0x04
-#define COMMAND_COMPLETE_INTR_PENDING 0x08
-#define X25_ASY_TRANS_INTR_PENDING 0x10
-#define TIMER_INTR_PENDING 0x40
-
-/*----------------------------------------------------------------------------
- * X.25 Mailbox.
- * This structure is located at offsets X25_MBOX_OFFS and X25_RXMBOX_OFFS
- * into shared memory window.
- */
-typedef struct X25Mbox
-{
- unsigned char opflag PACKED; /* 00h: execution flag */
- TX25Cmd cmd PACKED; /* 01h: command block */
- unsigned char data[1] PACKED; /* 10h: data buffer */
-} TX25Mbox;
-
-/*----------------------------------------------------------------------------
- * X.25 Time Stamp Structure.
- */
-typedef struct X25TimeStamp
-{
- unsigned char month PACKED;
- unsigned char date PACKED;
- unsigned char sec PACKED;
- unsigned char min PACKED;
- unsigned char hour PACKED;
-} TX25TimeStamp;
-
-/*----------------------------------------------------------------------------
- * X.25 Status Block.
- * This structure is located at offset X25_STATUS_OFF into shared memory
- * window.
- */
-typedef struct X25Status
-{
- unsigned short pvc_map PACKED; /* 00h: PVC map */
- unsigned short icc_map PACKED; /* 02h: Incomming Chan. map */
- unsigned short twc_map PACKED; /* 04h: Two-way Cnan. map */
- unsigned short ogc_map PACKED; /* 06h: Outgoing Chan. map */
- TX25TimeStamp tstamp PACKED; /* 08h: timestamp (BCD) */
- unsigned char iflags PACKED; /* 0Dh: interrupt flags */
- unsigned char imask PACKED; /* 0Eh: interrupt mask */
- unsigned char resrv PACKED; /* 0Eh: */
- unsigned char gflags PACKED; /* 10h: misc. HDLC/X25 flags */
- unsigned char cflags[X25_MAX_CHAN] PACKED; /* channel status bytes */
-} TX25Status;
-
-/*
- * Bitmasks for the 'iflags' field.
- */
-#define X25_RX_INTR 0x01 /* receive interrupt */
-#define X25_TX_INTR 0x02 /* transmit interrupt */
-#define X25_MODEM_INTR 0x04 /* modem status interrupt (CTS/DCD) */
-#define X25_EVENT_INTR 0x10 /* asyncronous event encountered */
-#define X25_CMD_INTR 0x08 /* interface command complete */
-
-/*
- * Bitmasks for the 'gflags' field.
- */
-#define X25_HDLC_ABM 0x01 /* HDLC is in ABM mode */
-#define X25_RX_READY 0x02 /* X.25 data available */
-#define X25_TRACE_READY 0x08 /* trace data available */
-#define X25_EVENT_IND 0x20 /* asynchronous event indicator */
-#define X25_TX_READY 0x40 /* space is available in Tx buf.*/
-
-/*
- * Bitmasks for the 'cflags' field.
- */
-#define X25_XFER_MODE 0x80 /* channel is in data transfer mode */
-#define X25_TXWIN_OPEN 0x40 /* transmit window open */
-#define X25_RXBUF_MASK 0x3F /* number of data buffers available */
-
-/*****************************************************************************
- * Following definitions structurize contents of the TX25Mbox.data field for
- * different X.25 interface commands.
- ****************************************************************************/
-
-/* ---------------------------------------------------------------------------
- * X25_SET_GLOBAL_VARS Command.
- */
-typedef struct X25GlobalVars
-{
- unsigned char resrv PACKED; /* 00h: reserved */
- unsigned char dtrCtl PACKED; /* 01h: DTR control code */
- unsigned char resErr PACKED; /* 01h: '1' - reset modem error */
-} TX25GlobalVars;
-
-/*
- * Defines for the 'dtrCtl' field.
- */
-#define X25_RAISE_DTR 0x01
-#define X25_DROP_DTR 0x02
-
-/* ---------------------------------------------------------------------------
- * X25_READ_MODEM_STATUS Command.
- */
-typedef struct X25ModemStatus
-{
- unsigned char status PACKED; /* 00h: modem status */
-} TX25ModemStatus;
-
-/*
- * Defines for the 'status' field.
- */
-#define X25_CTS_MASK 0x20
-#define X25_DCD_MASK 0x08
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_LINK_STATUS Command.
- */
-typedef struct X25LinkStatus
-{
- unsigned char txQueued PACKED; /* 00h: queued Tx I-frames*/
- unsigned char rxQueued PACKED; /* 01h: queued Rx I-frames*/
- unsigned char station PACKED; /* 02h: DTE/DCE config. */
- unsigned char reserved PACKED; /* 03h: reserved */
- unsigned char sfTally PACKED; /* 04h: supervisory frame tally */
-} TX25LinkStatus;
-
-/*
- * Defines for the 'station' field.
- */
-#define X25_STATION_DTE 0x01 /* station configured as DTE */
-#define X25_STATION_DCE 0x02 /* station configured as DCE */
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_READ_STATS Command.
- */
-typedef struct HdlcStats
-{ /* a number of ... */
- unsigned short rxIFrames PACKED; /* 00h: ready Rx I-frames */
- unsigned short rxNoseq PACKED; /* 02h: frms out-of-sequence */
- unsigned short rxNodata PACKED; /* 04h: I-frms without data */
- unsigned short rxDiscarded PACKED; /* 06h: discarded frames */
- unsigned short rxTooLong PACKED; /* 08h: frames too long */
- unsigned short rxBadAddr PACKED; /* 0Ah: frms with inval.addr*/
- unsigned short txAcked PACKED; /* 0Ch: acknowledged I-frms */
- unsigned short txRetransm PACKED; /* 0Eh: re-transmit. I-frms */
- unsigned short t1Timeout PACKED; /* 10h: T1 timeouts */
- unsigned short rxSABM PACKED; /* 12h: received SABM frames */
- unsigned short rxDISC PACKED; /* 14h: received DISC frames */
- unsigned short rxDM PACKED; /* 16h: received DM frames */
- unsigned short rxFRMR PACKED; /* 18h: FRMR frames received */
- unsigned short txSABM PACKED; /* 1Ah: transm. SABM frames*/
- unsigned short txDISC PACKED; /* 1Ch: transm. DISC frames*/
- unsigned short txDM PACKED; /* 1Eh: transm. DM frames */
- unsigned short txFRMR PACKED; /* 20h: transm. FRMR frames*/
-} THdlcStats;
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_READ_COMM_ERR Command.
- */
-typedef struct HdlcCommErr
-{ /* a number of ... */
- unsigned char rxOverrun PACKED; /* 00h: Rx overrun errors */
- unsigned char rxBadCrc PACKED; /* 01h: Rx CRC errors */
- unsigned char rxAborted PACKED; /* 02h: Rx aborted frames */
- unsigned char rxDropped PACKED; /* 03h: frames lost */
- unsigned char txAborted PACKED; /* 04h: Tx aborted frames */
- unsigned char txUnderrun PACKED; /* 05h: Tx underrun errors */
- unsigned char txMissIntr PACKED; /* 06h: missed underrun ints */
- unsigned char reserved PACKED; /* 07h: reserved */
- unsigned char droppedDCD PACKED; /* 08h: times DCD dropped */
- unsigned char droppedCTS PACKED; /* 09h: times CTS dropped */
-} THdlcCommErr;
-
-/* ---------------------------------------------------------------------------
- * X25_SET_CONFIGURATION & X25_READ_CONFIGURATION Commands.
- */
-typedef struct X25Config
-{
-unsigned char baudRate PACKED; /* 00h: */
- unsigned char t1 PACKED; /* 01h: */
- unsigned char t2 PACKED; /* 02h: */
- unsigned char n2 PACKED; /* 03h: */
- unsigned short hdlcMTU PACKED; /* 04h: */
- unsigned char hdlcWindow PACKED; /* 06h: */
- unsigned char t4 PACKED; /* 07h: */
- unsigned char autoModem PACKED; /* 08h: */
- unsigned char autoHdlc PACKED; /* 09h: */
- unsigned char hdlcOptions PACKED; /* 0Ah: */
- unsigned char station PACKED; /* 0Bh: */
- unsigned char pktWindow PACKED; /* 0Ch: */
- unsigned short defPktSize PACKED; /* 0Dh: */
- unsigned short pktMTU PACKED; /* 0Fh: */
- unsigned short loPVC PACKED; /* 11h: */
- unsigned short hiPVC PACKED; /* 13h: */
- unsigned short loIncommingSVC PACKED; /* 15h: */
- unsigned short hiIncommingSVC PACKED; /* 17h: */
- unsigned short loTwoWaySVC PACKED; /* 19h: */
- unsigned short hiTwoWaySVC PACKED; /* 1Bh: */
- unsigned short loOutgoingSVC PACKED; /* 1Dh: */
- unsigned short hiOutgoingSVC PACKED; /* 1Fh: */
- unsigned short options PACKED; /* 21h: */
- unsigned char responseOpt PACKED; /* 23h: */
- unsigned short facil1 PACKED; /* 24h: */
- unsigned short facil2 PACKED; /* 26h: */
- unsigned short ccittFacil PACKED; /* 28h: */
- unsigned short otherFacil PACKED; /* 2Ah: */
- unsigned short ccittCompat PACKED; /* 2Ch: */
- unsigned char t10t20 PACKED; /* 2Eh: */
- unsigned char t11t21 PACKED; /* 2Fh: */
- unsigned char t12t22 PACKED; /* 30h: */
- unsigned char t13t23 PACKED; /* 31h: */
- unsigned char t16t26 PACKED; /* 32H: */
- unsigned char t28 PACKED; /* 33h: */
- unsigned char r10r20 PACKED; /* 34h: */
- unsigned char r12r22 PACKED; /* 35h: */
- unsigned char r13r23 PACKED; /* 36h: */
-} TX25Config;
-
-/* ---------------------------------------------------------------------------
- * X25_READ_CHANNEL_CONFIG Command.
- */
-typedef struct X25ChanAlloc /*----- Channel allocation -*/
-{
- unsigned short loPVC PACKED; /* 00h: lowest PVC number */
- unsigned short hiPVC PACKED; /* 02h: highest PVC number */
- unsigned short loIncommingSVC PACKED; /* 04h: lowest incoming SVC */
- unsigned short hiIncommingSVC PACKED; /* 06h: highest incoming SVC */
- unsigned short loTwoWaySVC PACKED; /* 08h: lowest two-way SVC */
- unsigned short hiTwoWaySVC PACKED; /* 0Ah: highest two-way SVC */
- unsigned short loOutgoingSVC PACKED; /* 0Ch: lowest outgoing SVC */
- unsigned short hiOutgoingSVC PACKED; /* 0Eh: highest outgoing SVC */
-} TX25ChanAlloc;
-
-typedef struct X25ChanCfg /*------ Channel configuration -----*/
-{
- unsigned char type PACKED; /* 00h: channel type */
- unsigned char txConf PACKED; /* 01h: Tx packet and window sizes */
- unsigned char rxConf PACKED; /* 01h: Rx packet and window sizes */
-} TX25ChanCfg;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25_PVC 0x01 /* PVC */
-#define X25_SVC_IN 0x03 /* Incoming SVC */
-#define X25_SVC_TWOWAY 0x07 /* Two-way SVC */
-#define X25_SVC_OUT 0x0B /* Outgoing SVC */
-
-/*----------------------------------------------------------------------------
- * X25_READ_STATISTICS Command.
- */
-typedef struct X25Stats
-{ /* number of packets Tx/Rx'ed */
- unsigned short txRestartRqst PACKED; /* 00h: Restart Request */
- unsigned short rxRestartRqst PACKED; /* 02h: Restart Request */
- unsigned short txRestartConf PACKED; /* 04h: Restart Confirmation */
- unsigned short rxRestartConf PACKED; /* 06h: Restart Confirmation */
- unsigned short txResetRqst PACKED; /* 08h: Reset Request */
- unsigned short rxResetRqst PACKED; /* 0Ah: Reset Request */
- unsigned short txResetConf PACKED; /* 0Ch: Reset Confirmation */
- unsigned short rxResetConf PACKED; /* 0Eh: Reset Confirmation */
- unsigned short txCallRequest PACKED; /* 10h: Call Request */
- unsigned short rxCallRequest PACKED; /* 12h: Call Request */
- unsigned short txCallAccept PACKED; /* 14h: Call Accept */
- unsigned short rxCallAccept PACKED; /* 16h: Call Accept */
- unsigned short txClearRqst PACKED; /* 18h: Clear Request */
- unsigned short rxClearRqst PACKED; /* 1Ah: Clear Request */
- unsigned short txClearConf PACKED; /* 1Ch: Clear Confirmation */
- unsigned short rxClearConf PACKED; /* 1Eh: Clear Confirmation */
- unsigned short txDiagnostic PACKED; /* 20h: Diagnostic */
- unsigned short rxDiagnostic PACKED; /* 22h: Diagnostic */
- unsigned short txRegRqst PACKED; /* 24h: Registration Request */
- unsigned short rxRegRqst PACKED; /* 26h: Registration Request */
- unsigned short txRegConf PACKED; /* 28h: Registration Confirm.*/
- unsigned short rxRegConf PACKED; /* 2Ah: Registration Confirm.*/
- unsigned short txInterrupt PACKED; /* 2Ch: Interrupt */
- unsigned short rxInterrupt PACKED; /* 2Eh: Interrupt */
- unsigned short txIntrConf PACKED; /* 30h: Interrupt Confirm. */
- unsigned short rxIntrConf PACKED; /* 32h: Interrupt Confirm. */
- unsigned short txData PACKED; /* 34h: Data */
- unsigned short rxData PACKED; /* 36h: Data */
- unsigned short txRR PACKED; /* 38h: RR */
- unsigned short rxRR PACKED; /* 3Ah: RR */
- unsigned short txRNR PACKED; /* 3Ch: RNR */
- unsigned short rxRNR PACKED; /* 3Eh: RNR */
-} TX25Stats;
-
-/*----------------------------------------------------------------------------
- * X25_READ_HISTORY_TABLE Command.
- */
-typedef struct X25EventLog
-{
- unsigned char type PACKED; /* 00h: transaction type */
- unsigned short lcn PACKED; /* 01h: logical channel num */
- unsigned char packet PACKED; /* 03h: async packet type */
- unsigned char cause PACKED; /* 04h: X.25 cause field */
- unsigned char diag PACKED; /* 05h: X.25 diag field */
- TX25TimeStamp ts PACKED; /* 06h: time stamp */
-} TX25EventLog;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25LOG_INCOMMING 0x00
-#define X25LOG_APPLICATION 0x01
-#define X25LOG_AUTOMATIC 0x02
-#define X25LOG_ERROR 0x04
-#define X25LOG_TIMEOUT 0x08
-#define X25LOG_RECOVERY 0x10
-
-/*
- * Defines for the 'packet' field.
- */
-#define X25LOG_CALL_RQST 0x0B
-#define X25LOG_CALL_ACCEPTED 0x0F
-#define X25LOG_CLEAR_RQST 0x13
-#define X25LOG_CLEAR_CONFRM 0x17
-#define X25LOG_RESET_RQST 0x1B
-#define X25LOG_RESET_CONFRM 0x1F
-#define X25LOG_RESTART_RQST 0xFB
-#define X25LOG_RESTART_COMFRM 0xFF
-#define X25LOG_DIAGNOSTIC 0xF1
-#define X25LOG_DTE_REG_RQST 0xF3
-#define X25LOG_DTE_REG_COMFRM 0xF7
-
-/* ---------------------------------------------------------------------------
- * X25_TRACE_CONFIGURE Command.
- */
-typedef struct X25TraceCfg
-{
- unsigned char flags PACKED; /* 00h: trace configuration flags */
- unsigned char timeout PACKED; /* 01h: timeout for trace delay mode*/
-} TX25TraceCfg;
-
-/*
- * Defines for the 'flags' field.
- */
-#define X25_TRC_ENABLE 0x01 /* bit0: '1' - trace enabled */
-#define X25_TRC_TIMESTAMP 0x02 /* bit1: '1' - time stamping enabled*/
-#define X25_TRC_DELAY 0x04 /* bit2: '1' - trace delay enabled */
-#define X25_TRC_DATA 0x08 /* bit3: '1' - trace data packets */
-#define X25_TRC_SUPERVISORY 0x10 /* bit4: '1' - trace suprvisory pkts*/
-#define X25_TRC_ASYNCHRONOUS 0x20 /* bit5: '1' - trace asynch. packets*/
-#define X25_TRC_HDLC 0x40 /* bit6: '1' - trace all packets */
-#define X25_TRC_READ 0x80 /* bit7: '1' - get current config. */
-
-/* ---------------------------------------------------------------------------
- * X25_READ_TRACE_DATA Command.
- */
-typedef struct X25Trace /*----- Trace data structure -------*/
-{
- unsigned short length PACKED; /* 00h: trace data length */
- unsigned char type PACKED; /* 02h: trace type */
- unsigned char lost_cnt PACKED; /* 03h: N of traces lost */
- TX25TimeStamp tstamp PACKED; /* 04h: mon/date/sec/min/hour */
- unsigned short millisec PACKED; /* 09h: ms time stamp */
- unsigned char data[0] PACKED; /* 0Bh: traced frame */
-} TX25Trace;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25_TRC_TYPE_MASK 0x0F /* bits 0..3: trace type */
-#define X25_TRC_TYPE_RX_FRAME 0x00 /* received frame trace */
-#define X25_TRC_TYPE_TX_FRAME 0x01 /* transmitted frame */
-#define X25_TRC_TYPE_ERR_FRAME 0x02 /* error frame */
-
-#define X25_TRC_ERROR_MASK 0xF0 /* bits 4..7: error code */
-#define X25_TRCERR_RX_ABORT 0x10 /* receive abort error */
-#define X25_TRCERR_RX_BADCRC 0x20 /* receive CRC error */
-#define X25_TRCERR_RX_OVERRUN 0x30 /* receiver overrun error */
-#define X25_TRCERR_RX_TOO_LONG 0x40 /* excessive frame length error */
-#define X25_TRCERR_TX_ABORT 0x70 /* aborted frame transmittion error */
-#define X25_TRCERR_TX_UNDERRUN 0x80 /* transmit underrun error */
-
-/*****************************************************************************
- * Following definitions describe HDLC frame and X.25 packet formats.
- ****************************************************************************/
-
-typedef struct HDLCFrame /*----- DHLC Frame Format ----------*/
-{
- unsigned char addr PACKED; /* address field */
- unsigned char cntl PACKED; /* control field */
- unsigned char data[0] PACKED;
-} THDLCFrame;
-
-typedef struct X25Pkt /*----- X.25 Paket Format ----------*/
-{
- unsigned char lcn_hi PACKED; /* 4 MSB of Logical Channel Number */
- unsigned char lcn_lo PACKED; /* 8 LSB of Logical Channel Number */
- unsigned char type PACKED;
- unsigned char data[0] PACKED;
-} TX25Pkt;
-
-/*
- * Defines for the 'lcn_hi' field.
- */
-#define X25_Q_BIT_MASK 0x80 /* Data Qualifier Bit mask */
-#define X25_D_BIT_MASK 0x40 /* Delivery Confirmation Bit mask */
-#define X25_M_BITS_MASK 0x30 /* Modulo Bits mask */
-#define X25_LCN_MSB_MASK 0x0F /* LCN most significant bits mask */
-
-/*
- * Defines for the 'type' field.
- */
-#define X25PKT_DATA 0x01 /* Data packet mask */
-#define X25PKT_SUPERVISORY 0x02 /* Supervisory packet mask */
-#define X25PKT_CALL_RQST 0x0B /* Call Request/Incoming */
-#define X25PKT_CALL_ACCEPTED 0x0F /* Call Accepted/Connected */
-#define X25PKT_CLEAR_RQST 0x13 /* Clear Request/Indication */
-#define X25PKT_CLEAR_CONFRM 0x17 /* Clear Confirmation */
-#define X25PKT_RESET_RQST 0x1B /* Reset Request/Indication */
-#define X25PKT_RESET_CONFRM 0x1F /* Reset Confirmation */
-#define X25PKT_RESTART_RQST 0xFB /* Restart Request/Indication */
-#define X25PKT_RESTART_CONFRM 0xFF /* Restart Confirmation */
-#define X25PKT_INTERRUPT 0x23 /* Interrupt */
-#define X25PKT_INTERRUPT_CONFRM 0x27 /* Interrupt Confirmation */
-#define X25PKT_DIAGNOSTIC 0xF1 /* Diagnostic */
-#define X25PKT_REGISTR_RQST 0xF3 /* Registration Request */
-#define X25PKT_REGISTR_CONFRM 0xF7 /* Registration Confirmation */
-#define X25PKT_RR_MASKED 0x01 /* Receive Ready packet after masking */
-#define X25PKT_RNR_MASKED 0x05 /* Receive Not Ready after masking */
-
-
-typedef struct {
- TX25Cmd cmd PACKED;
- char data[X25_MAX_DATA] PACKED;
-} mbox_cmd_t;
-
-
-typedef struct {
- unsigned char qdm PACKED; /* Q/D/M bits */
- unsigned char cause PACKED; /* cause field */
- unsigned char diagn PACKED; /* diagnostics */
- unsigned char pktType PACKED;
- unsigned short length PACKED;
- unsigned char result PACKED;
- unsigned short lcn PACKED;
- char reserved[7] PACKED;
-}x25api_hdr_t;
-
-
-typedef struct {
- x25api_hdr_t hdr PACKED;
- char data[X25_MAX_DATA] PACKED;
-}x25api_t;
-
-
-/*
- * XPIPEMON Definitions
- */
-
-/* valid ip_protocol for UDP management */
-#define UDPMGMT_UDP_PROTOCOL 0x11
-#define UDPMGMT_XPIPE_SIGNATURE "XLINK8ND"
-#define UDPMGMT_DRVRSTATS_SIGNATURE "DRVSTATS"
-
-/* values for request/reply byte */
-#define UDPMGMT_REQUEST 0x01
-#define UDPMGMT_REPLY 0x02
-#define UDP_OFFSET 12
-
-
-typedef struct {
- unsigned char opp_flag PACKED; /* the opp flag */
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* transfer data length */
- unsigned char result PACKED; /* return code */
- unsigned char pf PACKED; /* P/F bit */
- unsigned short lcn PACKED; /* logical channel */
- unsigned char qdm PACKED; /* Q/D/M bits */
- unsigned char cause PACKED; /* cause field */
- unsigned char diagn PACKED; /* diagnostics */
- unsigned char pktType PACKED; /* packet type */
- unsigned char resrv[4] PACKED; /* reserved */
-} cblock_t;
-
-typedef struct {
- ip_pkt_t ip_pkt PACKED;
- udp_pkt_t udp_pkt PACKED;
- wp_mgmt_t wp_mgmt PACKED;
- cblock_t cblock PACKED;
- unsigned char data[4080] PACKED;
-} x25_udp_pkt_t;
-
-
-typedef struct read_hdlc_stat {
- unsigned short inf_frames_rx_ok PACKED;
- unsigned short inf_frames_rx_out_of_seq PACKED;
- unsigned short inf_frames_rx_no_data PACKED;
- unsigned short inf_frames_rx_dropped PACKED;
- unsigned short inf_frames_rx_data_too_long PACKED;
- unsigned short inf_frames_rx_invalid_addr PACKED;
- unsigned short inf_frames_tx_ok PACKED;
- unsigned short inf_frames_tx_retransmit PACKED;
- unsigned short T1_timeouts PACKED;
- unsigned short SABM_frames_rx PACKED;
- unsigned short DISC_frames_rx PACKED;
- unsigned short DM_frames_rx PACKED;
- unsigned short FRMR_frames_rx PACKED;
- unsigned short SABM_frames_tx PACKED;
- unsigned short DISC_frames_tx PACKED;
- unsigned short DM_frames_tx PACKED;
- unsigned short FRMR_frames_tx PACKED;
-} read_hdlc_stat_t;
-
-typedef struct read_comms_err_stats{
- unsigned char overrun_err_rx PACKED;
- unsigned char CRC_err PACKED;
- unsigned char abort_frames_rx PACKED;
- unsigned char frames_dropped_buf_full PACKED;
- unsigned char abort_frames_tx PACKED;
- unsigned char transmit_underruns PACKED;
- unsigned char missed_tx_underruns_intr PACKED;
- unsigned char reserved PACKED;
- unsigned char DCD_drop PACKED;
- unsigned char CTS_drop PACKED;
-} read_comms_err_stats_t;
-
-typedef struct trace_data {
- unsigned short length PACKED;
- unsigned char type PACKED;
- unsigned char trace_dropped PACKED;
- unsigned char reserved[5] PACKED;
- unsigned short timestamp PACKED;
- unsigned char data PACKED;
-} trace_data_t;
-
-enum {UDP_XPIPE_TYPE};
-
-#define XPIPE_ENABLE_TRACING 0x14
-#define XPIPE_DISABLE_TRACING 0x14
-#define XPIPE_GET_TRACE_INFO 0x16
-#define XPIPE_FT1_READ_STATUS 0x74
-#define XPIPE_DRIVER_STAT_IFSEND 0x75
-#define XPIPE_DRIVER_STAT_INTR 0x76
-#define XPIPE_DRIVER_STAT_GEN 0x77
-#define XPIPE_FLUSH_DRIVER_STATS 0x78
-#define XPIPE_ROUTER_UP_TIME 0x79
-#define XPIPE_SET_FT1_MODE 0x81
-#define XPIPE_FT1_STATUS_CTRL 0x80
-
-
-/* error messages */
-#define NO_BUFFS_OR_CLOSED_WIN 0x33
-#define DATA_LENGTH_TOO_BIG 0x32
-#define NO_DATA_AVAILABLE 0x33
-#define Z80_TIMEOUT_ERROR 0x0a
-#define NO_BUFFS 0x08
-
-
-/* Trace options */
-#define TRACE_DEFAULT 0x03
-#define TRACE_SUPERVISOR_FRMS 0x10
-#define TRACE_ASYNC_FRMS 0x20
-#define TRACE_ALL_HDLC_FRMS 0x40
-#define TRACE_DATA_FRMS 0x08
-
-
-#endif /* _SDLA_X25_H */
diff --git a/include/linux/sdladrv.h b/include/linux/sdladrv.h
deleted file mode 100644
index c85e103d5e7b..000000000000
--- a/include/linux/sdladrv.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*****************************************************************************
-* sdladrv.h SDLA Support Module. Kernel API Definitions.
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Jun 02, 1999 Gideon Hack Added support for the S514 PCI adapter.
-* Dec 11, 1996 Gene Kozin Complete overhaul.
-* Oct 17, 1996 Gene Kozin Minor bug fixes.
-* Jun 12, 1996 Gene Kozin Added support for S503 card.
-* Dec 06, 1995 Gene Kozin Initial version.
-*****************************************************************************/
-#ifndef _SDLADRV_H
-#define _SDLADRV_H
-
-
-#define SDLA_MAXIORANGE 4 /* maximum I/O port range */
-#define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */
-/****** Data Structures *****************************************************/
-
-/*----------------------------------------------------------------------------
- * Adapter hardware configuration. Pointer to this structure is passed to all
- * APIs.
- */
-typedef struct sdlahw
-{
- unsigned type; /* adapter type */
- unsigned fwid; /* firmware ID */
- unsigned port; /* adapter I/O port base */
- int irq; /* interrupt request level */
- char S514_cpu_no[1]; /* PCI CPU Number */
- unsigned char S514_slot_no; /* PCI Slot Number */
- char auto_pci_cfg; /* Autodetect PCI Slot */
- struct pci_dev *pci_dev; /* PCI device */
- void * dpmbase; /* dual-port memory base */
- unsigned dpmsize; /* dual-port memory size */
- unsigned pclk; /* CPU clock rate, kHz */
- unsigned long memory; /* memory size */
- unsigned long vector; /* local offset of the DPM window */
- unsigned io_range; /* I/O port range */
- unsigned char regs[SDLA_MAXIORANGE]; /* was written to registers */
- unsigned reserved[5];
-} sdlahw_t;
-
-/****** Function Prototypes *************************************************/
-
-extern int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len);
-extern int sdla_down (sdlahw_t* hw);
-extern void S514_intack (sdlahw_t* hw, u32 int_status);
-extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
-extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr);
-extern int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf,
- unsigned len);
-extern int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf,
- unsigned len);
-extern int sdla_exec (void* opflag);
-
-extern unsigned wanpipe_hw_probe(void);
-
-#endif /* _SDLADRV_H */
diff --git a/include/linux/sdlapci.h b/include/linux/sdlapci.h
deleted file mode 100644
index 6f7c904f188d..000000000000
--- a/include/linux/sdlapci.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*****************************************************************************
-* sdlapci.h WANPIPE(tm) Multiprotocol WAN Link Driver.
-* Definitions for the SDLA PCI adapter.
-*
-* Author: Gideon Hack <ghack@sangoma.com>
-*
-* Copyright: (c) 1999-2000 Sangoma Technologies 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.
-* ============================================================================
-* Jun 02, 1999 Gideon Hack Initial version.
-*****************************************************************************/
-#ifndef _SDLAPCI_H
-#define _SDLAPCI_H
-
-/****** Defines *************************************************************/
-
-/* Definitions for identifying and finding S514 PCI adapters */
-#define V3_VENDOR_ID 0x11B0 /* V3 vendor ID number */
-#define V3_DEVICE_ID 0x0002 /* V3 device ID number */
-#define SANGOMA_SUBSYS_VENDOR 0x4753 /* ID for Sangoma */
-#define PCI_DEV_SLOT_MASK 0x1F /* mask for slot numbering */
-#define PCI_IRQ_NOT_ALLOCATED 0xFF /* interrupt line for no IRQ */
-
-/* Local PCI register offsets */
-#define PCI_VENDOR_ID_WORD 0x00 /* vendor ID */
-#define PCI_IO_BASE_DWORD 0x10 /* IO base */
-#define PCI_MEM_BASE0_DWORD 0x14 /* memory base - apperture 0 */
-#define PCI_MEM_BASE1_DWORD 0x18 /* memory base - apperture 1 */
-#define PCI_SUBSYS_VENDOR_WORD 0x2C /* subsystem vendor ID */
-#define PCI_INT_LINE_BYTE 0x3C /* interrupt line */
-#define PCI_INT_PIN_BYTE 0x3D /* interrupt pin */
-#define PCI_MAP0_DWORD 0x40 /* PCI to local bus address 0 */
-#define PCI_MAP1_DWORD 0x44 /* PCI to local bus address 1 */
-#define PCI_INT_STATUS 0x48 /* interrupt status */
-#define PCI_INT_CONFIG 0x4C /* interrupt configuration */
-
-/* Local PCI register usage */
-#define PCI_MEMORY_ENABLE 0x00000003 /* enable PCI memory */
-#define PCI_CPU_A_MEM_DISABLE 0x00000002 /* disable CPU A memory */
-#define PCI_CPU_B_MEM_DISABLE 0x00100002 /* disable CPU B memory */
-#define PCI_ENABLE_IRQ_CPU_A 0x005A0004 /* enable IRQ for CPU A */
-#define PCI_ENABLE_IRQ_CPU_B 0x005A0008 /* enable IRQ for CPU B */
-#define PCI_DISABLE_IRQ_CPU_A 0x00000004 /* disable IRQ for CPU A */
-#define PCI_DISABLE_IRQ_CPU_B 0x00000008 /* disable IRQ for CPU B */
-
-/* Setting for the Interrupt Status register */
-#define IRQ_CPU_A 0x04 /* IRQ for CPU A */
-#define IRQ_CPU_B 0x08 /* IRQ for CPU B */
-
-/* The maximum size of the S514 memory */
-#define MAX_SIZEOF_S514_MEMORY (256 * 1024)
-
-/* S514 control register offsets within the memory address space */
-#define S514_CTRL_REG_BYTE 0x80000
-
-/* S514 adapter control bytes */
-#define S514_CPU_HALT 0x00
-#define S514_CPU_START 0x01
-
-/* The maximum number of S514 adapters supported */
-#define MAX_S514_CARDS 20
-
-#define PCI_CARD_TYPE 0x2E
-#define S514_DUAL_CPU 0x12
-#define S514_SINGLE_CPU 0x11
-
-#endif /* _SDLAPCI_H */
-
diff --git a/include/linux/sdlasfm.h b/include/linux/sdlasfm.h
deleted file mode 100644
index 94aaa8ada667..000000000000
--- a/include/linux/sdlasfm.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*****************************************************************************
-* sdlasfm.h WANPIPE(tm) Multiprotocol WAN Link Driver.
-* Definitions for the SDLA Firmware Module (SFM).
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 1995-1999 Sangoma Technologies 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.
-* ============================================================================
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Dec 11, 1996 Gene Kozin Cosmetic changes
-* Apr 16, 1996 Gene Kozin Changed adapter & firmware IDs. Version 2
-* Dec 15, 1995 Gene Kozin Structures chaned
-* Nov 09, 1995 Gene Kozin Initial version.
-*****************************************************************************/
-#ifndef _SDLASFM_H
-#define _SDLASFM_H
-
-/****** Defines *************************************************************/
-
-#define SFM_VERSION 2
-#define SFM_SIGNATURE "SFM - Sangoma SDLA Firmware Module"
-
-/* min/max */
-#define SFM_IMAGE_SIZE 0x8000 /* max size of SDLA code image file */
-#define SFM_DESCR_LEN 256 /* max length of description string */
-#define SFM_MAX_SDLA 16 /* max number of compatible adapters */
-
-/* Adapter types */
-#define SDLA_S502A 5020
-#define SDLA_S502E 5021
-#define SDLA_S503 5030
-#define SDLA_S508 5080
-#define SDLA_S507 5070
-#define SDLA_S509 5090
-#define SDLA_S514 5140
-
-/* S514 PCI adapter CPU numbers */
-#define S514_CPU_A 'A'
-#define S514_CPU_B 'B'
-
-
-/* Firmware identification numbers:
- * 0 .. 999 Test & Diagnostics
- * 1000 .. 1999 Streaming HDLC
- * 2000 .. 2999 Bisync
- * 3000 .. 3999 SDLC
- * 4000 .. 4999 HDLC
- * 5000 .. 5999 X.25
- * 6000 .. 6999 Frame Relay
- * 7000 .. 7999 PPP
- * 8000 .. 8999 Cisco HDLC
- */
-#define SFID_CALIB502 200
-#define SFID_STRM502 1200
-#define SFID_STRM508 1800
-#define SFID_BSC502 2200
-#define SFID_SDLC502 3200
-#define SFID_HDLC502 4200
-#define SFID_HDLC508 4800
-#define SFID_X25_502 5200
-#define SFID_X25_508 5800
-#define SFID_FR502 6200
-#define SFID_FR508 6800
-#define SFID_PPP502 7200
-#define SFID_PPP508 7800
-#define SFID_PPP514 7140
-#define SFID_CHDLC508 8800
-#define SFID_CHDLC514 8140
-
-/****** Data Types **********************************************************/
-
-typedef struct sfm_info /* firmware module information */
-{
- unsigned short codeid; /* firmware ID */
- unsigned short version; /* firmaware version number */
- unsigned short adapter[SFM_MAX_SDLA]; /* compatible adapter types */
- unsigned long memsize; /* minimum memory size */
- unsigned short reserved[2]; /* reserved */
- unsigned short startoffs; /* entry point offset */
- unsigned short winoffs; /* dual-port memory window offset */
- unsigned short codeoffs; /* code load offset */
- unsigned short codesize; /* code size */
- unsigned short dataoffs; /* configuration data load offset */
- unsigned short datasize; /* configuration data size */
-} sfm_info_t;
-
-typedef struct sfm /* SDLA firmware file structire */
-{
- char signature[80]; /* SFM file signature */
- unsigned short version; /* file format version */
- unsigned short checksum; /* info + image */
- unsigned short reserved[6]; /* reserved */
- char descr[SFM_DESCR_LEN]; /* description string */
- sfm_info_t info; /* firmware module info */
- unsigned char image[1]; /* code image (variable size) */
-} sfm_t;
-
-#endif /* _SDLASFM_H */
-
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index fca9b0fb5b4e..5a095572881d 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -73,7 +73,7 @@ static inline int write_tryseqlock(seqlock_t *sl)
}
/* Start of read calculation -- fetch last complete writer token */
-static inline unsigned read_seqbegin(const seqlock_t *sl)
+static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
{
unsigned ret = sl->sequence;
smp_rmb();
@@ -88,7 +88,7 @@ static inline unsigned read_seqbegin(const seqlock_t *sl)
*
* Using xor saves one conditional branch.
*/
-static inline int read_seqretry(const seqlock_t *sl, unsigned iv)
+static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
{
smp_rmb();
return (iv & 1) | (sl->sequence ^ iv);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 162a8fd10b29..70739f51a09f 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -14,10 +14,12 @@
*
* SA_INTERRUPT is also used by the irq handling routines.
* SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ * SA_PROBEIRQ is set by callers when they expect sharing mismatches to occur
*/
-#define SA_PROBE SA_ONESHOT
#define SA_SAMPLE_RANDOM SA_RESTART
#define SA_SHIRQ 0x04000000
+#define SA_PROBEIRQ 0x08000000
+
/*
* As above, these correspond to the IORESOURCE_IRQ_* defines in
* linux/ioport.h to select the interrupt line behaviour. When
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c4619a428d9b..f8f234708b98 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -344,6 +344,13 @@ extern void skb_over_panic(struct sk_buff *skb, int len,
void *here);
extern void skb_under_panic(struct sk_buff *skb, int len,
void *here);
+extern void skb_truesize_bug(struct sk_buff *skb);
+
+static inline void skb_truesize_check(struct sk_buff *skb)
+{
+ if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+ skb_truesize_bug(skb);
+}
extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
int getfrag(void *from, char *to, int offset,
diff --git a/include/linux/string.h b/include/linux/string.h
index dee221429ad0..c61306da8c52 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -13,11 +13,6 @@
extern "C" {
#endif
-extern char * strpbrk(const char *,const char *);
-extern char * strsep(char **,const char *);
-extern __kernel_size_t strspn(const char *,const char *);
-extern __kernel_size_t strcspn(const char *,const char *);
-
extern char *strndup_user(const char __user *, long);
/*
@@ -70,6 +65,18 @@ extern __kernel_size_t strlen(const char *);
#ifndef __HAVE_ARCH_STRNLEN
extern __kernel_size_t strnlen(const char *,__kernel_size_t);
#endif
+#ifndef __HAVE_ARCH_STRPBRK
+extern char * strpbrk(const char *,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRSEP
+extern char * strsep(char **,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRSPN
+extern __kernel_size_t strspn(const char *,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRCSPN
+extern __kernel_size_t strcspn(const char *,const char *);
+#endif
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index 8f96e9dc369a..77f78e56c481 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -69,9 +69,21 @@ struct rpc_clnt;
/*
* EXPORTed functions for managing rpc_iostats structures
*/
+
+#ifdef CONFIG_PROC_FS
+
struct rpc_iostats * rpc_alloc_iostats(struct rpc_clnt *);
void rpc_count_iostats(struct rpc_task *);
void rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
void rpc_free_iostats(struct rpc_iostats *);
+#else /* CONFIG_PROC_FS */
+
+static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
+static inline void rpc_count_iostats(struct rpc_task *task) {}
+static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
+
+#endif /* CONFIG_PROC_FS */
+
#endif /* _LINUX_SUNRPC_METRICS_H */
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 50cab2a09f28..503564384545 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -197,15 +197,16 @@ svc_take_res_page(struct svc_rqst *rqstp)
return rqstp->rq_respages[rqstp->rq_resused++];
}
-static inline int svc_take_page(struct svc_rqst *rqstp)
+static inline void svc_take_page(struct svc_rqst *rqstp)
{
- if (rqstp->rq_arghi <= rqstp->rq_argused)
- return -ENOMEM;
+ if (rqstp->rq_arghi <= rqstp->rq_argused) {
+ WARN_ON(1);
+ return;
+ }
rqstp->rq_arghi--;
rqstp->rq_respages[rqstp->rq_resused] =
rqstp->rq_argpages[rqstp->rq_arghi];
rqstp->rq_resused++;
- return 0;
}
static inline void svc_pushback_allpages(struct svc_rqst *rqstp)
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 7eebbab7160b..e8bbe8118de8 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -53,6 +53,7 @@ struct rpc_timeout {
struct rpc_task;
struct rpc_xprt;
+struct seq_file;
/*
* This describes a complete RPC request
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 54eac8a39a4c..5b1fdf1cff4f 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -155,6 +155,7 @@ extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *
/* linux/mm/page_alloc.c */
extern unsigned long totalram_pages;
extern unsigned long totalhigh_pages;
+extern unsigned long totalreserve_pages;
extern long nr_swap_pages;
extern unsigned int nr_free_pages(void);
extern unsigned int nr_free_pages_pgdat(pg_data_t *pgdat);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 5717147596b6..3996960fc565 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -569,9 +569,17 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
int flags, int mode);
asmlinkage long sys_unshare(unsigned long unshare_flags);
-asmlinkage long sys_splice(int fdin, int fdout, size_t len,
- unsigned int flags);
+
+asmlinkage long sys_splice(int fd_in, loff_t __user *off_in,
+ int fd_out, loff_t __user *off_out,
+ size_t len, unsigned int flags);
+
+asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags);
+
+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,
- int flags);
+ unsigned int flags);
#endif
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 392da5a6dacb..1ea5d3cda6ae 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -74,6 +74,7 @@ struct sysfs_dirent {
umode_t s_mode;
struct dentry * s_dentry;
struct iattr * s_iattr;
+ atomic_t s_event;
};
#define SYSFS_ROOT 0x0001
@@ -117,6 +118,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
int sysfs_create_group(struct kobject *, const struct attribute_group *);
void sysfs_remove_group(struct kobject *, const struct attribute_group *);
+void sysfs_notify(struct kobject * k, char *dir, char *attr);
#else /* CONFIG_SYSFS */
@@ -185,6 +187,10 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
;
}
+static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
+{
+}
+
#endif /* CONFIG_SYSFS */
#endif /* _SYSFS_H_ */
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 0976a163b459..31548303ee37 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -6,9 +6,10 @@ extern int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *c
extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size);
extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
+void tty_schedule_flip(struct tty_struct *tty);
static inline int tty_insert_flip_char(struct tty_struct *tty,
- unsigned char ch, char flag)
+ unsigned char ch, char flag)
{
struct tty_buffer *tb = tty->buf.tail;
if (tb && tb->active && tb->used < tb->size) {
@@ -19,26 +20,4 @@ static inline int tty_insert_flip_char(struct tty_struct *tty,
return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
}
-static inline void tty_schedule_flip(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL) {
- tty->buf.tail->active = 0;
- tty->buf.tail->commit = tty->buf.tail->used;
- }
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- schedule_delayed_work(&tty->buf.work, 1);
-}
-
-#undef _INLINE_
-
-
#endif /* _LINUX_TTY_FLIP_H */
-
-
-
-
-
-
-
diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
new file mode 100644
index 000000000000..c602f884f182
--- /dev/null
+++ b/include/linux/usb/net2280.h
@@ -0,0 +1,444 @@
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+#ifndef __LINUX_USB_NET2280_H
+#define __LINUX_USB_NET2280_H
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* NET2280 MEMORY MAPPED REGISTERS
+ *
+ * The register layout came from the chip documentation, and the bit
+ * number definitions were extracted from chip specification.
+ *
+ * Use the shift operator ('<<') to build bit masks, with readl/writel
+ * to access the registers through PCI.
+ */
+
+/* main registers, BAR0 + 0x0000 */
+struct net2280_regs {
+ // offset 0x0000
+ u32 devinit;
+#define LOCAL_CLOCK_FREQUENCY 8
+#define FORCE_PCI_RESET 7
+#define PCI_ID 6
+#define PCI_ENABLE 5
+#define FIFO_SOFT_RESET 4
+#define CFG_SOFT_RESET 3
+#define PCI_SOFT_RESET 2
+#define USB_SOFT_RESET 1
+#define M8051_RESET 0
+ u32 eectl;
+#define EEPROM_ADDRESS_WIDTH 23
+#define EEPROM_CHIP_SELECT_ACTIVE 22
+#define EEPROM_PRESENT 21
+#define EEPROM_VALID 20
+#define EEPROM_BUSY 19
+#define EEPROM_CHIP_SELECT_ENABLE 18
+#define EEPROM_BYTE_READ_START 17
+#define EEPROM_BYTE_WRITE_START 16
+#define EEPROM_READ_DATA 8
+#define EEPROM_WRITE_DATA 0
+ u32 eeclkfreq;
+ u32 _unused0;
+ // offset 0x0010
+
+ u32 pciirqenb0; /* interrupt PCI master ... */
+#define SETUP_PACKET_INTERRUPT_ENABLE 7
+#define ENDPOINT_F_INTERRUPT_ENABLE 6
+#define ENDPOINT_E_INTERRUPT_ENABLE 5
+#define ENDPOINT_D_INTERRUPT_ENABLE 4
+#define ENDPOINT_C_INTERRUPT_ENABLE 3
+#define ENDPOINT_B_INTERRUPT_ENABLE 2
+#define ENDPOINT_A_INTERRUPT_ENABLE 1
+#define ENDPOINT_0_INTERRUPT_ENABLE 0
+ u32 pciirqenb1;
+#define PCI_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+ u32 cpu_irqenb0; /* ... or onboard 8051 */
+#define SETUP_PACKET_INTERRUPT_ENABLE 7
+#define ENDPOINT_F_INTERRUPT_ENABLE 6
+#define ENDPOINT_E_INTERRUPT_ENABLE 5
+#define ENDPOINT_D_INTERRUPT_ENABLE 4
+#define ENDPOINT_C_INTERRUPT_ENABLE 3
+#define ENDPOINT_B_INTERRUPT_ENABLE 2
+#define ENDPOINT_A_INTERRUPT_ENABLE 1
+#define ENDPOINT_0_INTERRUPT_ENABLE 0
+ u32 cpu_irqenb1;
+#define CPU_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_INTA_INTERRUPT_ENABLE 24
+#define PCI_PME_INTERRUPT_ENABLE 23
+#define PCI_SERR_INTERRUPT_ENABLE 22
+#define PCI_PERR_INTERRUPT_ENABLE 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+
+ // offset 0x0020
+ u32 _unused1;
+ u32 usbirqenb1;
+#define USB_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_INTA_INTERRUPT_ENABLE 24
+#define PCI_PME_INTERRUPT_ENABLE 23
+#define PCI_SERR_INTERRUPT_ENABLE 22
+#define PCI_PERR_INTERRUPT_ENABLE 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+ u32 irqstat0;
+#define INTA_ASSERTED 12
+#define SETUP_PACKET_INTERRUPT 7
+#define ENDPOINT_F_INTERRUPT 6
+#define ENDPOINT_E_INTERRUPT 5
+#define ENDPOINT_D_INTERRUPT 4
+#define ENDPOINT_C_INTERRUPT 3
+#define ENDPOINT_B_INTERRUPT 2
+#define ENDPOINT_A_INTERRUPT 1
+#define ENDPOINT_0_INTERRUPT 0
+ u32 irqstat1;
+#define POWER_STATE_CHANGE_INTERRUPT 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
+#define PCI_PARITY_ERROR_INTERRUPT 25
+#define PCI_INTA_INTERRUPT 24
+#define PCI_PME_INTERRUPT 23
+#define PCI_SERR_INTERRUPT 22
+#define PCI_PERR_INTERRUPT 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
+#define PCI_RETRY_ABORT_INTERRUPT 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
+#define SOF_DOWN_INTERRUPT 14
+#define GPIO_INTERRUPT 13
+#define DMA_D_INTERRUPT 12
+#define DMA_C_INTERRUPT 11
+#define DMA_B_INTERRUPT 10
+#define DMA_A_INTERRUPT 9
+#define EEPROM_DONE_INTERRUPT 8
+#define VBUS_INTERRUPT 7
+#define CONTROL_STATUS_INTERRUPT 6
+#define ROOT_PORT_RESET_INTERRUPT 4
+#define SUSPEND_REQUEST_INTERRUPT 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
+#define RESUME_INTERRUPT 1
+#define SOF_INTERRUPT 0
+ // offset 0x0030
+ u32 idxaddr;
+ u32 idxdata;
+ u32 fifoctl;
+#define PCI_BASE2_RANGE 16
+#define IGNORE_FIFO_AVAILABILITY 3
+#define PCI_BASE2_SELECT 2
+#define FIFO_CONFIGURATION_SELECT 0
+ u32 _unused2;
+ // offset 0x0040
+ u32 memaddr;
+#define START 28
+#define DIRECTION 27
+#define FIFO_DIAGNOSTIC_SELECT 24
+#define MEMORY_ADDRESS 0
+ u32 memdata0;
+ u32 memdata1;
+ u32 _unused3;
+ // offset 0x0050
+ u32 gpioctl;
+#define GPIO3_LED_SELECT 12
+#define GPIO3_INTERRUPT_ENABLE 11
+#define GPIO2_INTERRUPT_ENABLE 10
+#define GPIO1_INTERRUPT_ENABLE 9
+#define GPIO0_INTERRUPT_ENABLE 8
+#define GPIO3_OUTPUT_ENABLE 7
+#define GPIO2_OUTPUT_ENABLE 6
+#define GPIO1_OUTPUT_ENABLE 5
+#define GPIO0_OUTPUT_ENABLE 4
+#define GPIO3_DATA 3
+#define GPIO2_DATA 2
+#define GPIO1_DATA 1
+#define GPIO0_DATA 0
+ u32 gpiostat;
+#define GPIO3_INTERRUPT 3
+#define GPIO2_INTERRUPT 2
+#define GPIO1_INTERRUPT 1
+#define GPIO0_INTERRUPT 0
+} __attribute__ ((packed));
+
+/* usb control, BAR0 + 0x0080 */
+struct net2280_usb_regs {
+ // offset 0x0080
+ u32 stdrsp;
+#define STALL_UNSUPPORTED_REQUESTS 31
+#define SET_TEST_MODE 16
+#define GET_OTHER_SPEED_CONFIGURATION 15
+#define GET_DEVICE_QUALIFIER 14
+#define SET_ADDRESS 13
+#define ENDPOINT_SET_CLEAR_HALT 12
+#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
+#define GET_STRING_DESCRIPTOR_2 10
+#define GET_STRING_DESCRIPTOR_1 9
+#define GET_STRING_DESCRIPTOR_0 8
+#define GET_SET_INTERFACE 6
+#define GET_SET_CONFIGURATION 5
+#define GET_CONFIGURATION_DESCRIPTOR 4
+#define GET_DEVICE_DESCRIPTOR 3
+#define GET_ENDPOINT_STATUS 2
+#define GET_INTERFACE_STATUS 1
+#define GET_DEVICE_STATUS 0
+ u32 prodvendid;
+#define PRODUCT_ID 16
+#define VENDOR_ID 0
+ u32 relnum;
+ u32 usbctl;
+#define SERIAL_NUMBER_INDEX 16
+#define PRODUCT_ID_STRING_ENABLE 13
+#define VENDOR_ID_STRING_ENABLE 12
+#define USB_ROOT_PORT_WAKEUP_ENABLE 11
+#define VBUS_PIN 10
+#define TIMED_DISCONNECT 9
+#define SUSPEND_IMMEDIATELY 7
+#define SELF_POWERED_USB_DEVICE 6
+#define REMOTE_WAKEUP_SUPPORT 5
+#define PME_POLARITY 4
+#define USB_DETECT_ENABLE 3
+#define PME_WAKEUP_ENABLE 2
+#define DEVICE_REMOTE_WAKEUP_ENABLE 1
+#define SELF_POWERED_STATUS 0
+ // offset 0x0090
+ u32 usbstat;
+#define HIGH_SPEED 7
+#define FULL_SPEED 6
+#define GENERATE_RESUME 5
+#define GENERATE_DEVICE_REMOTE_WAKEUP 4
+ u32 xcvrdiag;
+#define FORCE_HIGH_SPEED_MODE 31
+#define FORCE_FULL_SPEED_MODE 30
+#define USB_TEST_MODE 24
+#define LINE_STATE 16
+#define TRANSCEIVER_OPERATION_MODE 2
+#define TRANSCEIVER_SELECT 1
+#define TERMINATION_SELECT 0
+ u32 setup0123;
+ u32 setup4567;
+ // offset 0x0090
+ u32 _unused0;
+ u32 ouraddr;
+#define FORCE_IMMEDIATE 7
+#define OUR_USB_ADDRESS 0
+ u32 ourconfig;
+} __attribute__ ((packed));
+
+/* pci control, BAR0 + 0x0100 */
+struct net2280_pci_regs {
+ // offset 0x0100
+ u32 pcimstctl;
+#define PCI_ARBITER_PARK_SELECT 13
+#define PCI_MULTI LEVEL_ARBITER 12
+#define PCI_RETRY_ABORT_ENABLE 11
+#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
+#define DMA_READ_MULTIPLE_ENABLE 9
+#define DMA_READ_LINE_ENABLE 8
+#define PCI_MASTER_COMMAND_SELECT 6
+#define MEM_READ_OR_WRITE 0
+#define IO_READ_OR_WRITE 1
+#define CFG_READ_OR_WRITE 2
+#define PCI_MASTER_START 5
+#define PCI_MASTER_READ_WRITE 4
+#define PCI_MASTER_WRITE 0
+#define PCI_MASTER_READ 1
+#define PCI_MASTER_BYTE_WRITE_ENABLES 0
+ u32 pcimstaddr;
+ u32 pcimstdata;
+ u32 pcimststat;
+#define PCI_ARBITER_CLEAR 2
+#define PCI_EXTERNAL_ARBITER 1
+#define PCI_HOST_MODE 0
+} __attribute__ ((packed));
+
+/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+ * for channels 0..3. see also struct net2280_dma: descriptor
+ * that can be loaded into some of these registers.
+ */
+struct net2280_dma_regs { /* [11.7] */
+ // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+ u32 dmactl;
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
+#define DMA_CLEAR_COUNT_ENABLE 21
+#define DESCRIPTOR_POLLING_RATE 19
+#define POLL_CONTINUOUS 0
+#define POLL_1_USEC 1
+#define POLL_100_USEC 2
+#define POLL_1_MSEC 3
+#define DMA_VALID_BIT_POLLING_ENABLE 18
+#define DMA_VALID_BIT_ENABLE 17
+#define DMA_SCATTER_GATHER_ENABLE 16
+#define DMA_OUT_AUTO_START_ENABLE 4
+#define DMA_PREEMPT_ENABLE 3
+#define DMA_FIFO_VALIDATE 2
+#define DMA_ENABLE 1
+#define DMA_ADDRESS_HOLD 0
+ u32 dmastat;
+#define DMA_ABORT_DONE_INTERRUPT 27
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
+#define DMA_TRANSACTION_DONE_INTERRUPT 24
+#define DMA_ABORT 1
+#define DMA_START 0
+ u32 _unused0 [2];
+ // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+ u32 dmacount;
+#define VALID_BIT 31
+#define DMA_DIRECTION 30
+#define DMA_DONE_INTERRUPT_ENABLE 29
+#define END_OF_CHAIN 28
+#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
+#define DMA_BYTE_COUNT 0
+ u32 dmaaddr;
+ u32 dmadesc;
+ u32 _unused1;
+} __attribute__ ((packed));
+
+/* dedicated endpoint registers, BAR0 + 0x0200 */
+
+struct net2280_dep_regs { /* [11.8] */
+ // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+ u32 dep_cfg;
+ // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+ u32 dep_rsp;
+ u32 _unused [2];
+} __attribute__ ((packed));
+
+/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+ * like this, for ep0 then the configurable endpoints A..F
+ * ep0 reserved for control; E and F have only 64 bytes of fifo
+ */
+struct net2280_ep_regs { /* [11.9] */
+ // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+ u32 ep_cfg;
+#define ENDPOINT_BYTE_COUNT 16
+#define ENDPOINT_ENABLE 10
+#define ENDPOINT_TYPE 8
+#define ENDPOINT_DIRECTION 7
+#define ENDPOINT_NUMBER 0
+ u32 ep_rsp;
+#define SET_NAK_OUT_PACKETS 15
+#define SET_EP_HIDE_STATUS_PHASE 14
+#define SET_EP_FORCE_CRC_ERROR 13
+#define SET_INTERRUPT_MODE 12
+#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
+#define SET_NAK_OUT_PACKETS_MODE 10
+#define SET_ENDPOINT_TOGGLE 9
+#define SET_ENDPOINT_HALT 8
+#define CLEAR_NAK_OUT_PACKETS 7
+#define CLEAR_EP_HIDE_STATUS_PHASE 6
+#define CLEAR_EP_FORCE_CRC_ERROR 5
+#define CLEAR_INTERRUPT_MODE 4
+#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
+#define CLEAR_NAK_OUT_PACKETS_MODE 2
+#define CLEAR_ENDPOINT_TOGGLE 1
+#define CLEAR_ENDPOINT_HALT 0
+ u32 ep_irqenb;
+#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
+#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
+#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
+#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
+ u32 ep_stat;
+#define FIFO_VALID_COUNT 24
+#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
+#define TIMEOUT 21
+#define USB_STALL_SENT 20
+#define USB_IN_NAK_SENT 19
+#define USB_IN_ACK_RCVD 18
+#define USB_OUT_PING_NAK_SENT 17
+#define USB_OUT_ACK_SENT 16
+#define FIFO_OVERFLOW 13
+#define FIFO_UNDERFLOW 12
+#define FIFO_FULL 11
+#define FIFO_EMPTY 10
+#define FIFO_FLUSH 9
+#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
+#define NAK_OUT_PACKETS 4
+#define DATA_PACKET_RECEIVED_INTERRUPT 3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
+#define DATA_OUT_PING_TOKEN_INTERRUPT 1
+#define DATA_IN_TOKEN_INTERRUPT 0
+ // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+ u32 ep_avail;
+ u32 ep_data;
+ u32 _unused0 [2];
+} __attribute__ ((packed));
+
+#endif /* __LINUX_USB_NET2280_H */
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index fadc535e2925..dc7c621e4647 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -12,6 +12,11 @@
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif
+#ifdef CONFIG_MODULE_UNLOAD
+#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload "
+#else
+#define MODULE_VERMAGIC_MODULE_UNLOAD ""
+#endif
#ifndef MODULE_ARCH_VERMAGIC
#define MODULE_ARCH_VERMAGIC ""
#endif
@@ -19,5 +24,5 @@
#define VERMAGIC_STRING \
UTS_RELEASE " " \
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \
- MODULE_ARCH_VERMAGIC \
+ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC \
"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index af2d6155d3fe..d7670ec1ec1e 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -966,66 +966,17 @@ struct v4l2_sliced_vbi_format
/* Teletext World System Teletext
(WST), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_PAL_B (0x000001)
-#define V4L2_SLICED_TELETEXT_PAL_C (0x000002)
-#define V4L2_SLICED_TELETEXT_NTSC_B (0x000010)
-#define V4L2_SLICED_TELETEXT_SECAM (0x000020)
-
-/* Teletext North American Broadcast Teletext Specification
- (NABTS), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_NTSC_C (0x000040)
-#define V4L2_SLICED_TELETEXT_NTSC_D (0x000080)
-
+#define V4L2_SLICED_TELETEXT_B (0x0001)
/* Video Program System, defined on ETS 300 231*/
-#define V4L2_SLICED_VPS (0x000400)
-
+#define V4L2_SLICED_VPS (0x0400)
/* Closed Caption, defined on EIA-608 */
-#define V4L2_SLICED_CAPTION_525 (0x001000)
-#define V4L2_SLICED_CAPTION_625 (0x002000)
-
+#define V4L2_SLICED_CAPTION_525 (0x1000)
/* Wide Screen System, defined on ITU-R BT1119.1 */
-#define V4L2_SLICED_WSS_625 (0x004000)
-
-/* Wide Screen System, defined on IEC 61880 */
-#define V4L2_SLICED_WSS_525 (0x008000)
-
-/* Vertical Interval Timecode (VITC), defined on SMPTE 12M */
-#define V4l2_SLICED_VITC_625 (0x010000)
-#define V4l2_SLICED_VITC_525 (0x020000)
-
-#define V4L2_SLICED_TELETEXT_B (V4L2_SLICED_TELETEXT_PAL_B |\
- V4L2_SLICED_TELETEXT_NTSC_B)
-
-#define V4L2_SLICED_TELETEXT (V4L2_SLICED_TELETEXT_PAL_B |\
- V4L2_SLICED_TELETEXT_PAL_C |\
- V4L2_SLICED_TELETEXT_SECAM |\
- V4L2_SLICED_TELETEXT_NTSC_B |\
- V4L2_SLICED_TELETEXT_NTSC_C |\
- V4L2_SLICED_TELETEXT_NTSC_D)
-
-#define V4L2_SLICED_CAPTION (V4L2_SLICED_CAPTION_525 |\
- V4L2_SLICED_CAPTION_625)
-
-#define V4L2_SLICED_WSS (V4L2_SLICED_WSS_525 |\
- V4L2_SLICED_WSS_625)
-
-#define V4L2_SLICED_VITC (V4L2_SLICED_VITC_525 |\
- V4L2_SLICED_VITC_625)
-
-#define V4L2_SLICED_VBI_525 (V4L2_SLICED_TELETEXT_NTSC_B |\
- V4L2_SLICED_TELETEXT_NTSC_C |\
- V4L2_SLICED_TELETEXT_NTSC_D |\
- V4L2_SLICED_CAPTION_525 |\
- V4L2_SLICED_WSS_525 |\
- V4l2_SLICED_VITC_525)
-
-#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_PAL_B |\
- V4L2_SLICED_TELETEXT_PAL_C |\
- V4L2_SLICED_TELETEXT_SECAM |\
- V4L2_SLICED_VPS |\
- V4L2_SLICED_CAPTION_625 |\
- V4L2_SLICED_WSS_625 |\
- V4l2_SLICED_VITC_625)
+#define V4L2_SLICED_WSS_625 (0x4000)
+
+#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525)
+#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
+
struct v4l2_sliced_vbi_cap
{
diff --git a/include/linux/wanpipe.h b/include/linux/wanpipe.h
deleted file mode 100644
index dae9860091dd..000000000000
--- a/include/linux/wanpipe.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/*****************************************************************************
-* wanpipe.h WANPIPE(tm) Multiprotocol WAN Link Driver.
-* User-level API definitions.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Nov 3, 2000 Nenad Corbic Added config_id to sdla_t structure.
-* Used to determine the protocol running.
-* Jul 13, 2000 Nenad Corbic Added SyncPPP Support
-* Feb 24, 2000 Nenad Corbic Added support for x25api driver
-* Oct 04, 1999 Nenad Corbic New CHDLC and FRAME RELAY code, SMP support
-* Jun 02, 1999 Gideon Hack Added 'update_call_count' for Cisco HDLC
-* support
-* Jun 26, 1998 David Fong Added 'ip_mode' in sdla_t.u.p for dynamic IP
-* routing mode configuration
-* Jun 12, 1998 David Fong Added Cisco HDLC union member in sdla_t
-* Dec 08, 1997 Jaspreet Singh Added 'authenticator' in union of 'sdla_t'
-* Nov 26, 1997 Jaspreet Singh Added 'load_sharing' structure. Also added
-* 'devs_struct','dev_to_devtint_next' to 'sdla_t'
-* Nov 24, 1997 Jaspreet Singh Added 'irq_dis_if_send_count',
-* 'irq_dis_poll_count' to 'sdla_t'.
-* Nov 06, 1997 Jaspreet Singh Added a define called 'INTR_TEST_MODE'
-* Oct 20, 1997 Jaspreet Singh Added 'buff_intr_mode_unbusy' and
-* 'dlci_intr_mode_unbusy' to 'sdla_t'
-* Oct 18, 1997 Jaspreet Singh Added structure to maintain global driver
-* statistics.
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o added UDP management stuff
-* Jan 02, 1997 Gene Kozin Version 3.0.0
-*****************************************************************************/
-#ifndef _WANPIPE_H
-#define _WANPIPE_H
-
-#include <linux/wanrouter.h>
-
-/* Defines */
-
-#ifndef PACKED
-#define PACKED __attribute__((packed))
-#endif
-
-#define WANPIPE_MAGIC 0x414C4453L /* signature: 'SDLA' reversed */
-
-/* IOCTL numbers (up to 16) */
-#define WANPIPE_DUMP (ROUTER_USER+0) /* dump adapter's memory */
-#define WANPIPE_EXEC (ROUTER_USER+1) /* execute firmware command */
-
-#define TRACE_ALL 0x00
-#define TRACE_PROT 0x01
-#define TRACE_DATA 0x02
-
-/* values for request/reply byte */
-#define UDPMGMT_REQUEST 0x01
-#define UDPMGMT_REPLY 0x02
-#define UDP_OFFSET 12
-
-#define MAX_CMD_BUFF 10
-#define MAX_X25_LCN 255 /* Maximum number of x25 channels */
-#define MAX_LCN_NUM 4095 /* Maximum lcn number */
-#define MAX_FT1_RETRY 100
-
-#ifndef AF_WANPIPE
- #define AF_WANPIPE 25
- #ifndef PF_WANPIPE
- #define PF_WANPIPE AF_WANPIPE
- #endif
-#endif
-
-
-#define TX_TIMEOUT 5*HZ
-
-/* General Critical Flags */
-#define SEND_CRIT 0x00
-#define PERI_CRIT 0x01
-
-/* Chdlc and PPP polling critical flag */
-#define POLL_CRIT 0x03
-
-/* Frame Relay Tx IRQ send critical flag */
-#define SEND_TXIRQ_CRIT 0x02
-
-/* Frame Relay ARP critical flag */
-#define ARP_CRIT 0x03
-
-/* Bit maps for dynamic interface configuration
- * DYN_OPT_ON : turns this option on/off
- * DEV_DOWN : device was shutdown by the driver not
- * by user
- */
-#define DYN_OPT_ON 0x00
-#define DEV_DOWN 0x01
-
-/*
- * Data structures for IOCTL calls.
- */
-
-typedef struct sdla_dump /* WANPIPE_DUMP */
-{
- unsigned long magic; /* for verification */
- unsigned long offset; /* absolute adapter memory address */
- unsigned long length; /* block length */
- void* ptr; /* -> buffer */
-} sdla_dump_t;
-
-typedef struct sdla_exec /* WANPIPE_EXEC */
-{
- unsigned long magic; /* for verification */
- void* cmd; /* -> command structure */
- void* data; /* -> data buffer */
-} sdla_exec_t;
-
-/* UDP management stuff */
-
-typedef struct wum_header
-{
- unsigned char signature[8]; /* 00h: signature */
- unsigned char type; /* 08h: request/reply */
- unsigned char command; /* 09h: commnand */
- unsigned char reserved[6]; /* 0Ah: reserved */
-} wum_header_t;
-
-/*************************************************************************
- Data Structure for global statistics
-*************************************************************************/
-
-typedef struct global_stats
-{
- unsigned long isr_entry;
- unsigned long isr_already_critical;
- unsigned long isr_rx;
- unsigned long isr_tx;
- unsigned long isr_intr_test;
- unsigned long isr_spurious;
- unsigned long isr_enable_tx_int;
- unsigned long rx_intr_corrupt_rx_bfr;
- unsigned long rx_intr_on_orphaned_DLCI;
- unsigned long rx_intr_dev_not_started;
- unsigned long tx_intr_dev_not_started;
- unsigned long poll_entry;
- unsigned long poll_already_critical;
- unsigned long poll_processed;
- unsigned long poll_tbusy_bad_status;
- unsigned long poll_host_disable_irq;
- unsigned long poll_host_enable_irq;
-
-} global_stats_t;
-
-
-typedef struct{
- unsigned short udp_src_port PACKED;
- unsigned short udp_dst_port PACKED;
- unsigned short udp_length PACKED;
- unsigned short udp_checksum PACKED;
-} udp_pkt_t;
-
-
-typedef struct {
- unsigned char ver_inet_hdr_length PACKED;
- unsigned char service_type PACKED;
- unsigned short total_length PACKED;
- unsigned short identifier PACKED;
- unsigned short flags_frag_offset PACKED;
- unsigned char ttl PACKED;
- unsigned char protocol PACKED;
- unsigned short hdr_checksum PACKED;
- unsigned long ip_src_address PACKED;
- unsigned long ip_dst_address PACKED;
-} ip_pkt_t;
-
-
-typedef struct {
- unsigned char signature[8] PACKED;
- unsigned char request_reply PACKED;
- unsigned char id PACKED;
- unsigned char reserved[6] PACKED;
-} wp_mgmt_t;
-
-/*************************************************************************
- Data Structure for if_send statistics
-*************************************************************************/
-typedef struct if_send_stat{
- unsigned long if_send_entry;
- unsigned long if_send_skb_null;
- unsigned long if_send_broadcast;
- unsigned long if_send_multicast;
- unsigned long if_send_critical_ISR;
- unsigned long if_send_critical_non_ISR;
- unsigned long if_send_tbusy;
- unsigned long if_send_tbusy_timeout;
- unsigned long if_send_PIPE_request;
- unsigned long if_send_wan_disconnected;
- unsigned long if_send_dlci_disconnected;
- unsigned long if_send_no_bfrs;
- unsigned long if_send_adptr_bfrs_full;
- unsigned long if_send_bfr_passed_to_adptr;
- unsigned long if_send_protocol_error;
- unsigned long if_send_bfr_not_passed_to_adptr;
- unsigned long if_send_tx_int_enabled;
- unsigned long if_send_consec_send_fail;
-} if_send_stat_t;
-
-typedef struct rx_intr_stat{
- unsigned long rx_intr_no_socket;
- unsigned long rx_intr_dev_not_started;
- unsigned long rx_intr_PIPE_request;
- unsigned long rx_intr_bfr_not_passed_to_stack;
- unsigned long rx_intr_bfr_passed_to_stack;
-} rx_intr_stat_t;
-
-typedef struct pipe_mgmt_stat{
- unsigned long UDP_PIPE_mgmt_kmalloc_err;
- unsigned long UDP_PIPE_mgmt_direction_err;
- unsigned long UDP_PIPE_mgmt_adptr_type_err;
- unsigned long UDP_PIPE_mgmt_adptr_cmnd_OK;
- unsigned long UDP_PIPE_mgmt_adptr_cmnd_timeout;
- unsigned long UDP_PIPE_mgmt_adptr_send_passed;
- unsigned long UDP_PIPE_mgmt_adptr_send_failed;
- unsigned long UDP_PIPE_mgmt_not_passed_to_stack;
- unsigned long UDP_PIPE_mgmt_passed_to_stack;
- unsigned long UDP_PIPE_mgmt_no_socket;
- unsigned long UDP_PIPE_mgmt_passed_to_adptr;
-} pipe_mgmt_stat_t;
-
-
-typedef struct {
- struct sk_buff *skb;
-} bh_data_t, cmd_data_t;
-
-#define MAX_LGTH_UDP_MGNT_PKT 2000
-
-
-/* This is used for interrupt testing */
-#define INTR_TEST_MODE 0x02
-
-#define WUM_SIGNATURE_L 0x50495046
-#define WUM_SIGNATURE_H 0x444E3845
-
-#define WUM_KILL 0x50
-#define WUM_EXEC 0x51
-
-#define WANPIPE 0x00
-#define API 0x01
-#define BRIDGE 0x02
-#define BRIDGE_NODE 0x03
-
-#ifdef __KERNEL__
-/****** Kernel Interface ****************************************************/
-
-#include <linux/sdladrv.h> /* SDLA support module API definitions */
-#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
-#include <linux/workqueue.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-
-/****** Data Structures *****************************************************/
-
-/* Adapter Data Space.
- * This structure is needed because we handle multiple cards, otherwise
- * static data would do it.
- */
-typedef struct sdla
-{
- char devname[WAN_DRVNAME_SZ+1]; /* card name */
- sdlahw_t hw; /* hardware configuration */
- struct wan_device wandev; /* WAN device data space */
-
- unsigned open_cnt; /* number of open interfaces */
- unsigned long state_tick; /* link state timestamp */
- unsigned intr_mode; /* Type of Interrupt Mode */
- char in_isr; /* interrupt-in-service flag */
- char buff_int_mode_unbusy; /* flag for carrying out dev_tint */
- char dlci_int_mode_unbusy; /* flag for carrying out dev_tint */
- long configured; /* flag for previous configurations */
-
- unsigned short irq_dis_if_send_count; /* Disabling irqs in if_send*/
- unsigned short irq_dis_poll_count; /* Disabling irqs in poll routine*/
- unsigned short force_enable_irq;
- char TracingEnabled; /* flag for enabling trace */
- global_stats_t statistics; /* global statistics */
- void* mbox; /* -> mailbox */
- void* rxmb; /* -> receive mailbox */
- void* flags; /* -> adapter status flags */
- void (*isr)(struct sdla* card); /* interrupt service routine */
- void (*poll)(struct sdla* card); /* polling routine */
- int (*exec)(struct sdla* card, void* u_cmd, void* u_data);
- /* Used by the listen() system call */
- /* Wanpipe Socket Interface */
- int (*func) (struct sk_buff *, struct sock *);
- struct sock *sk;
-
- /* Shutdown function */
- void (*disable_comm) (struct sdla *card);
-
- /* Secondary Port Device: Piggibacking */
- struct sdla *next;
-
- /* TTY driver variables */
- unsigned char tty_opt;
- struct tty_struct *tty;
- unsigned int tty_minor;
- unsigned int tty_open;
- unsigned char *tty_buf;
- unsigned char *tty_rx;
- struct work_struct tty_work;
-
- union
- {
- struct
- { /****** X.25 specific data **********/
- u32 lo_pvc;
- u32 hi_pvc;
- u32 lo_svc;
- u32 hi_svc;
- struct net_device *svc_to_dev_map[MAX_X25_LCN];
- struct net_device *pvc_to_dev_map[MAX_X25_LCN];
- struct net_device *tx_dev;
- struct net_device *cmd_dev;
- u32 no_dev;
- volatile u8 *hdlc_buf_status;
- u32 tx_interrupts_pending;
- u16 timer_int_enabled;
- struct net_device *poll_device;
- atomic_t command_busy;
-
- u16 udp_pkt_lgth;
- u32 udp_type;
- u8 udp_pkt_src;
- u32 udp_lcn;
- struct net_device *udp_dev;
- s8 udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-
- u8 LAPB_hdlc; /* Option to turn off X25 and run only LAPB */
- u8 logging; /* Option to log call messages */
- u8 oob_on_modem; /* Option to send modem status to the api */
- u16 num_of_ch; /* Number of channels configured by the user */
-
- struct work_struct x25_poll_work;
- struct timer_list x25_timer;
- } x;
- struct
- { /****** frame relay specific data ***/
- void* rxmb_base; /* -> first Rx buffer */
- void* rxmb_last; /* -> last Rx buffer */
- unsigned rx_base; /* S508 receive buffer base */
- unsigned rx_top; /* S508 receive buffer end */
- unsigned short node_dlci[100];
- unsigned short dlci_num;
- struct net_device *dlci_to_dev_map[991 + 1];
- unsigned tx_interrupts_pending;
- unsigned short timer_int_enabled;
- unsigned short udp_pkt_lgth;
- int udp_type;
- char udp_pkt_src;
- unsigned udp_dlci;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- void* trc_el_base; /* first trace element */
- void* trc_el_last; /* last trace element */
- void *curr_trc_el; /* current trace element */
- unsigned short trc_bfr_space; /* trace buffer space */
- unsigned char update_comms_stats;
- struct net_device *arp_dev;
- spinlock_t if_send_lock;
- } f;
- struct /****** PPP-specific data ***********/
- {
- char if_name[WAN_IFNAME_SZ+1]; /* interface name */
- void* txbuf; /* -> current Tx buffer */
- void* txbuf_base; /* -> first Tx buffer */
- void* txbuf_last; /* -> last Tx buffer */
- void* rxbuf_base; /* -> first Rx buffer */
- void* rxbuf_last; /* -> last Rx buffer */
- unsigned rx_base; /* S508 receive buffer base */
- unsigned rx_top; /* S508 receive buffer end */
- char ip_mode; /* STATIC/HOST/PEER IP Mode */
- char authenticator; /* Authenticator for PAP/CHAP */
- unsigned char comm_enabled; /* Is comm enabled or not */
- unsigned char peer_route; /* Process Peer Route */
- unsigned long *txbuf_next; /* Next Tx buffer to use */
- unsigned long *rxbuf_next; /* Next Rx buffer to use */
- } p;
- struct /* Cisco HDLC-specific data */
- {
- char if_name[WAN_IFNAME_SZ+1]; /* interface name */
- unsigned char comm_port;/* Communication Port O or 1 */
- unsigned char usedby; /* Used by WANPIPE or API */
- void* rxmb; /* Receive mail box */
- void* flags; /* flags */
- void* tx_status; /* Tx status element */
- void* rx_status; /* Rx status element */
- void* txbuf; /* -> current Tx buffer */
- void* txbuf_base; /* -> first Tx buffer */
- void* txbuf_last; /* -> last Tx buffer */
- void* rxbuf_base; /* -> first Rx buffer */
- void* rxbuf_last; /* -> last Rx buffer */
- unsigned rx_base; /* S508 receive buffer base */
- unsigned rx_top; /* S508 receive buffer end */
- unsigned char receive_only; /* high speed receivers */
- unsigned short protocol_options;
- unsigned short kpalv_tx; /* Tx kpalv timer */
- unsigned short kpalv_rx; /* Rx kpalv timer */
- unsigned short kpalv_err; /* Error tolerance */
- unsigned short slarp_timer; /* SLARP req timer */
- unsigned state; /* state of the link */
- unsigned char api_status;
- unsigned char update_call_count;
- unsigned short api_options; /* for async config */
- unsigned char async_mode;
- unsigned short tx_bits_per_char;
- unsigned short rx_bits_per_char;
- unsigned short stop_bits;
- unsigned short parity;
- unsigned short break_timer;
- unsigned short inter_char_timer;
- unsigned short rx_complete_length;
- unsigned short xon_char;
- unsigned short xoff_char;
- unsigned char comm_enabled; /* Is comm enabled or not */
- unsigned char backup;
- } c;
- struct
- {
- void* tx_status; /* Tx status element */
- void* rx_status; /* Rx status element */
- void* trace_status; /* Trace status element */
- void* txbuf; /* -> current Tx buffer */
- void* txbuf_base; /* -> first Tx buffer */
- void* txbuf_last; /* -> last Tx buffer */
- void* rxbuf_base; /* -> first Rx buffer */
- void* rxbuf_last; /* -> last Rx buffer */
- void* tracebuf; /* -> current Trace buffer */
- void* tracebuf_base; /* -> current Trace buffer */
- void* tracebuf_last; /* -> current Trace buffer */
- unsigned rx_base; /* receive buffer base */
- unsigned rx_end; /* receive buffer end */
- unsigned trace_base; /* trace buffer base */
- unsigned trace_end; /* trace buffer end */
-
- } h;
- } u;
-} sdla_t;
-
-/****** Public Functions ****************************************************/
-
-void wanpipe_open (sdla_t* card); /* wpmain.c */
-void wanpipe_close (sdla_t* card); /* wpmain.c */
-void wanpipe_set_state (sdla_t* card, int state); /* wpmain.c */
-
-int wpx_init (sdla_t* card, wandev_conf_t* conf); /* wpx.c */
-int wpf_init (sdla_t* card, wandev_conf_t* conf); /* wpf.c */
-int wpp_init (sdla_t* card, wandev_conf_t* conf); /* wpp.c */
-int wpc_init (sdla_t* card, wandev_conf_t* conf); /* Cisco HDLC */
-int bsc_init (sdla_t* card, wandev_conf_t* conf); /* BSC streaming */
-int hdlc_init(sdla_t* card, wandev_conf_t* conf); /* HDLC support */
-int wpft1_init (sdla_t* card, wandev_conf_t* conf); /* FT1 Config support */
-int wsppp_init (sdla_t* card, wandev_conf_t* conf); /* Sync PPP on top of RAW CHDLC */
-
-extern sdla_t * wanpipe_find_card(char *);
-extern sdla_t * wanpipe_find_card_num (int);
-
-extern void wanpipe_queue_work (struct work_struct *);
-extern void wanpipe_mark_bh (void);
-extern void wakeup_sk_bh(struct net_device *dev);
-extern int change_dev_flags(struct net_device *dev, unsigned flags);
-extern unsigned long get_ip_address(struct net_device *dev, int option);
-extern void add_gateway(sdla_t *card, struct net_device *dev);
-
-
-#endif /* __KERNEL__ */
-#endif /* _WANPIPE_H */
-
diff --git a/include/media/cx25840.h b/include/media/cx25840.h
new file mode 100644
index 000000000000..8e7e52d659a0
--- /dev/null
+++ b/include/media/cx25840.h
@@ -0,0 +1,64 @@
+/*
+ cx25840.h - definition for cx25840/1/2/3 inputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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 _CX25840_H_
+#define _CX25840_H_
+
+enum cx25840_video_input {
+ /* Composite video inputs In1-In8 */
+ CX25840_COMPOSITE1 = 1,
+ CX25840_COMPOSITE2,
+ CX25840_COMPOSITE3,
+ CX25840_COMPOSITE4,
+ CX25840_COMPOSITE5,
+ CX25840_COMPOSITE6,
+ CX25840_COMPOSITE7,
+ CX25840_COMPOSITE8,
+
+ /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+ chroma input (In5-In8) */
+ CX25840_SVIDEO_LUMA1 = 0x10,
+ CX25840_SVIDEO_LUMA2 = 0x20,
+ CX25840_SVIDEO_LUMA3 = 0x30,
+ CX25840_SVIDEO_LUMA4 = 0x40,
+ CX25840_SVIDEO_CHROMA4 = 0x400,
+ CX25840_SVIDEO_CHROMA5 = 0x500,
+ CX25840_SVIDEO_CHROMA6 = 0x600,
+ CX25840_SVIDEO_CHROMA7 = 0x700,
+ CX25840_SVIDEO_CHROMA8 = 0x800,
+
+ /* S-Video aliases for common luma/chroma combinations */
+ CX25840_SVIDEO1 = 0x510,
+ CX25840_SVIDEO2 = 0x620,
+ CX25840_SVIDEO3 = 0x730,
+ CX25840_SVIDEO4 = 0x840,
+};
+
+enum cx25840_audio_input {
+ /* Audio inputs: serial or In4-In8 */
+ CX25840_AUDIO_SERIAL,
+ CX25840_AUDIO4 = 4,
+ CX25840_AUDIO5,
+ CX25840_AUDIO6,
+ CX25840_AUDIO7,
+ CX25840_AUDIO8,
+};
+
+#endif
diff --git a/include/media/msp3400.h b/include/media/msp3400.h
index 0be61a021d45..6ab854931c05 100644
--- a/include/media/msp3400.h
+++ b/include/media/msp3400.h
@@ -80,16 +80,16 @@
*/
/* SCART input to DSP selection */
-#define MSP_IN_SCART_1 0 /* Pin SC1_IN */
-#define MSP_IN_SCART_2 1 /* Pin SC2_IN */
-#define MSP_IN_SCART_3 2 /* Pin SC3_IN */
-#define MSP_IN_SCART_4 3 /* Pin SC4_IN */
+#define MSP_IN_SCART1 0 /* Pin SC1_IN */
+#define MSP_IN_SCART2 1 /* Pin SC2_IN */
+#define MSP_IN_SCART3 2 /* Pin SC3_IN */
+#define MSP_IN_SCART4 3 /* Pin SC4_IN */
#define MSP_IN_MONO 6 /* Pin MONO_IN */
#define MSP_IN_MUTE 7 /* Mute DSP input */
#define MSP_SCART_TO_DSP(in) (in)
/* Tuner input to demodulator and DSP selection */
-#define MSP_IN_TUNER_1 0 /* Analog Sound IF input pin ANA_IN1 */
-#define MSP_IN_TUNER_2 1 /* Analog Sound IF input pin ANA_IN2 */
+#define MSP_IN_TUNER1 0 /* Analog Sound IF input pin ANA_IN1 */
+#define MSP_IN_TUNER2 1 /* Analog Sound IF input pin ANA_IN2 */
#define MSP_TUNER_TO_DSP(in) ((in) << 3)
/* The msp has up to 5 DSP outputs, each output can independently select
@@ -109,14 +109,14 @@
DSP. This is currently not implemented. Also not implemented is the
multi-channel capable I2S3 input of the 44x0G. If someone can demonstrate
a need for one of those features then additional support can be added. */
-#define MSP_DSP_OUT_TUNER 0 /* Tuner output */
-#define MSP_DSP_OUT_SCART 2 /* SCART output */
-#define MSP_DSP_OUT_I2S1 5 /* I2S1 output */
-#define MSP_DSP_OUT_I2S2 6 /* I2S2 output */
-#define MSP_DSP_OUT_I2S3 7 /* I2S3 output */
-#define MSP_DSP_OUT_MAIN_AVC 11 /* MAIN AVC processed output */
-#define MSP_DSP_OUT_MAIN 12 /* MAIN output */
-#define MSP_DSP_OUT_AUX 13 /* AUX output */
+#define MSP_DSP_IN_TUNER 0 /* Tuner DSP input */
+#define MSP_DSP_IN_SCART 2 /* SCART DSP input */
+#define MSP_DSP_IN_I2S1 5 /* I2S1 DSP input */
+#define MSP_DSP_IN_I2S2 6 /* I2S2 DSP input */
+#define MSP_DSP_IN_I2S3 7 /* I2S3 DSP input */
+#define MSP_DSP_IN_MAIN_AVC 11 /* MAIN AVC processed DSP input */
+#define MSP_DSP_IN_MAIN 12 /* MAIN DSP input */
+#define MSP_DSP_IN_AUX 13 /* AUX DSP input */
#define MSP_DSP_TO_MAIN(in) ((in) << 4)
#define MSP_DSP_TO_AUX(in) ((in) << 8)
#define MSP_DSP_TO_SCART1(in) ((in) << 12)
@@ -125,16 +125,16 @@
/* Output SCART select: the SCART outputs can select which input
to use. */
-#define MSP_OUT_SCART1 0 /* SCART1 input, bypassing the DSP */
-#define MSP_OUT_SCART2 1 /* SCART2 input, bypassing the DSP */
-#define MSP_OUT_SCART3 2 /* SCART3 input, bypassing the DSP */
-#define MSP_OUT_SCART4 3 /* SCART4 input, bypassing the DSP */
-#define MSP_OUT_SCART1_DA 4 /* DSP SCART1 output */
-#define MSP_OUT_SCART2_DA 5 /* DSP SCART2 output */
-#define MSP_OUT_MONO 6 /* MONO input, bypassing the DSP */
-#define MSP_OUT_MUTE 7 /* MUTE output */
-#define MSP_OUT_TO_SCART1(in) (in)
-#define MSP_OUT_TO_SCART2(in) ((in) << 4)
+#define MSP_SC_IN_SCART1 0 /* SCART1 input, bypassing the DSP */
+#define MSP_SC_IN_SCART2 1 /* SCART2 input, bypassing the DSP */
+#define MSP_SC_IN_SCART3 2 /* SCART3 input, bypassing the DSP */
+#define MSP_SC_IN_SCART4 3 /* SCART4 input, bypassing the DSP */
+#define MSP_SC_IN_DSP_SCART1 4 /* DSP SCART1 input */
+#define MSP_SC_IN_DSP_SCART2 5 /* DSP SCART2 input */
+#define MSP_SC_IN_MONO 6 /* MONO input, bypassing the DSP */
+#define MSP_SC_IN_MUTE 7 /* MUTE output */
+#define MSP_SC_TO_SCART1(in) (in)
+#define MSP_SC_TO_SCART2(in) ((in) << 4)
/* Shortcut macros */
#define MSP_INPUT(sc, t, main_aux_src, sc_i2s_src) \
@@ -145,14 +145,14 @@
MSP_DSP_TO_SCART1(sc_i2s_src) | \
MSP_DSP_TO_SCART2(sc_i2s_src) | \
MSP_DSP_TO_I2S(sc_i2s_src))
-#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, \
- MSP_DSP_OUT_TUNER, MSP_DSP_OUT_TUNER)
+#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+ MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER)
#define MSP_OUTPUT(sc) \
- (MSP_OUT_TO_SCART1(sc) | \
- MSP_OUT_TO_SCART2(sc))
+ (MSP_SC_TO_SCART1(sc) | \
+ MSP_SC_TO_SCART2(sc))
/* This equals the RESET position of the msp3400 ACB register */
-#define MSP_OUTPUT_DEFAULT (MSP_OUT_TO_SCART1(MSP_OUT_SCART3) | \
- MSP_OUT_TO_SCART2(MSP_OUT_SCART1_DA))
+#define MSP_OUTPUT_DEFAULT (MSP_SC_TO_SCART1(MSP_SC_IN_SCART3) | \
+ MSP_SC_TO_SCART2(MSP_SC_IN_DSP_SCART1))
/* Tuner inputs vs. msp version */
/* Chip TUNER_1 TUNER_2
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
new file mode 100644
index 000000000000..6b4836f3f057
--- /dev/null
+++ b/include/media/saa7115.h
@@ -0,0 +1,37 @@
+/*
+ saa7115.h - definition for saa7113/4/5 inputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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 _SAA7115_H_
+#define _SAA7115_H_
+
+/* SAA7113/4/5 HW inputs */
+#define SAA7115_COMPOSITE0 0
+#define SAA7115_COMPOSITE1 1
+#define SAA7115_COMPOSITE2 2
+#define SAA7115_COMPOSITE3 3
+#define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */
+#define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */
+#define SAA7115_SVIDEO0 6
+#define SAA7115_SVIDEO1 7
+#define SAA7115_SVIDEO2 8
+#define SAA7115_SVIDEO3 9
+
+#endif
+
diff --git a/include/media/saa7127.h b/include/media/saa7127.h
new file mode 100644
index 000000000000..bbcf862141af
--- /dev/null
+++ b/include/media/saa7127.h
@@ -0,0 +1,41 @@
+/*
+ saa7127.h - definition for saa7126/7/8/9 inputs/outputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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 _SAA7127_H_
+#define _SAA7127_H_
+
+/* Enumeration for the supported input types */
+enum saa7127_input_type {
+ SAA7127_INPUT_TYPE_NORMAL,
+ SAA7127_INPUT_TYPE_TEST_IMAGE
+};
+
+/* Enumeration for the supported output signal types */
+enum saa7127_output_type {
+ SAA7127_OUTPUT_TYPE_BOTH,
+ SAA7127_OUTPUT_TYPE_COMPOSITE,
+ SAA7127_OUTPUT_TYPE_SVIDEO,
+ SAA7127_OUTPUT_TYPE_RGB,
+ SAA7127_OUTPUT_TYPE_YUV_C,
+ SAA7127_OUTPUT_TYPE_YUV_V
+};
+
+#endif
+
diff --git a/include/media/upd64031a.h b/include/media/upd64031a.h
new file mode 100644
index 000000000000..3ad6a32e1bce
--- /dev/null
+++ b/include/media/upd64031a.h
@@ -0,0 +1,40 @@
+/*
+ * upd64031a - NEC Electronics Ghost Reduction input defines
+ *
+ * 2006 by Hans Verkuil (hverkuil@xs4all.nl)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _UPD64031A_H_
+#define _UPD64031A_H_
+
+/* Ghost reduction modes */
+#define UPD64031A_GR_ON 0
+#define UPD64031A_GR_OFF 1
+#define UPD64031A_GR_THROUGH 3
+
+/* Direct 3D/YCS Connection */
+#define UPD64031A_3DYCS_DISABLE (0 << 2)
+#define UPD64031A_3DYCS_COMPOSITE (2 << 2)
+#define UPD64031A_3DYCS_SVIDEO (3 << 2)
+
+/* Composite sync digital separation circuit */
+#define UPD64031A_COMPOSITE_EXTERNAL (1 << 4)
+
+/* Vertical sync digital separation circuit */
+#define UPD64031A_VERTICAL_EXTERNAL (1 << 5)
+
+#endif
diff --git a/include/media/upd64083.h b/include/media/upd64083.h
new file mode 100644
index 000000000000..59b6f32ba300
--- /dev/null
+++ b/include/media/upd64083.h
@@ -0,0 +1,58 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation input defines
+ *
+ * 2006 by Hans Verkuil (hverkuil@xs4all.nl)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _UPD64083_H_
+#define _UPD64083_H_
+
+/* There are two bits of information that the driver needs in order
+ to select the correct routing: the operating mode and the selection
+ of the Y input (external or internal).
+
+ The first two operating modes expect a composite signal on the Y input,
+ the second two operating modes use both the Y and C inputs.
+
+ Normally YCS_MODE is used for tuner and composite inputs, and the
+ YCNR mode is used for S-Video inputs.
+
+ The external Y-ADC is selected when the composite input comes from a
+ upd64031a ghost reduction device. If this device is not present, or
+ the input is a S-Video signal, then the internal Y-ADC input should
+ be used. */
+
+/* Operating modes: */
+
+/* YCS mode: Y/C separation (burst locked clocking) */
+#define UPD64083_YCS_MODE 0
+/* YCS+ mode: 2D Y/C separation and YCNR (burst locked clocking) */
+#define UPD64083_YCS_PLUS_MODE 1
+
+/* Note: the following two modes cannot be used in combination with the
+ external Y-ADC. */
+/* MNNR mode: frame comb type YNR+C delay (line locked clocking) */
+#define UPD64083_MNNR_MODE 2
+/* YCNR mode: frame recursive YCNR (burst locked clocking) */
+#define UPD64083_YCNR_MODE 3
+
+/* Select external Y-ADC: this should be set if this device is used in
+ combination with the upd64031a ghost reduction device.
+ Otherwise leave at 0 (use internal Y-ADC). */
+#define UPD64083_EXT_Y_ADC (1 << 2)
+
+#endif
diff --git a/include/net/arp.h b/include/net/arp.h
index a13e30c35f42..643bded9f557 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -10,8 +10,6 @@
extern struct neigh_table arp_tbl;
extern void arp_init(void);
-extern int arp_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev);
extern int arp_find(unsigned char *haddr, struct sk_buff *skb);
extern int arp_ioctl(unsigned int cmd, void __user *arg);
extern void arp_send(int type, int ptype, u32 dest_ip,
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index b971d8c82bdd..b1ebfbae397f 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -96,10 +96,13 @@ struct ieee80211softmac_assoc_info {
*
* bssvalid is true if we found a matching network
* and saved it's BSSID into the bssid above.
+ *
+ * bssfixed is used for SIOCSIWAP.
*/
u8 static_essid:1,
associating:1,
- bssvalid:1;
+ bssvalid:1,
+ bssfixed:1;
/* Scan retries remaining */
int scan_retry;
@@ -267,8 +270,9 @@ extern void ieee80211softmac_stop(struct net_device *dev);
#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5
#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6
#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7
+#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED 8
/* keep this updated! */
-#define IEEE80211SOFTMAC_EVENT_LAST 7
+#define IEEE80211SOFTMAC_EVENT_LAST 8
/*
* If you want to be notified of certain events, you can call
* ieee80211softmac_notify[_atomic] with
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 25f708ff020e..59f0c83d55a2 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -48,31 +48,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(laddr, lport, faddr, fport);
}
-static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
- struct sock *sk)
-{
- struct hlist_head *list;
- rwlock_t *lock;
-
- BUG_TRAP(sk_unhashed(sk));
-
- if (sk->sk_state == TCP_LISTEN) {
- list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
- lock = &hashinfo->lhash_lock;
- inet_listen_wlock(hashinfo);
- } else {
- unsigned int hash;
- sk->sk_hash = hash = inet6_sk_ehashfn(sk);
- hash &= (hashinfo->ehash_size - 1);
- list = &hashinfo->ehash[hash].chain;
- lock = &hashinfo->ehash[hash].lock;
- write_lock(lock);
- }
-
- __sk_add_node(sk, list);
- sock_prot_inc_use(sk->sk_prot);
- write_unlock(lock);
-}
+extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
@@ -80,52 +56,12 @@ static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
*
* The sockhash lock must be held as a reader here.
*/
-static inline struct sock *
- __inet6_lookup_established(struct inet_hashinfo *hashinfo,
+extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const u16 sport,
const struct in6_addr *daddr,
const u16 hnum,
- const int dif)
-{
- struct sock *sk;
- const struct hlist_node *node;
- const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
- /* Optimize here for direct hit, only listening connections can
- * have wildcards anyways.
- */
- unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
- struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
-
- prefetch(head->chain.first);
- read_lock(&head->lock);
- sk_for_each(sk, node, &head->chain) {
- /* For IPV6 do the cheaper port and family tests first. */
- if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
- goto hit; /* You sunk my battleship! */
- }
- /* Must check for a TIME_WAIT'er before going to listener hash. */
- sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
- const struct inet_timewait_sock *tw = inet_twsk(sk);
-
- if(*((__u32 *)&(tw->tw_dport)) == ports &&
- sk->sk_family == PF_INET6) {
- const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
-
- if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
- ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
- (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
- goto hit;
- }
- }
- read_unlock(&head->lock);
- return NULL;
-
-hit:
- sock_hold(sk);
- read_unlock(&head->lock);
- return sk;
-}
+ const int dif);
extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
diff --git a/include/net/ip.h b/include/net/ip.h
index 8fe6156ca9b0..3d2e5ca62a5a 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb);
extern int ip_mr_input(struct sk_buff *skb);
extern int ip_output(struct sk_buff *skb);
extern int ip_mc_output(struct sk_buff *skb);
+extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
extern int ip_do_nat(struct sk_buff *skb);
extern void ip_send_check(struct iphdr *ip);
extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 6d6f0634ae41..4abedb8eaece 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -230,7 +230,7 @@ extern int ip6_ra_control(struct sock *sk, int sel,
void (*destructor)(struct sock *));
-extern int ipv6_parse_hopopts(struct sk_buff *skb, int);
+extern int ipv6_parse_hopopts(struct sk_buff *skb);
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
diff --git a/include/net/sock.h b/include/net/sock.h
index af2b0544586e..ff8b0dad7b0f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -454,6 +454,7 @@ static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk)
static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
{
+ skb_truesize_check(skb);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk->sk_wmem_queued -= skb->truesize;
sk->sk_forward_alloc += skb->truesize;
diff --git a/include/net/x25device.h b/include/net/x25device.h
index 1a318374faef..1d10c879f7e2 100644
--- a/include/net/x25device.h
+++ b/include/net/x25device.h
@@ -8,6 +8,7 @@
static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->mac.raw = skb->data;
+ skb->dev = dev;
skb->pkt_type = PACKET_HOST;
return htons(ETH_P_X25);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e100291e43f4..afa508d92c93 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -143,6 +143,11 @@ struct xfrm_state
/* Replay detection state at the time we sent the last notification */
struct xfrm_replay_state preplay;
+ /* internal flag that only holds state for delayed aevent at the
+ * moment
+ */
+ u32 xflags;
+
/* Replay detection notification settings */
u32 replay_maxage;
u32 replay_maxdiff;
@@ -168,6 +173,9 @@ struct xfrm_state
void *data;
};
+/* xflags - make enum if more show up */
+#define XFRM_TIME_DEFER 1
+
enum {
XFRM_STATE_VOID,
XFRM_STATE_ACQ,
@@ -242,7 +250,6 @@ extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
-struct xfrm_decap_state;
struct xfrm_type
{
char *description;
@@ -251,7 +258,7 @@ struct xfrm_type
int (*init_state)(struct xfrm_state *x);
void (*destructor)(struct xfrm_state *);
- int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
+ int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
/* Estimate maximal size of result of transformation of a dgram */
u32 (*get_max_size)(struct xfrm_state *, int size);
@@ -606,25 +613,11 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
-/* Decapsulation state, used by the input to store data during
- * decapsulation procedure, to be used later (during the policy
- * check
- */
-struct xfrm_decap_state {
- char decap_data[20];
- __u16 decap_type;
-};
-
-struct sec_decap_state {
- struct xfrm_state *xvec;
- struct xfrm_decap_state decap;
-};
-
struct sec_path
{
atomic_t refcnt;
int len;
- struct sec_decap_state x[XFRM_MAX_DEPTH];
+ struct xfrm_state *xvec[XFRM_MAX_DEPTH];
};
static inline struct sec_path *
diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h
index b53b78d497ba..6bc7472293b2 100644
--- a/include/pcmcia/bulkmem.h
+++ b/include/pcmcia/bulkmem.h
@@ -35,7 +35,7 @@ typedef struct region_info_t {
#define REGION_BAR_MASK 0xe000
#define REGION_BAR_SHIFT 13
-int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn);
-int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn);
+int pcmcia_get_first_region(struct pcmcia_device *handle, region_info_t *rgn);
+int pcmcia_get_next_region(struct pcmcia_device *handle, region_info_t *rgn);
#endif /* _LINUX_BULKMEM_H */
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index da19c297dd65..c1da8558339a 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -1,5 +1,5 @@
/*
- * ciscode.h -- Definitions for bulk memory services
+ * ciscode.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -122,4 +122,7 @@
#define MANFID_XIRCOM 0x0105
+#define MANFID_POSSIO 0x030c
+#define PRODID_POSSIO_GCC 0x0003
+
#endif /* _LINUX_CISCODE_H */
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h
index c6a069554fd7..d3bbb19caf81 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -586,12 +586,7 @@ typedef struct cisdump_t {
cisdata_t Data[CISTPL_MAX_CIS_SIZE];
} cisdump_t;
-int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple);
-int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse);
-int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info);
int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
/* don't use outside of PCMCIA core yet */
@@ -602,4 +597,20 @@ int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse);
int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info);
+/* ... but use these wrappers instead */
+#define pcmcia_get_first_tuple(p_dev, tuple) \
+ pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_next_tuple(p_dev, tuple) \
+ pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_tuple_data(p_dev, tuple) \
+ pccard_get_tuple_data(p_dev->socket, tuple)
+
+#define pcmcia_parse_tuple(p_dev, tuple, parse) \
+ pccard_parse_tuple(tuple, parse)
+
+#define pcmcia_validate_cis(p_dev, info) \
+ pccard_validate_cis(p_dev->socket, p_dev->func, info)
+
#endif /* LINUX_CISTPL_H */
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 52660f32663d..d5838c30d20f 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -109,17 +109,6 @@ typedef struct client_req_t {
#define CLIENT_THIS_SOCKET 0x01
-/* For RegisterClient */
-typedef struct client_reg_t {
- dev_info_t *dev_info;
- u_int Attributes; /* UNUSED */
- u_int EventMask;
- int (*event_handler)(event_t event, int priority,
- event_callback_args_t *);
- event_callback_args_t event_callback_args;
- u_int Version;
-} client_reg_t;
-
/* ModifyConfiguration */
typedef struct modconf_t {
u_int Attributes;
@@ -127,15 +116,16 @@ typedef struct modconf_t {
} modconf_t;
/* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID 0x100
-#define CONF_VCC_CHANGE_VALID 0x200
-#define CONF_VPP1_CHANGE_VALID 0x400
-#define CONF_VPP2_CHANGE_VALID 0x800
+#define CONF_IRQ_CHANGE_VALID 0x0100
+#define CONF_VCC_CHANGE_VALID 0x0200
+#define CONF_VPP1_CHANGE_VALID 0x0400
+#define CONF_VPP2_CHANGE_VALID 0x0800
+#define CONF_IO_CHANGE_WIDTH 0x1000
/* For RequestConfiguration */
typedef struct config_req_t {
u_int Attributes;
- u_int Vcc, Vpp1, Vpp2;
+ u_int Vpp; /* both Vpp1 and Vpp2 */
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, ExtStatus;
@@ -389,23 +379,27 @@ int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status);
int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
-int pcmcia_release_configuration(struct pcmcia_device *p_dev);
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);
int pcmcia_release_window(window_handle_t win);
int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req);
int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh);
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req);
int pcmcia_suspend_card(struct pcmcia_socket *skt);
int pcmcia_resume_card(struct pcmcia_socket *skt);
int pcmcia_eject_card(struct pcmcia_socket *skt);
int pcmcia_insert_card(struct pcmcia_socket *skt);
+int pccard_reset_card(struct pcmcia_socket *skt);
+
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *p_dev);
+void pcmcia_disable_device(struct pcmcia_device *p_dev);
struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt);
void pcmcia_put_socket(struct pcmcia_socket *skt);
+/* compatibility functions */
+#define pcmcia_reset_card(p_dev, req) \
+ pccard_reset_card(p_dev->socket)
+
#endif /* __KERNEL__ */
#endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 8e2a96396478..8c339f5678cf 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -39,7 +39,7 @@ typedef struct win_info_t {
typedef struct bind_info_t {
dev_info_t dev_info;
u_char function;
- struct dev_link_t *instance;
+ struct pcmcia_device *instance;
char name[DEV_NAME_LEN];
u_short major, minor;
void *next;
@@ -96,6 +96,7 @@ typedef union ds_ioctl_arg_t {
#ifdef __KERNEL__
#include <linux/device.h>
+#include <pcmcia/ss.h>
typedef struct dev_node_t {
char dev_name[DEV_NAME_LEN];
@@ -103,34 +104,9 @@ typedef struct dev_node_t {
struct dev_node_t *next;
} dev_node_t;
-typedef struct dev_link_t {
- dev_node_t *dev;
- u_int state, open;
- wait_queue_head_t pending;
- client_handle_t handle;
- io_req_t io;
- irq_req_t irq;
- config_req_t conf;
- window_handle_t win;
- void *priv;
- struct dev_link_t *next;
-} dev_link_t;
-
-/* Flags for device state */
-#define DEV_PRESENT 0x01
-#define DEV_CONFIG 0x02
-#define DEV_STALE_CONFIG 0x04 /* release on close */
-#define DEV_STALE_LINK 0x08 /* detach on release */
-#define DEV_CONFIG_PENDING 0x10
-#define DEV_RELEASE_PENDING 0x20
-#define DEV_SUSPEND 0x40
-#define DEV_BUSY 0x80
-
-#define DEV_OK(l) \
- ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
-
struct pcmcia_socket;
+struct config_t;
struct pcmcia_driver {
int (*probe) (struct pcmcia_device *dev);
@@ -148,6 +124,7 @@ struct pcmcia_driver {
int pcmcia_register_driver(struct pcmcia_driver *driver);
void pcmcia_unregister_driver(struct pcmcia_driver *driver);
+
struct pcmcia_device {
/* the socket and the device_no [for multifunction devices]
uniquely define a pcmcia_device */
@@ -160,21 +137,40 @@ struct pcmcia_device {
/* the hardware "function" device; certain subdevices can
* share one hardware "function" device. */
u8 func;
+ struct config_t* function_config;
struct list_head socket_device_list;
- /* deprecated, a cleaned up version will be moved into this
- struct soon */
- dev_link_t *instance;
- u_int state;
+ /* deprecated, will be cleaned up soon */
+ dev_node_t *dev_node;
+ u_int open;
+ io_req_t io;
+ irq_req_t irq;
+ config_req_t conf;
+ window_handle_t win;
+
+ /* Is the device suspended, or in the process of
+ * being removed? */
+ u16 suspended:1;
+ u16 _removed:1;
+
+ /* Flags whether io, irq, win configurations were
+ * requested, and whether the configuration is "locked" */
+ u16 _irq:1;
+ u16 _io:1;
+ u16 _win:4;
+ u16 _locked:1;
+
+ /* Flag whether a "fuzzy" func_id based match is
+ * allowed. */
+ u16 allow_func_id_match:1;
/* information about this device */
- u8 has_manf_id:1;
- u8 has_card_id:1;
- u8 has_func_id:1;
+ u16 has_manf_id:1;
+ u16 has_card_id:1;
+ u16 has_func_id:1;
- u8 allow_func_id_match:1;
- u8 reserved:4;
+ u16 reserved:3;
u8 func_id;
u16 manf_id;
@@ -182,22 +178,24 @@ struct pcmcia_device {
char * prod_id[4];
+ struct device dev;
+
+#ifdef CONFIG_PCMCIA_IOCTL
/* device driver wanted by cardmgr */
struct pcmcia_driver * cardmgr;
+#endif
- struct device dev;
+ /* data private to drivers */
+ void *priv;
};
#define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
#define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
-#define handle_to_pdev(handle) (handle)
#define handle_to_dev(handle) (handle->dev)
-#define dev_to_instance(dev) (dev->instance)
-
/* error reporting */
-void cs_error(client_handle_t handle, int func, int ret);
+void cs_error(struct pcmcia_device *handle, int func, int ret);
#endif /* __KERNEL__ */
#endif /* _LINUX_DS_H */
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 2889a69a7a8f..5e0a01ab2216 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -18,6 +18,7 @@
#include <linux/config.h>
#include <linux/device.h>
#include <linux/sched.h> /* task_struct, completion */
+#include <linux/mutex.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
@@ -146,14 +147,15 @@ extern struct pccard_resource_ops pccard_static_ops;
/* !SS_CAP_STATIC_MAP */
extern struct pccard_resource_ops pccard_nonstatic_ops;
+/* static mem, dynamic IO sockets */
+extern struct pccard_resource_ops pccard_iodyn_ops;
+
/*
* Calls to set up low-level "Socket Services" drivers
*/
struct pcmcia_socket;
typedef struct io_window_t {
- u_int Attributes;
- kio_addr_t BasePort, NumPorts;
kio_addr_t InUse, Config;
struct resource *res;
} io_window_t;
@@ -162,7 +164,7 @@ typedef struct io_window_t {
typedef struct window_t {
u_short magic;
u_short index;
- client_handle_t handle;
+ struct pcmcia_device *handle;
struct pcmcia_socket *sock;
pccard_mem_map ctl;
} window_t;
@@ -186,7 +188,6 @@ struct pcmcia_socket {
u_short lock_count;
pccard_mem_map cis_mem;
void __iomem *cis_virt;
- struct config_t *config;
struct {
u_int AssignedIRQ;
u_int Config;
@@ -241,7 +242,7 @@ struct pcmcia_socket {
#endif
/* state thread */
- struct semaphore skt_sem; /* protects socket h/w state */
+ struct mutex skt_mutex; /* protects socket h/w state */
struct task_struct *thread;
struct completion thread_done;
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index f404fe21cc21..ad63c215efe5 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -91,34 +91,6 @@ enum ib_sa_selector {
IB_SA_BEST = 3
};
-enum ib_sa_rate {
- IB_SA_RATE_2_5_GBPS = 2,
- IB_SA_RATE_5_GBPS = 5,
- IB_SA_RATE_10_GBPS = 3,
- IB_SA_RATE_20_GBPS = 6,
- IB_SA_RATE_30_GBPS = 4,
- IB_SA_RATE_40_GBPS = 7,
- IB_SA_RATE_60_GBPS = 8,
- IB_SA_RATE_80_GBPS = 9,
- IB_SA_RATE_120_GBPS = 10
-};
-
-static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
-{
- switch (rate) {
- case IB_SA_RATE_2_5_GBPS: return 1;
- case IB_SA_RATE_5_GBPS: return 2;
- case IB_SA_RATE_10_GBPS: return 4;
- case IB_SA_RATE_20_GBPS: return 8;
- case IB_SA_RATE_30_GBPS: return 12;
- case IB_SA_RATE_40_GBPS: return 16;
- case IB_SA_RATE_60_GBPS: return 24;
- case IB_SA_RATE_80_GBPS: return 32;
- case IB_SA_RATE_120_GBPS: return 48;
- default: return -1;
- }
-}
-
/*
* Structures for SA records are named "struct ib_sa_xxx_rec." No
* attempt is made to pack structures to match the physical layout of
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c1ad6273ac6c..6bbf1b364400 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -314,6 +314,34 @@ enum ib_ah_flags {
IB_AH_GRH = 1
};
+enum ib_rate {
+ IB_RATE_PORT_CURRENT = 0,
+ IB_RATE_2_5_GBPS = 2,
+ IB_RATE_5_GBPS = 5,
+ IB_RATE_10_GBPS = 3,
+ IB_RATE_20_GBPS = 6,
+ IB_RATE_30_GBPS = 4,
+ IB_RATE_40_GBPS = 7,
+ IB_RATE_60_GBPS = 8,
+ IB_RATE_80_GBPS = 9,
+ IB_RATE_120_GBPS = 10
+};
+
+/**
+ * ib_rate_to_mult - Convert the IB rate enum to a multiple of the
+ * base rate of 2.5 Gbit/sec. For example, IB_RATE_5_GBPS will be
+ * converted to 2, since 5 Gbit/sec is 2 * 2.5 Gbit/sec.
+ * @rate: rate to convert.
+ */
+int ib_rate_to_mult(enum ib_rate rate) __attribute_const__;
+
+/**
+ * mult_to_ib_rate - Convert a multiple of 2.5 Gbit/sec to an IB rate
+ * enum.
+ * @mult: multiple to convert.
+ */
+enum ib_rate mult_to_ib_rate(int mult) __attribute_const__;
+
struct ib_ah_attr {
struct ib_global_route grh;
u16 dlid;
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 174101b2069b..d31b16d25a09 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -28,4 +28,5 @@
#define BLIST_NO_ULD_ATTACH 0x100000 /* device is actually for RAID config */
#define BLIST_SELECT_NO_ATN 0x200000 /* select without ATN */
#define BLIST_RETRY_HWERROR 0x400000 /* retry HARDWARE_ERROR */
+#define BLIST_MAX_512 0x800000 /* maximum 512 sector cdb length */
#endif
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index dc6862d09e53..de6ce541a046 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -140,7 +140,6 @@ struct scsi_host_template {
*
* Status: REQUIRED (at least one of them)
*/
- int (* eh_strategy_handler)(struct Scsi_Host *);
int (* eh_abort_handler)(struct scsi_cmnd *);
int (* eh_device_reset_handler)(struct scsi_cmnd *);
int (* eh_bus_reset_handler)(struct scsi_cmnd *);
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index d4be4d92d586..edb9525386da 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -41,8 +41,6 @@ typedef struct scsi_fctargaddress {
} Scsi_FCTargAddress;
extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-extern int scsi_ioctl_send_command(struct scsi_device *,
- struct scsi_ioctl_command __user *);
extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
void __user *arg, struct file *filp);
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index b3657f111937..cca1d4926d2a 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -50,6 +50,11 @@ struct scsi_transport_template {
unsigned int create_work_queue : 1;
/*
+ * Allows a transport to override the default error handler.
+ */
+ void (* eh_strategy_handler)(struct Scsi_Host *);
+
+ /*
* This is an optional routine that allows the transport to become
* involved when a scsi io timer fires. The return value tells the
* timer routine how to finish the io timeout handling:
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index cf3fec8be1e3..5626225bd3ae 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -202,12 +202,19 @@ struct fc_rport { /* aka fc_starget_attrs */
/* internal data */
unsigned int channel;
u32 number;
+ u8 flags;
struct list_head peers;
struct device dev;
struct work_struct dev_loss_work;
struct work_struct scan_work;
+ struct work_struct stgt_delete_work;
+ struct work_struct rport_delete_work;
} __attribute__((aligned(sizeof(unsigned long))));
+/* bit field values for struct fc_rport "flags" field: */
+#define FC_RPORT_DEVLOSS_PENDING 0x01
+#define FC_RPORT_SCAN_PENDING 0x02
+
#define dev_to_rport(d) \
container_of(d, struct fc_rport, dev)
#define transport_class_to_rport(classdev) \
@@ -327,13 +334,16 @@ struct fc_host_attrs {
struct list_head rport_bindings;
u32 next_rport_number;
u32 next_target_id;
- u8 flags;
- struct work_struct rport_del_work;
-};
-/* values for struct fc_host_attrs "flags" field: */
-#define FC_SHOST_RPORT_DEL_SCHEDULED 0x01
+ /* work queues for rport state manipulation */
+ char work_q_name[KOBJ_NAME_LEN];
+ struct workqueue_struct *work_q;
+ char devloss_work_q_name[KOBJ_NAME_LEN];
+ struct workqueue_struct *devloss_work_q;
+};
+#define shost_to_fc_host(x) \
+ ((struct fc_host_attrs *)(x)->shost_data)
#define fc_host_node_name(x) \
(((struct fc_host_attrs *)(x)->shost_data)->node_name)
@@ -375,10 +385,14 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
#define fc_host_next_target_id(x) \
(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
-#define fc_host_flags(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->flags)
-#define fc_host_rport_del_work(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->rport_del_work)
+#define fc_host_work_q_name(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
+#define fc_host_work_q(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->work_q)
+#define fc_host_devloss_work_q_name(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
+#define fc_host_devloss_work_q(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
/* The functions by which the transport class and the driver communicate */
@@ -461,10 +475,15 @@ fc_remote_port_chkready(struct fc_rport *rport)
switch (rport->port_state) {
case FC_PORTSTATE_ONLINE:
- result = 0;
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ result = 0;
+ else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
+ result = DID_IMM_RETRY << 16;
+ else
+ result = DID_NO_CONNECT << 16;
break;
case FC_PORTSTATE_BLOCKED:
- result = DID_BUS_BUSY << 16;
+ result = DID_IMM_RETRY << 16;
break;
default:
result = DID_NO_CONNECT << 16;
diff --git a/include/sound/core.h b/include/sound/core.h
index 7f32c12b4a0a..5135147f20e8 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -170,13 +170,13 @@ static inline void snd_power_change_state(struct snd_card *card, unsigned int st
}
/* init.c */
-int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file);
+int snd_power_wait(struct snd_card *card, unsigned int power_state);
#else /* ! CONFIG_PM */
#define snd_power_lock(card) do { (void)(card); } while (0)
#define snd_power_unlock(card) do { (void)(card); } while (0)
-static inline int snd_power_wait(struct snd_card *card, unsigned int state, struct file *file) { return 0; }
+static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 15b885660bf0..df70e7592ab5 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -367,8 +367,9 @@ struct snd_pcm_substream {
struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */
struct snd_pcm_group *group; /* pointer to current group */
/* -- assigned files -- */
- struct snd_pcm_file *file;
+ void *file;
struct file *ffile;
+ void (*pcm_release)(struct snd_pcm_substream *);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
struct snd_pcm_oss_substream oss;
@@ -381,13 +382,10 @@ struct snd_pcm_substream {
struct snd_info_entry *proc_prealloc_entry;
/* misc flags */
unsigned int no_mmap_ctrl: 1;
+ unsigned int hw_opened: 1;
};
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL))
-#else
#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
-#endif
struct snd_pcm_str {
@@ -460,7 +458,6 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
struct snd_pcm_info __user *info);
int snd_pcm_status(struct snd_pcm_substream *substream,
struct snd_pcm_status *status);
-int snd_pcm_prepare(struct snd_pcm_substream *substream);
int snd_pcm_start(struct snd_pcm_substream *substream);
int snd_pcm_stop(struct snd_pcm_substream *substream, int status);
int snd_pcm_drain_done(struct snd_pcm_substream *substream);
@@ -468,11 +465,13 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream);
int snd_pcm_suspend(struct snd_pcm_substream *substream);
int snd_pcm_suspend_all(struct snd_pcm *pcm);
#endif
-int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream);
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
+ struct snd_pcm_substream **rsubstream);
void snd_pcm_release_substream(struct snd_pcm_substream *substream);
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
+ struct snd_pcm_substream **rsubstream);
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
void snd_pcm_vma_notify_data(void *client, void *data);
int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
@@ -899,7 +898,6 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
-const char *snd_pcm_format_name(snd_pcm_format_t format);
void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops);
void snd_pcm_set_sync(struct snd_pcm_substream *substream);
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index bff0778e1969..39df2baca18a 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -69,8 +69,7 @@ struct snd_pcm_oss_file {
struct snd_pcm_oss_substream {
unsigned oss: 1; /* oss mode */
- struct snd_pcm_oss_setup *setup; /* active setup */
- struct snd_pcm_oss_file *file;
+ struct snd_pcm_oss_setup setup; /* active setup */
};
struct snd_pcm_oss_stream {
diff --git a/ipc/shm.c b/ipc/shm.c
index f806a2e314e0..1c2faf62bc73 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -91,8 +91,8 @@ static inline int shm_addid(struct shmid_kernel *shp)
static inline void shm_inc (int id) {
struct shmid_kernel *shp;
- if(!(shp = shm_lock(id)))
- BUG();
+ shp = shm_lock(id);
+ BUG_ON(!shp);
shp->shm_atim = get_seconds();
shp->shm_lprid = current->tgid;
shp->shm_nattch++;
@@ -142,8 +142,8 @@ static void shm_close (struct vm_area_struct *shmd)
mutex_lock(&shm_ids.mutex);
/* remove from the list of attaches of the shm segment */
- if(!(shp = shm_lock(id)))
- BUG();
+ shp = shm_lock(id);
+ BUG_ON(!shp);
shp->shm_lprid = current->tgid;
shp->shm_dtim = get_seconds();
shp->shm_nattch--;
@@ -162,6 +162,8 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
ret = shmem_mmap(file, vma);
if (ret == 0) {
vma->vm_ops = &shm_vm_ops;
+ if (!(vma->vm_flags & VM_WRITE))
+ vma->vm_flags &= ~VM_MAYWRITE;
shm_inc(file->f_dentry->d_inode->i_ino);
}
@@ -283,8 +285,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
err = -EEXIST;
} else {
shp = shm_lock(id);
- if(shp==NULL)
- BUG();
+ BUG_ON(shp==NULL);
if (shp->shm_segsz < size)
err = -EINVAL;
else if (ipcperms(&shp->shm_perm, shmflg))
@@ -774,8 +775,8 @@ invalid:
up_write(&current->mm->mmap_sem);
mutex_lock(&shm_ids.mutex);
- if(!(shp = shm_lock(shmid)))
- BUG();
+ shp = shm_lock(shmid);
+ BUG_ON(!shp);
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
shp->shm_perm.mode & SHM_DEST)
diff --git a/ipc/util.c b/ipc/util.c
index 23151ef32590..b3dcfad3b4f7 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -183,8 +183,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
if(new == NULL)
return size;
new->size = newsize;
- memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
- sizeof(struct ipc_id_ary));
+ memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
for(i=size;i<newsize;i++) {
new->p[i] = NULL;
}
@@ -266,8 +265,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
{
struct kern_ipc_perm* p;
int lid = id % SEQ_MULTIPLIER;
- if(lid >= ids->entries->size)
- BUG();
+ BUG_ON(lid >= ids->entries->size);
/*
* do not need a rcu_dereference()() here to force ordering
@@ -275,8 +273,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
*/
p = ids->entries->p[lid];
ids->entries->p[lid] = NULL;
- if(p==NULL)
- BUG();
+ BUG_ON(p==NULL);
ids->in_use--;
if (lid == ids->max_id) {
diff --git a/kernel/exit.c b/kernel/exit.c
index 6c2eeb8f6390..f86434d7b3d1 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -34,6 +34,7 @@
#include <linux/mutex.h>
#include <linux/futex.h>
#include <linux/compat.h>
+#include <linux/pipe_fs_i.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -55,7 +56,7 @@ static void __unhash_process(struct task_struct *p)
detach_pid(p, PIDTYPE_PGID);
detach_pid(p, PIDTYPE_SID);
- list_del_init(&p->tasks);
+ list_del_rcu(&p->tasks);
__get_cpu_var(process_counts)--;
}
list_del_rcu(&p->thread_group);
@@ -941,6 +942,9 @@ fastcall NORET_TYPE void do_exit(long code)
if (tsk->io_context)
exit_io_context();
+ if (tsk->splice_pipe)
+ __free_pipe_info(tsk->splice_pipe);
+
/* PF_DEAD causes final put_task_struct after we schedule. */
preempt_disable();
BUG_ON(tsk->flags & PF_DEAD);
diff --git a/kernel/fork.c b/kernel/fork.c
index 3384eb89cb1c..d2fa57d480d4 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -124,12 +124,6 @@ void __put_task_struct(struct task_struct *tsk)
free_task(tsk);
}
-void __put_task_struct_cb(struct rcu_head *rhp)
-{
- struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
- __put_task_struct(tsk);
-}
-
void __init fork_init(unsigned long mempages)
{
#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
@@ -186,6 +180,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
atomic_set(&tsk->usage,2);
atomic_set(&tsk->fs_excl, 0);
tsk->btrace_seq = 0;
+ tsk->splice_pipe = NULL;
return tsk;
}
@@ -1210,7 +1205,7 @@ static task_t *copy_process(unsigned long clone_flags,
attach_pid(p, PIDTYPE_PGID, process_group(p));
attach_pid(p, PIDTYPE_SID, p->signal->session);
- list_add_tail(&p->tasks, &init_task.tasks);
+ list_add_tail_rcu(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
}
attach_pid(p, PIDTYPE_PID, p->pid);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f181ff4dd32e..b7f0388bd71c 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -501,6 +501,7 @@ int hrtimer_cancel(struct hrtimer *timer)
if (ret >= 0)
return ret;
+ cpu_relax();
}
}
@@ -835,7 +836,7 @@ static void migrate_hrtimers(int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
+static int hrtimer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -859,7 +860,7 @@ static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata hrtimers_nb = {
+static struct notifier_block hrtimers_nb = {
.notifier_call = hrtimer_cpu_notify,
};
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 2b33f852be3e..9f77f50d8143 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,4 +1,5 @@
-obj-y := handle.o manage.o spurious.o migration.o
+obj-y := handle.o manage.o spurious.o
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ac766ad573e8..1279e3499534 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -246,8 +246,10 @@ int setup_irq(unsigned int irq, struct irqaction * new)
mismatch:
spin_unlock_irqrestore(&desc->lock, flags);
- printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
- dump_stack();
+ if (!(new->flags & SA_PROBEIRQ)) {
+ printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
+ dump_stack();
+ }
return -EBUSY;
}
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 52a8655fa080..134f9f2e0e39 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -1,6 +1,5 @@
-#include <linux/irq.h>
-#if defined(CONFIG_GENERIC_PENDING_IRQ)
+#include <linux/irq.h>
void set_pending_irq(unsigned int irq, cpumask_t mask)
{
@@ -61,5 +60,3 @@ void move_native_irq(int irq)
}
cpus_clear(pending_irq_cpumask[irq]);
}
-
-#endif
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1156eb0977d0..1fbf466a29aa 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -585,6 +585,9 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
int i;
rp->kp.pre_handler = pre_handler_kretprobe;
+ rp->kp.post_handler = NULL;
+ rp->kp.fault_handler = NULL;
+ rp->kp.break_handler = NULL;
/* Pre-allocate memory for max kretprobe instances */
if (rp->maxactive <= 0) {
diff --git a/kernel/panic.c b/kernel/panic.c
index f895c7c01d5b..cc2a4c9c36ac 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -27,7 +27,6 @@ static int pause_on_oops_flag;
static DEFINE_SPINLOCK(pause_on_oops_lock);
int panic_timeout;
-EXPORT_SYMBOL(panic_timeout);
ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 9fd8d4f03595..ce0dfb8f4a4e 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -41,7 +41,7 @@ config SOFTWARE_SUSPEND
depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)
---help---
Enable the possibility of suspending the machine.
- It doesn't need APM.
+ It doesn't need ACPI or APM.
You may suspend your machine by 'swsusp' or 'shutdown -z <time>'
(patch for sysvinit needed).
diff --git a/kernel/power/main.c b/kernel/power/main.c
index ee371f50ccaa..a6d9ef46009e 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -272,7 +272,7 @@ static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n
if (*s && !strncmp(buf, *s, len))
break;
}
- if (*s)
+ if (state < PM_SUSPEND_MAX && *s)
error = enter_state(state);
else
error = -EINVAL;
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 0f6908cce1dd..84063ac8fcfc 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -75,25 +75,6 @@ struct pm_dev *pm_register(pm_dev_t type,
return dev;
}
-/**
- * pm_unregister - unregister a device with power management
- * @dev: device to unregister
- *
- * Remove a device from the power management notification lists. The
- * dev passed must be a handle previously returned by pm_register.
- */
-
-void pm_unregister(struct pm_dev *dev)
-{
- if (dev) {
- mutex_lock(&pm_devs_lock);
- list_del(&dev->entry);
- mutex_unlock(&pm_devs_lock);
-
- kfree(dev);
- }
-}
-
static void __pm_unregister(struct pm_dev *dev)
{
if (dev) {
@@ -258,7 +239,6 @@ int pm_send_all(pm_request_t rqst, void *data)
}
EXPORT_SYMBOL(pm_register);
-EXPORT_SYMBOL(pm_unregister);
EXPORT_SYMBOL(pm_unregister_all);
EXPORT_SYMBOL(pm_send_all);
EXPORT_SYMBOL(pm_active);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index c5863d02c89e..3eeedbb13b78 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -240,14 +240,15 @@ static void copy_data_pages(struct pbe *pblist)
* free_pagedir - free pages allocated with alloc_pagedir()
*/
-static void free_pagedir(struct pbe *pblist)
+static void free_pagedir(struct pbe *pblist, int clear_nosave_free)
{
struct pbe *pbe;
while (pblist) {
pbe = (pblist + PB_PAGE_SKIP)->next;
ClearPageNosave(virt_to_page(pblist));
- ClearPageNosaveFree(virt_to_page(pblist));
+ if (clear_nosave_free)
+ ClearPageNosaveFree(virt_to_page(pblist));
free_page((unsigned long)pblist);
pblist = pbe;
}
@@ -389,7 +390,7 @@ struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed
pbe->next = alloc_image_page(gfp_mask, safe_needed);
}
if (!pbe) { /* get_zeroed_page() failed */
- free_pagedir(pblist);
+ free_pagedir(pblist, 1);
pblist = NULL;
} else
create_pbe_list(pblist, nr_pages);
@@ -736,7 +737,7 @@ static int create_image(struct snapshot_handle *handle)
pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
if (pblist)
copy_page_backup_list(pblist, p);
- free_pagedir(p);
+ free_pagedir(p, 0);
if (!pblist)
error = -ENOMEM;
}
diff --git a/kernel/printk.c b/kernel/printk.c
index 8cc19431e74b..c056f3324432 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -360,8 +360,7 @@ static void call_console_drivers(unsigned long start, unsigned long end)
unsigned long cur_index, start_print;
static int msg_level = -1;
- if (((long)(start - end)) > 0)
- BUG();
+ BUG_ON(((long)(start - end)) > 0);
cur_index = start;
start_print = start;
@@ -708,8 +707,7 @@ int __init add_preferred_console(char *name, int idx, char *options)
*/
void acquire_console_sem(void)
{
- if (in_interrupt())
- BUG();
+ BUG_ON(in_interrupt());
down(&console_sem);
console_locked = 1;
console_may_schedule = 1;
diff --git a/kernel/profile.c b/kernel/profile.c
index 5a730fdb1a2c..68afe121e507 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -299,7 +299,7 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static int __devinit profile_cpu_callback(struct notifier_block *info,
+static int profile_cpu_callback(struct notifier_block *info,
unsigned long action, void *__cpu)
{
int node, cpu = (unsigned long)__cpu;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 86a7f6c60cb2..4e0f0ec003f7 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -30,8 +30,7 @@
*/
void __ptrace_link(task_t *child, task_t *new_parent)
{
- if (!list_empty(&child->ptrace_list))
- BUG();
+ BUG_ON(!list_empty(&child->ptrace_list));
if (child->parent == new_parent)
return;
list_add(&child->ptrace_list, &child->parent->ptrace_children);
@@ -57,10 +56,6 @@ void ptrace_untrace(task_t *child)
signal_wake_up(child, 1);
}
}
- if (child->signal->flags & SIGNAL_GROUP_EXIT) {
- sigaddset(&child->pending.signal, SIGKILL);
- signal_wake_up(child, 1);
- }
spin_unlock(&child->sighand->siglock);
}
@@ -82,7 +77,8 @@ void __ptrace_unlink(task_t *child)
add_parent(child);
}
- ptrace_untrace(child);
+ if (child->state == TASK_TRACED)
+ ptrace_untrace(child);
}
/*
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 13458bbaa1be..6d32ff26f948 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -520,7 +520,7 @@ static void __devinit rcu_online_cpu(int cpu)
tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
}
-static int __devinit rcu_cpu_notify(struct notifier_block *self,
+static int rcu_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -537,7 +537,7 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata rcu_nb = {
+static struct notifier_block rcu_nb = {
.notifier_call = rcu_cpu_notify,
};
diff --git a/kernel/sched.c b/kernel/sched.c
index dd153d6f8a04..4c64f85698ae 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -665,13 +665,55 @@ static int effective_prio(task_t *p)
}
/*
+ * 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, and switch periodically
+ * regardless, to ensure that highly interactive tasks do not starve
+ * the less fortunate for unreasonably long periods.
+ */
+static inline int expired_starving(runqueue_t *rq)
+{
+ int limit;
+
+ /*
+ * Arrays were recently switched, all is well
+ */
+ if (!rq->expired_timestamp)
+ return 0;
+
+ limit = STARVATION_LIMIT * rq->nr_running;
+
+ /*
+ * It's time to switch arrays
+ */
+ if (jiffies - rq->expired_timestamp >= limit)
+ return 1;
+
+ /*
+ * There's a better selection in the expired array
+ */
+ if (rq->curr->static_prio > rq->best_expired_prio)
+ return 1;
+
+ /*
+ * All is well
+ */
+ return 0;
+}
+
+/*
* __activate_task - move a task to the runqueue.
*/
static void __activate_task(task_t *p, runqueue_t *rq)
{
prio_array_t *target = rq->active;
- if (batch_task(p))
+ if (unlikely(batch_task(p) || (expired_starving(rq) && !rt_task(p))))
target = rq->expired;
enqueue_task(p, target);
rq->nr_running++;
@@ -2490,22 +2532,6 @@ unsigned long long current_sched_time(const task_t *tsk)
}
/*
- * 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:
- */
-#define EXPIRED_STARVING(rq) \
- ((STARVATION_LIMIT && ((rq)->expired_timestamp && \
- (jiffies - (rq)->expired_timestamp >= \
- STARVATION_LIMIT * ((rq)->nr_running) + 1))) || \
- ((rq)->curr->static_prio > (rq)->best_expired_prio))
-
-/*
* 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()
@@ -2640,7 +2666,7 @@ void scheduler_tick(void)
if (!rq->expired_timestamp)
rq->expired_timestamp = jiffies;
- if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {
+ 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;
@@ -4788,7 +4814,7 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
/* Register at highest priority so that task migration (migrate_all_tasks)
* happens before everything else.
*/
-static struct notifier_block __devinitdata migration_notifier = {
+static struct notifier_block migration_notifier = {
.notifier_call = migration_call,
.priority = 10
};
diff --git a/kernel/signal.c b/kernel/signal.c
index 92025b108791..e5f8aea78ffe 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -769,8 +769,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
{
int ret = 0;
- if (!irqs_disabled())
- BUG();
+ BUG_ON(!irqs_disabled());
assert_spin_locked(&t->sighand->siglock);
/* Short-circuit ignored signals. */
@@ -869,7 +868,6 @@ __group_complete_signal(int sig, struct task_struct *p)
if (t == NULL)
/* restart balancing at this thread */
t = p->signal->curr_target = p;
- BUG_ON(t->tgid != p->tgid);
while (!wants_signal(sig, t)) {
t = next_thread(t);
@@ -1384,8 +1382,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
* the overrun count. Other uses should not try to
* send the signal multiple times.
*/
- if (q->info.si_code != SI_TIMER)
- BUG();
+ BUG_ON(q->info.si_code != SI_TIMER);
q->info.si_overrun++;
goto out;
}
@@ -1757,9 +1754,9 @@ relock:
/* Let the debugger run. */
ptrace_stop(signr, signr, info);
- /* We're back. Did the debugger cancel the sig or group_exit? */
+ /* We're back. Did the debugger cancel the sig? */
signr = current->exit_code;
- if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT)
+ if (signr == 0)
continue;
current->exit_code = 0;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index ec8fed42a86f..336f92d64e2e 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -446,7 +446,7 @@ static void takeover_tasklets(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
@@ -484,7 +484,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block cpu_nfb = {
.notifier_call = cpu_callback
};
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index ced91e1ff564..14c7faf02909 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -104,7 +104,7 @@ static int watchdog(void * __bind_cpu)
/*
* Create/destroy watchdog threads as CPUs come and go:
*/
-static int __devinit
+static int
cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
int hotcpu = (unsigned long)hcpu;
@@ -140,7 +140,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block cpu_nfb = {
.notifier_call = cpu_callback
};
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index d82864c4a617..5433195040f1 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -120,3 +120,15 @@ cond_syscall(sys32_sysctl);
cond_syscall(ppc_rtas);
cond_syscall(sys_spu_run);
cond_syscall(sys_spu_create);
+
+/* mmu depending weak syscall entries */
+cond_syscall(sys_mprotect);
+cond_syscall(sys_msync);
+cond_syscall(sys_mlock);
+cond_syscall(sys_munlock);
+cond_syscall(sys_mlockall);
+cond_syscall(sys_munlockall);
+cond_syscall(sys_mincore);
+cond_syscall(sys_madvise);
+cond_syscall(sys_mremap);
+cond_syscall(sys_remap_file_pages);
diff --git a/kernel/time.c b/kernel/time.c
index ff8e7019c4c4..b00ddc71cedb 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -410,7 +410,7 @@ EXPORT_SYMBOL(current_kernel_time);
* current_fs_time - Return FS time
* @sb: Superblock.
*
- * Return the current time truncated to the time granuality supported by
+ * Return the current time truncated to the time granularity supported by
* the fs.
*/
struct timespec current_fs_time(struct super_block *sb)
@@ -421,11 +421,11 @@ struct timespec current_fs_time(struct super_block *sb)
EXPORT_SYMBOL(current_fs_time);
/**
- * timespec_trunc - Truncate timespec to a granuality
+ * timespec_trunc - Truncate timespec to a granularity
* @t: Timespec
- * @gran: Granuality in ns.
+ * @gran: Granularity in ns.
*
- * Truncate a timespec to a granuality. gran must be smaller than a second.
+ * Truncate a timespec to a granularity. gran must be smaller than a second.
* Always rounds down.
*
* This function should be only used for timestamps returned by
diff --git a/kernel/timer.c b/kernel/timer.c
index 6b812c04737b..67eaf0f54096 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -81,9 +81,10 @@ struct tvec_t_base_s {
} ____cacheline_aligned_in_smp;
typedef struct tvec_t_base_s tvec_base_t;
-static DEFINE_PER_CPU(tvec_base_t *, tvec_bases);
+
tvec_base_t boot_tvec_bases;
EXPORT_SYMBOL(boot_tvec_bases);
+static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases };
static inline void set_running_timer(tvec_base_t *base,
struct timer_list *timer)
@@ -1224,28 +1225,36 @@ static int __devinit init_timers_cpu(int cpu)
{
int j;
tvec_base_t *base;
+ static char __devinitdata tvec_base_done[NR_CPUS];
- base = per_cpu(tvec_bases, cpu);
- if (!base) {
+ if (!tvec_base_done[cpu]) {
static char boot_done;
- /*
- * Cannot do allocation in init_timers as that runs before the
- * allocator initializes (and would waste memory if there are
- * more possible CPUs than will ever be installed/brought up).
- */
if (boot_done) {
+ /*
+ * The APs use this path later in boot
+ */
base = kmalloc_node(sizeof(*base), GFP_KERNEL,
cpu_to_node(cpu));
if (!base)
return -ENOMEM;
memset(base, 0, sizeof(*base));
+ per_cpu(tvec_bases, cpu) = base;
} else {
- base = &boot_tvec_bases;
+ /*
+ * This is for the boot CPU - we use compile-time
+ * static initialisation because per-cpu memory isn't
+ * ready yet and because the memory allocators are not
+ * initialised either.
+ */
boot_done = 1;
+ base = &boot_tvec_bases;
}
- per_cpu(tvec_bases, cpu) = base;
+ tvec_base_done[cpu] = 1;
+ } else {
+ base = per_cpu(tvec_bases, cpu);
}
+
spin_lock_init(&base->lock);
for (j = 0; j < TVN_SIZE; j++) {
INIT_LIST_HEAD(base->tv5.vec + j);
@@ -1305,7 +1314,7 @@ static void __devinit migrate_timers(int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit timer_cpu_notify(struct notifier_block *self,
+static int timer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -1325,7 +1334,7 @@ static int __devinit timer_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata timers_nb = {
+static struct notifier_block timers_nb = {
.notifier_call = timer_cpu_notify,
};
@@ -1455,7 +1464,7 @@ static void time_interpolator_update(long delta_nsec)
*/
if (jiffies % INTERPOLATOR_ADJUST == 0)
{
- if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC)
+ if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
time_interpolator->nsec_per_cyc--;
if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
time_interpolator->nsec_per_cyc++;
@@ -1479,8 +1488,7 @@ register_time_interpolator(struct time_interpolator *ti)
unsigned long flags;
/* Sanity check */
- if (ti->frequency == 0 || ti->mask == 0)
- BUG();
+ BUG_ON(ti->frequency == 0 || ti->mask == 0);
ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
spin_lock(&time_interpolator_lock);
diff --git a/kernel/uid16.c b/kernel/uid16.c
index aa25605027c8..187e2a423878 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -20,43 +20,67 @@
asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group)
{
- return sys_chown(filename, low2highuid(user), low2highgid(group));
+ long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group)
{
- return sys_lchown(filename, low2highuid(user), low2highgid(group));
+ long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
{
- return sys_fchown(fd, low2highuid(user), low2highgid(group));
+ long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
{
- return sys_setregid(low2highgid(rgid), low2highgid(egid));
+ long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setgid16(old_gid_t gid)
{
- return sys_setgid(low2highgid(gid));
+ long ret = sys_setgid(low2highgid(gid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
{
- return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+ long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setuid16(old_uid_t uid)
{
- return sys_setuid(low2highuid(uid));
+ long ret = sys_setuid(low2highuid(uid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
{
- return sys_setresuid(low2highuid(ruid), low2highuid(euid),
- low2highuid(suid));
+ long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
+ low2highuid(suid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid)
@@ -72,8 +96,11 @@ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid,
asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
{
- return sys_setresgid(low2highgid(rgid), low2highgid(egid),
- low2highgid(sgid));
+ long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
+ low2highgid(sgid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid)
@@ -89,12 +116,18 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid,
asmlinkage long sys_setfsuid16(old_uid_t uid)
{
- return sys_setfsuid(low2highuid(uid));
+ long ret = sys_setfsuid(low2highuid(uid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setfsgid16(old_gid_t gid)
{
- return sys_setfsgid(low2highgid(gid));
+ long ret = sys_setfsgid(low2highgid(gid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
static int groups16_to_user(old_gid_t __user *grouplist,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index e9e464a90376..880fb415a8f6 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -547,7 +547,7 @@ static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
}
/* We're holding the cpucontrol mutex here */
-static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+static int workqueue_cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index d57fd9181b18..6ecc180beb71 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -101,7 +101,7 @@ config DEBUG_PREEMPT
config DEBUG_MUTEXES
bool "Mutex debugging, deadlock detection"
- default y
+ default n
depends on DEBUG_KERNEL
help
This allows mutex semantics violations and mutex related deadlocks
diff --git a/lib/kobject.c b/lib/kobject.c
index 25204a41a9b0..b46350c27837 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj)
{
kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry);
+ init_waitqueue_head(&kobj->poll);
kobj->kset = kset_get(kobj->kset);
}
@@ -421,7 +422,6 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
return k;
}
-EXPORT_SYMBOL_GPL(kobject_add_dir);
/**
* kset_init - initialize a kset for use
@@ -568,7 +568,7 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
* @s: subsystem.
* @a: attribute desciptor.
*/
-
+#if 0
void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
{
if (subsys_get(s)) {
@@ -576,6 +576,7 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
subsys_put(s);
}
}
+#endif /* 0 */
EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_register);
@@ -587,10 +588,7 @@ EXPORT_SYMBOL(kobject_del);
EXPORT_SYMBOL(kset_register);
EXPORT_SYMBOL(kset_unregister);
-EXPORT_SYMBOL(kset_find_obj);
-EXPORT_SYMBOL(subsystem_init);
EXPORT_SYMBOL(subsystem_register);
EXPORT_SYMBOL(subsystem_unregister);
EXPORT_SYMBOL(subsys_create_file);
-EXPORT_SYMBOL(subsys_remove_file);
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 982226daf939..7f20e7b857cb 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -25,11 +25,13 @@
#define BUFFER_SIZE 2048 /* buffer for the variables */
#define NUM_ENVP 32 /* number of env pointers */
-#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG)
u64 uevent_seqnum;
char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
static DEFINE_SPINLOCK(sequence_lock);
+#if defined(CONFIG_NET)
static struct sock *uevent_sock;
+#endif
static char *action_to_string(enum kobject_action action)
{
@@ -155,6 +157,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
spin_unlock(&sequence_lock);
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
+#if defined(CONFIG_NET)
/* send netlink message */
if (uevent_sock) {
struct sk_buff *skb;
@@ -179,6 +182,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
}
}
+#endif
/* call uevent_helper, usually only enabled during early boot */
if (uevent_helper[0]) {
@@ -249,6 +253,7 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
}
EXPORT_SYMBOL_GPL(add_uevent_var);
+#if defined(CONFIG_NET)
static int __init kobject_uevent_init(void)
{
uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
@@ -264,5 +269,6 @@ static int __init kobject_uevent_init(void)
}
postcore_initcall(kobject_uevent_init);
+#endif
#endif /* CONFIG_HOTPLUG */
diff --git a/lib/string.c b/lib/string.c
index b3c28a3f6332..064f6315b1c3 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -362,6 +362,7 @@ size_t strspn(const char *s, const char *accept)
EXPORT_SYMBOL(strspn);
#endif
+#ifndef __HAVE_ARCH_STRCSPN
/**
* strcspn - Calculate the length of the initial substring of @s which does
* not contain letters in @reject
@@ -384,6 +385,7 @@ size_t strcspn(const char *s, const char *reject)
return count;
}
EXPORT_SYMBOL(strcspn);
+#endif
#ifndef __HAVE_ARCH_STRPBRK
/**
@@ -403,6 +405,7 @@ char *strpbrk(const char *cs, const char *ct)
}
return NULL;
}
+EXPORT_SYMBOL(strpbrk);
#endif
#ifndef __HAVE_ARCH_STRSEP
@@ -467,7 +470,7 @@ EXPORT_SYMBOL(memset);
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
- char *s = src;
+ const char *s = src;
while (count--)
*tmp++ = *s++;
diff --git a/mm/bootmem.c b/mm/bootmem.c
index d3e3bd2ffcea..d213feded10d 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -401,7 +401,7 @@ unsigned long __init free_all_bootmem (void)
return(free_all_bootmem_core(NODE_DATA(0)));
}
-void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
+void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, unsigned long goal)
{
bootmem_data_t *bdata;
void *ptr;
@@ -409,7 +409,14 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned
list_for_each_entry(bdata, &bdata_list, list)
if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0)))
return(ptr);
+ return NULL;
+}
+void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
+{
+ void *mem = __alloc_bootmem_nopanic(size,align,goal);
+ if (mem)
+ return mem;
/*
* Whoops, we cannot satisfy the allocation request.
*/
diff --git a/mm/filemap.c b/mm/filemap.c
index 3ef20739e725..fd57442186cb 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -697,6 +697,38 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
return ret;
}
+/**
+ * find_get_pages_contig - gang contiguous pagecache lookup
+ * @mapping: The address_space to search
+ * @index: The starting page index
+ * @nr_pages: The maximum number of pages
+ * @pages: Where the resulting pages are placed
+ *
+ * find_get_pages_contig() works exactly like find_get_pages(), except
+ * that the returned number of pages are guaranteed to be contiguous.
+ *
+ * find_get_pages_contig() returns the number of pages which were found.
+ */
+unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
+ unsigned int nr_pages, struct page **pages)
+{
+ unsigned int i;
+ unsigned int ret;
+
+ read_lock_irq(&mapping->tree_lock);
+ ret = radix_tree_gang_lookup(&mapping->page_tree,
+ (void **)pages, index, nr_pages);
+ for (i = 0; i < ret; i++) {
+ if (pages[i]->mapping == NULL || pages[i]->index != index)
+ break;
+
+ page_cache_get(pages[i]);
+ index++;
+ }
+ read_unlock_irq(&mapping->tree_lock);
+ return i;
+}
+
/*
* Like find_get_pages, except we only return pages which are tagged with
* `tag'. We update *index to index the next page for the traversal.
diff --git a/mm/highmem.c b/mm/highmem.c
index 55885f64af40..9b274fdf9d08 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -74,8 +74,7 @@ static void flush_all_zero_pkmaps(void)
pkmap_count[i] = 0;
/* sanity check */
- if (pte_none(pkmap_page_table[i]))
- BUG();
+ BUG_ON(pte_none(pkmap_page_table[i]));
/*
* Don't need an atomic fetch-and-clear op here;
@@ -158,8 +157,7 @@ void fastcall *kmap_high(struct page *page)
if (!vaddr)
vaddr = map_new_virtual(page);
pkmap_count[PKMAP_NR(vaddr)]++;
- if (pkmap_count[PKMAP_NR(vaddr)] < 2)
- BUG();
+ BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2);
spin_unlock(&kmap_lock);
return (void*) vaddr;
}
@@ -174,8 +172,7 @@ void fastcall kunmap_high(struct page *page)
spin_lock(&kmap_lock);
vaddr = (unsigned long)page_address(page);
- if (!vaddr)
- BUG();
+ BUG_ON(!vaddr);
nr = PKMAP_NR(vaddr);
/*
@@ -220,8 +217,7 @@ static __init int init_emergency_pool(void)
return 0;
page_pool = mempool_create_page_pool(POOL_SIZE, 0);
- if (!page_pool)
- BUG();
+ BUG_ON(!page_pool);
printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
return 0;
@@ -264,8 +260,7 @@ int init_emergency_isa_pool(void)
isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa,
mempool_free_pages, (void *) 0);
- if (!isa_page_pool)
- BUG();
+ BUG_ON(!isa_page_pool);
printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
return 0;
diff --git a/mm/madvise.c b/mm/madvise.c
index af3d573b0141..4e196155a0c3 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -168,6 +168,9 @@ static long madvise_remove(struct vm_area_struct *vma,
return -EINVAL;
}
+ if ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE))
+ return -EACCES;
+
mapping = vma->vm_file->f_mapping;
offset = (loff_t)(start - vma->vm_start)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index dec8249e972d..8778f58880c4 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1761,7 +1761,6 @@ static void gather_stats(struct page *page, void *private, int pte_dirty)
md->mapcount_max = count;
md->node[page_to_nid(page)]++;
- cond_resched();
}
#ifdef CONFIG_HUGETLB_PAGE
diff --git a/mm/migrate.c b/mm/migrate.c
index 09f6e4aa87fc..d444229f2599 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -16,8 +16,7 @@
#include <linux/module.h>
#include <linux/swap.h>
#include <linux/pagemap.h>
-#include <linux/buffer_head.h> /* for try_to_release_page(),
- buffer_heads_over_limit */
+#include <linux/buffer_head.h>
#include <linux/mm_inline.h>
#include <linux/pagevec.h>
#include <linux/rmap.h>
@@ -28,8 +27,6 @@
#include "internal.h"
-#include "internal.h"
-
/* The maximum number of pages to take off the LRU for migration */
#define MIGRATE_CHUNK_SIZE 256
@@ -176,7 +173,6 @@ unlock_retry:
retry:
return -EAGAIN;
}
-EXPORT_SYMBOL(swap_page);
/*
* Remove references for a page and establish the new page with the correct
@@ -234,7 +230,7 @@ int migrate_page_remove_references(struct page *newpage,
if (!page_mapping(page) || page_count(page) != nr_refs ||
*radix_pointer != page) {
write_unlock_irq(&mapping->tree_lock);
- return 1;
+ return -EAGAIN;
}
/*
diff --git a/mm/mmap.c b/mm/mmap.c
index 4f5b5709136a..e6ee12344b13 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -121,14 +121,26 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
* only call if we're about to fail.
*/
n = nr_free_pages();
+
+ /*
+ * Leave reserved pages. The pages are not for anonymous pages.
+ */
+ if (n <= totalreserve_pages)
+ goto error;
+ else
+ n -= totalreserve_pages;
+
+ /*
+ * Leave the last 3% for root
+ */
if (!cap_sys_admin)
n -= n / 32;
free += n;
if (free > pages)
return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
+
+ goto error;
}
allowed = (totalram_pages - hugetlb_total_pages())
@@ -150,7 +162,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
*/
if (atomic_read(&vm_committed_space) < (long)allowed)
return 0;
-
+error:
vm_unacct_memory(pages);
return -ENOMEM;
@@ -220,6 +232,17 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
if (brk < mm->end_code)
goto out;
+
+ /*
+ * Check against rlimit here. If this check is done later after the test
+ * of oldbrk with newbrk then it can escape the test and let the data
+ * segment grow beyond its set limit the in case where the limit is
+ * not page aligned -Ram Gupta
+ */
+ rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
+ goto out;
+
newbrk = PAGE_ALIGN(brk);
oldbrk = PAGE_ALIGN(mm->brk);
if (oldbrk == newbrk)
@@ -232,11 +255,6 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
goto out;
}
- /* Check against rlimit.. */
- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
- if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
- goto out;
-
/* Check against existing mmap mappings. */
if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
goto out;
@@ -294,8 +312,7 @@ void validate_mm(struct mm_struct *mm)
i = browse_rb(&mm->mm_rb);
if (i != mm->map_count)
printk("map_count %d rb %d\n", mm->map_count, i), bug = 1;
- if (bug)
- BUG();
+ BUG_ON(bug);
}
#else
#define validate_mm(mm) do { } while (0)
@@ -432,8 +449,7 @@ __insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
struct rb_node ** rb_link, * rb_parent;
__vma = find_vma_prepare(mm, vma->vm_start,&prev, &rb_link, &rb_parent);
- if (__vma && __vma->vm_start < vma->vm_end)
- BUG();
+ BUG_ON(__vma && __vma->vm_start < vma->vm_end);
__vma_link(mm, vma, prev, rb_link, rb_parent);
mm->map_count++;
}
@@ -813,8 +829,7 @@ try_prev:
* (e.g. stash info in next's anon_vma_node when assigning
* an anon_vma, or when trying vma_merge). Another time.
*/
- if (find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma)
- BUG();
+ BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma);
if (!near)
goto none;
diff --git a/mm/nommu.c b/mm/nommu.c
index db45efac17cc..029fadac0fb5 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1147,14 +1147,26 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
* only call if we're about to fail.
*/
n = nr_free_pages();
+
+ /*
+ * Leave reserved pages. The pages are not for anonymous pages.
+ */
+ if (n <= totalreserve_pages)
+ goto error;
+ else
+ n -= totalreserve_pages;
+
+ /*
+ * Leave the last 3% for root
+ */
if (!cap_sys_admin)
n -= n / 32;
free += n;
if (free > pages)
return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
+
+ goto error;
}
allowed = totalram_pages * sysctl_overcommit_ratio / 100;
@@ -1175,7 +1187,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
*/
if (atomic_read(&vm_committed_space) < (long)allowed)
return 0;
-
+error:
vm_unacct_memory(pages);
return -ENOMEM;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 78747afad6b0..042e6436c3ee 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -46,15 +46,25 @@
unsigned long badness(struct task_struct *p, unsigned long uptime)
{
unsigned long points, cpu_time, run_time, s;
- struct list_head *tsk;
+ struct mm_struct *mm;
+ struct task_struct *child;
- if (!p->mm)
+ task_lock(p);
+ mm = p->mm;
+ if (!mm) {
+ task_unlock(p);
return 0;
+ }
/*
* The memory size of the process is the basis for the badness.
*/
- points = p->mm->total_vm;
+ points = mm->total_vm;
+
+ /*
+ * After this unlock we can no longer dereference local variable `mm'
+ */
+ task_unlock(p);
/*
* Processes which fork a lot of child processes are likely
@@ -64,11 +74,11 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
* child is eating the vast majority of memory, adding only half
* to the parents will make the child our kill candidate of choice.
*/
- list_for_each(tsk, &p->children) {
- struct task_struct *chld;
- chld = list_entry(tsk, struct task_struct, sibling);
- if (chld->mm != p->mm && chld->mm)
- points += chld->mm->total_vm/2 + 1;
+ list_for_each_entry(child, &p->children, sibling) {
+ task_lock(child);
+ if (child->mm != mm && child->mm)
+ points += child->mm->total_vm/2 + 1;
+ task_unlock(child);
}
/*
@@ -244,17 +254,24 @@ static void __oom_kill_task(task_t *p, const char *message)
force_sig(SIGKILL, p);
}
-static struct mm_struct *oom_kill_task(task_t *p, const char *message)
+static int oom_kill_task(task_t *p, const char *message)
{
- struct mm_struct *mm = get_task_mm(p);
+ struct mm_struct *mm;
task_t * g, * q;
- if (!mm)
- return NULL;
- if (mm == &init_mm) {
- mmput(mm);
- return NULL;
- }
+ mm = p->mm;
+
+ /* WARNING: mm may not be dereferenced since we did not obtain its
+ * value from get_task_mm(p). This is OK since all we need to do is
+ * compare mm to q->mm below.
+ *
+ * Furthermore, even if mm contains a non-NULL value, p->mm may
+ * change to NULL at any time since we do not hold task_lock(p).
+ * However, this is of no concern to us.
+ */
+
+ if (mm == NULL || mm == &init_mm)
+ return 1;
__oom_kill_task(p, message);
/*
@@ -266,13 +283,12 @@ static struct mm_struct *oom_kill_task(task_t *p, const char *message)
__oom_kill_task(q, message);
while_each_thread(g, q);
- return mm;
+ return 0;
}
-static struct mm_struct *oom_kill_process(struct task_struct *p,
- unsigned long points, const char *message)
+static int oom_kill_process(struct task_struct *p, unsigned long points,
+ const char *message)
{
- struct mm_struct *mm;
struct task_struct *c;
struct list_head *tsk;
@@ -283,9 +299,8 @@ static struct mm_struct *oom_kill_process(struct task_struct *p,
c = list_entry(tsk, struct task_struct, sibling);
if (c->mm == p->mm)
continue;
- mm = oom_kill_task(c, message);
- if (mm)
- return mm;
+ if (!oom_kill_task(c, message))
+ return 0;
}
return oom_kill_task(p, message);
}
@@ -300,7 +315,6 @@ static struct mm_struct *oom_kill_process(struct task_struct *p,
*/
void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
{
- struct mm_struct *mm = NULL;
task_t *p;
unsigned long points = 0;
@@ -320,12 +334,12 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
*/
switch (constrained_alloc(zonelist, gfp_mask)) {
case CONSTRAINT_MEMORY_POLICY:
- mm = oom_kill_process(current, points,
+ oom_kill_process(current, points,
"No available memory (MPOL_BIND)");
break;
case CONSTRAINT_CPUSET:
- mm = oom_kill_process(current, points,
+ oom_kill_process(current, points,
"No available memory in cpuset");
break;
@@ -347,8 +361,7 @@ retry:
panic("Out of memory and no killable processes...\n");
}
- mm = oom_kill_process(p, points, "Out of memory");
- if (!mm)
+ if (oom_kill_process(p, points, "Out of memory"))
goto retry;
break;
@@ -357,8 +370,6 @@ retry:
out:
read_unlock(&tasklist_lock);
cpuset_unlock();
- if (mm)
- mmput(mm);
/*
* Give "p" a good chance of killing itself before we
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 893d7677579e..75d7f48b79bb 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -72,13 +72,12 @@ int dirty_background_ratio = 10;
int vm_dirty_ratio = 40;
/*
- * The interval between `kupdate'-style writebacks, in centiseconds
- * (hundredths of a second)
+ * The interval between `kupdate'-style writebacks, in jiffies
*/
int dirty_writeback_interval = 5 * HZ;
/*
- * The longest number of centiseconds for which data is allowed to remain dirty
+ * The longest number of jiffies for which data is allowed to remain dirty
*/
int dirty_expire_interval = 30 * HZ;
@@ -258,7 +257,7 @@ static void balance_dirty_pages(struct address_space *mapping)
/**
* balance_dirty_pages_ratelimited_nr - balance dirty memory state
* @mapping: address_space which was dirtied
- * @nr_pages: number of pages which the caller has just dirtied
+ * @nr_pages_dirtied: number of pages which the caller has just dirtied
*
* Processes which are dirtying memory should call in here once for each page
* which was newly dirtied. The function will periodically check the system's
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dc523a1f270d..ea77c999047e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -51,6 +51,7 @@ nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
EXPORT_SYMBOL(node_possible_map);
unsigned long totalram_pages __read_mostly;
unsigned long totalhigh_pages __read_mostly;
+unsigned long totalreserve_pages __read_mostly;
long nr_swap_pages;
int percpu_pagelist_fraction;
@@ -151,7 +152,8 @@ static void bad_page(struct page *page)
1 << PG_reclaim |
1 << PG_slab |
1 << PG_swapcache |
- 1 << PG_writeback );
+ 1 << PG_writeback |
+ 1 << PG_buddy );
set_page_count(page, 0);
reset_page_mapcount(page);
page->mapping = NULL;
@@ -230,18 +232,20 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
* zone->lock is already acquired when we use these.
* So, we don't need atomic page->flags operations here.
*/
-static inline unsigned long page_order(struct page *page) {
+static inline unsigned long page_order(struct page *page)
+{
return page_private(page);
}
-static inline void set_page_order(struct page *page, int order) {
+static inline void set_page_order(struct page *page, int order)
+{
set_page_private(page, order);
- __SetPagePrivate(page);
+ __SetPageBuddy(page);
}
static inline void rmv_page_order(struct page *page)
{
- __ClearPagePrivate(page);
+ __ClearPageBuddy(page);
set_page_private(page, 0);
}
@@ -280,11 +284,13 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
* This function checks whether a page is free && is the buddy
* we can do coalesce a page and its buddy if
* (a) the buddy is not in a hole &&
- * (b) the buddy is free &&
- * (c) the buddy is on the buddy system &&
- * (d) a page and its buddy have the same order.
- * for recording page's order, we use page_private(page) and PG_private.
+ * (b) the buddy is in the buddy system &&
+ * (c) a page and its buddy have the same order.
*
+ * For recording whether a page is in the buddy system, we use PG_buddy.
+ * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
+ *
+ * For recording page's order, we use page_private(page).
*/
static inline int page_is_buddy(struct page *page, int order)
{
@@ -293,11 +299,11 @@ static inline int page_is_buddy(struct page *page, int order)
return 0;
#endif
- if (PagePrivate(page) &&
- (page_order(page) == order) &&
- page_count(page) == 0)
- return 1;
- return 0;
+ if (PageBuddy(page) && page_order(page) == order) {
+ BUG_ON(page_count(page) != 0);
+ return 1;
+ }
+ return 0;
}
/*
@@ -313,7 +319,7 @@ static inline int page_is_buddy(struct page *page, int order)
* as necessary, plus some accounting needed to play nicely with other
* parts of the VM system.
* At each level, we keep a list of pages, which are heads of continuous
- * free pages of length of (1 << order) and marked with PG_Private.Page's
+ * free pages of length of (1 << order) and marked with PG_buddy. Page's
* order is recorded in page_private(page) field.
* So when we are allocating or freeing one, we can derive the state of the
* other. That is, if we allocate a small block, and both were
@@ -376,7 +382,8 @@ static inline int free_pages_check(struct page *page)
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
- 1 << PG_reserved ))))
+ 1 << PG_reserved |
+ 1 << PG_buddy ))))
bad_page(page);
if (PageDirty(page))
__ClearPageDirty(page);
@@ -524,7 +531,8 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
- 1 << PG_reserved ))))
+ 1 << PG_reserved |
+ 1 << PG_buddy ))))
bad_page(page);
/*
@@ -1954,7 +1962,7 @@ static inline void free_zone_pagesets(int cpu)
}
}
-static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
+static int pageset_cpuup_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
@@ -2472,6 +2480,38 @@ void __init page_alloc_init(void)
}
/*
+ * calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio
+ * or min_free_kbytes changes.
+ */
+static void calculate_totalreserve_pages(void)
+{
+ struct pglist_data *pgdat;
+ unsigned long reserve_pages = 0;
+ int i, j;
+
+ for_each_online_pgdat(pgdat) {
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ struct zone *zone = pgdat->node_zones + i;
+ unsigned long max = 0;
+
+ /* Find valid and maximum lowmem_reserve in the zone */
+ for (j = i; j < MAX_NR_ZONES; j++) {
+ if (zone->lowmem_reserve[j] > max)
+ max = zone->lowmem_reserve[j];
+ }
+
+ /* we treat pages_high as reserved pages. */
+ max += zone->pages_high;
+
+ if (max > zone->present_pages)
+ max = zone->present_pages;
+ reserve_pages += max;
+ }
+ }
+ totalreserve_pages = reserve_pages;
+}
+
+/*
* setup_per_zone_lowmem_reserve - called whenever
* sysctl_lower_zone_reserve_ratio changes. Ensures that each zone
* has a correct pages reserved value, so an adequate number of
@@ -2502,6 +2542,9 @@ static void setup_per_zone_lowmem_reserve(void)
}
}
}
+
+ /* update totalreserve_pages */
+ calculate_totalreserve_pages();
}
/*
@@ -2556,6 +2599,9 @@ void setup_per_zone_pages_min(void)
zone->pages_high = zone->pages_min + tmp / 2;
spin_unlock_irqrestore(&zone->lru_lock, flags);
}
+
+ /* update totalreserve_pages */
+ calculate_totalreserve_pages();
}
/*
diff --git a/mm/shmem.c b/mm/shmem.c
index 37eaf42ed2c6..4c5e68e4e9ae 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -46,6 +46,8 @@
#include <linux/mempolicy.h>
#include <linux/namei.h>
#include <linux/ctype.h>
+#include <linux/migrate.h>
+
#include <asm/uaccess.h>
#include <asm/div64.h>
#include <asm/pgtable.h>
@@ -2173,6 +2175,7 @@ static struct address_space_operations shmem_aops = {
.prepare_write = shmem_prepare_write,
.commit_write = simple_commit_write,
#endif
+ .migratepage = migrate_page,
};
static struct file_operations shmem_file_operations = {
diff --git a/mm/slab.c b/mm/slab.c
index 4cbf8bb13557..c32af7e7581e 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -420,6 +420,7 @@ struct kmem_cache {
unsigned long max_freeable;
unsigned long node_allocs;
unsigned long node_frees;
+ unsigned long node_overflow;
atomic_t allochit;
atomic_t allocmiss;
atomic_t freehit;
@@ -465,6 +466,7 @@ struct kmem_cache {
#define STATS_INC_ERR(x) ((x)->errors++)
#define STATS_INC_NODEALLOCS(x) ((x)->node_allocs++)
#define STATS_INC_NODEFREES(x) ((x)->node_frees++)
+#define STATS_INC_ACOVERFLOW(x) ((x)->node_overflow++)
#define STATS_SET_FREEABLE(x, i) \
do { \
if ((x)->max_freeable < i) \
@@ -484,6 +486,7 @@ struct kmem_cache {
#define STATS_INC_ERR(x) do { } while (0)
#define STATS_INC_NODEALLOCS(x) do { } while (0)
#define STATS_INC_NODEFREES(x) do { } while (0)
+#define STATS_INC_ACOVERFLOW(x) do { } while (0)
#define STATS_SET_FREEABLE(x, i) do { } while (0)
#define STATS_INC_ALLOCHIT(x) do { } while (0)
#define STATS_INC_ALLOCMISS(x) do { } while (0)
@@ -976,7 +979,8 @@ static void __drain_alien_cache(struct kmem_cache *cachep,
* That way we could avoid the overhead of putting the objects
* into the free lists and getting them back later.
*/
- transfer_objects(rl3->shared, ac, ac->limit);
+ if (rl3->shared)
+ transfer_objects(rl3->shared, ac, ac->limit);
free_block(cachep, ac->entry, ac->avail, node);
ac->avail = 0;
@@ -1033,7 +1037,7 @@ static inline void free_alien_cache(struct array_cache **ac_ptr)
#endif
-static int __devinit cpuup_callback(struct notifier_block *nfb,
+static int cpuup_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -1297,8 +1301,7 @@ void __init kmem_cache_init(void)
if (cache_cache.num)
break;
}
- if (!cache_cache.num)
- BUG();
+ BUG_ON(!cache_cache.num);
cache_cache.gfporder = order;
cache_cache.colour = left_over / cache_cache.colour_off;
cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
@@ -1454,7 +1457,14 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
int i;
flags |= cachep->gfpflags;
+#ifndef CONFIG_MMU
+ /* nommu uses slab's for process anonymous memory allocations, so
+ * requires __GFP_COMP to properly refcount higher order allocations"
+ */
+ page = alloc_pages_node(nodeid, (flags | __GFP_COMP), cachep->gfporder);
+#else
page = alloc_pages_node(nodeid, flags, cachep->gfporder);
+#endif
if (!page)
return NULL;
addr = page_address(page);
@@ -1974,8 +1984,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* Always checks flags, a caller might be expecting debug support which
* isn't available.
*/
- if (flags & ~CREATE_MASK)
- BUG();
+ BUG_ON(flags & ~CREATE_MASK);
/*
* Check that size is in terms of words. This is needed to avoid
@@ -2206,8 +2215,7 @@ static int __node_shrink(struct kmem_cache *cachep, int node)
slabp = list_entry(l3->slabs_free.prev, struct slab, list);
#if DEBUG
- if (slabp->inuse)
- BUG();
+ BUG_ON(slabp->inuse);
#endif
list_del(&slabp->list);
@@ -2248,8 +2256,7 @@ static int __cache_shrink(struct kmem_cache *cachep)
*/
int kmem_cache_shrink(struct kmem_cache *cachep)
{
- if (!cachep || in_interrupt())
- BUG();
+ BUG_ON(!cachep || in_interrupt());
return __cache_shrink(cachep);
}
@@ -2277,8 +2284,7 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
int i;
struct kmem_list3 *l3;
- if (!cachep || in_interrupt())
- BUG();
+ BUG_ON(!cachep || in_interrupt());
/* Don't let CPUs to come and go */
lock_cpu_hotplug();
@@ -2323,13 +2329,15 @@ EXPORT_SYMBOL(kmem_cache_destroy);
/* Get the memory for a slab management obj. */
static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
- int colour_off, gfp_t local_flags)
+ int colour_off, gfp_t local_flags,
+ int nodeid)
{
struct slab *slabp;
if (OFF_SLAB(cachep)) {
/* Slab management obj is off-slab. */
- slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
+ slabp = kmem_cache_alloc_node(cachep->slabp_cache,
+ local_flags, nodeid);
if (!slabp)
return NULL;
} else {
@@ -2339,6 +2347,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
slabp->inuse = 0;
slabp->colouroff = colour_off;
slabp->s_mem = objp + colour_off;
+ slabp->nodeid = nodeid;
return slabp;
}
@@ -2477,8 +2486,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
* Be lazy and only check for valid flags here, keeping it out of the
* critical path in kmem_cache_alloc().
*/
- if (flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW))
- BUG();
+ BUG_ON(flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW));
if (flags & SLAB_NO_GROW)
return 0;
@@ -2525,7 +2533,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
goto failed;
/* Get slab management. */
- slabp = alloc_slabmgmt(cachep, objp, offset, local_flags);
+ slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid);
if (!slabp)
goto opps1;
@@ -3086,9 +3094,11 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
if (l3->alien && l3->alien[nodeid]) {
alien = l3->alien[nodeid];
spin_lock(&alien->lock);
- if (unlikely(alien->avail == alien->limit))
+ if (unlikely(alien->avail == alien->limit)) {
+ STATS_INC_ACOVERFLOW(cachep);
__drain_alien_cache(cachep,
alien, nodeid);
+ }
alien->entry[alien->avail++] = objp;
spin_unlock(&alien->lock);
} else {
@@ -3766,7 +3776,7 @@ static void print_slabinfo_header(struct seq_file *m)
seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
#if STATS
seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
- "<error> <maxfreeable> <nodeallocs> <remotefrees>");
+ "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
#endif
seq_putc(m, '\n');
@@ -3880,11 +3890,12 @@ static int s_show(struct seq_file *m, void *p)
unsigned long max_freeable = cachep->max_freeable;
unsigned long node_allocs = cachep->node_allocs;
unsigned long node_frees = cachep->node_frees;
+ unsigned long overflows = cachep->node_overflow;
seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \
- %4lu %4lu %4lu %4lu", allocs, high, grown,
+ %4lu %4lu %4lu %4lu %4lu", allocs, high, grown,
reaped, errors, max_freeable, node_allocs,
- node_frees);
+ node_frees, overflows);
}
/* cpu stats */
{
diff --git a/mm/slob.c b/mm/slob.c
index 9bcc7e2cabfd..a68255ba4553 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -354,9 +354,7 @@ void *__alloc_percpu(size_t size)
if (!pdata)
return NULL;
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_possible(i))
- continue;
+ for_each_possible_cpu(i) {
pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
if (!pdata->ptrs[i])
goto unwind_oom;
@@ -383,11 +381,9 @@ free_percpu(const void *objp)
int i;
struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_possible(i))
- continue;
+ for_each_possible_cpu(i)
kfree(p->ptrs[i]);
- }
+
kfree(p);
}
EXPORT_SYMBOL(free_percpu);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index d7af296833fc..e0e1583f32c2 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -148,8 +148,7 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)
swp_entry_t entry;
int err;
- if (!PageLocked(page))
- BUG();
+ BUG_ON(!PageLocked(page));
for (;;) {
entry = get_swap_page();
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 729eb3eec75f..c0504f1e34eb 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -321,8 +321,7 @@ void __vunmap(void *addr, int deallocate_pages)
int i;
for (i = 0; i < area->nr_pages; i++) {
- if (unlikely(!area->pages[i]))
- BUG();
+ BUG_ON(!area->pages[i]);
__free_page(area->pages[i]);
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index acdf001d6941..4649a63a8cb6 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1328,7 +1328,7 @@ repeat:
not required for correctness. So if the last cpu in a node goes
away, we get changed to run anywhere: as the first one comes back,
restore their cpu bindings. */
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
pg_data_t *pgdat;
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 3ab4e7947bab..1a786bfaa416 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -2,7 +2,6 @@
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
#include <linux/config.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -54,24 +53,24 @@ static struct net_device *clip_devs;
static struct atm_vcc *atmarpd;
static struct neigh_table clip_tbl;
static struct timer_list idle_timer;
-static int start_timer = 1;
-
-static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
+static int to_atmarpd(enum atmarp_ctrl_type type, int itf, unsigned long ip)
{
struct sock *sk;
struct atmarp_ctrl *ctrl;
struct sk_buff *skb;
- DPRINTK("to_atmarpd(%d)\n",type);
- if (!atmarpd) return -EUNATCH;
+ DPRINTK("to_atmarpd(%d)\n", type);
+ if (!atmarpd)
+ return -EUNATCH;
skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
- if (!skb) return -ENOMEM;
+ if (!skb)
+ return -ENOMEM;
ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
ctrl->type = type;
ctrl->itf_num = itf;
ctrl->ip = ip;
- atm_force_charge(atmarpd,skb->truesize);
+ atm_force_charge(atmarpd, skb->truesize);
sk = sk_atm(atmarpd);
skb_queue_tail(&sk->sk_receive_queue, skb);
@@ -79,26 +78,24 @@ static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
return 0;
}
-
-static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry)
+static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
{
- DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry,
- entry->neigh);
+ DPRINTK("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry,
+ entry->neigh);
clip_vcc->entry = entry;
- clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
+ clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
clip_vcc->next = entry->vccs;
entry->vccs = clip_vcc;
entry->neigh->used = jiffies;
}
-
static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
{
struct atmarp_entry *entry = clip_vcc->entry;
struct clip_vcc **walk;
if (!entry) {
- printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
+ printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
return;
}
spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */
@@ -107,24 +104,24 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
if (*walk == clip_vcc) {
int error;
- *walk = clip_vcc->next; /* atomic */
+ *walk = clip_vcc->next; /* atomic */
clip_vcc->entry = NULL;
if (clip_vcc->xoff)
netif_wake_queue(entry->neigh->dev);
if (entry->vccs)
goto out;
- entry->expires = jiffies-1;
- /* force resolution or expiration */
+ entry->expires = jiffies - 1;
+ /* force resolution or expiration */
error = neigh_update(entry->neigh, NULL, NUD_NONE,
NEIGH_UPDATE_F_ADMIN);
if (error)
printk(KERN_CRIT "unlink_clip_vcc: "
- "neigh_update failed with %d\n",error);
+ "neigh_update failed with %d\n", error);
goto out;
}
printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
- "0x%p)\n",entry,clip_vcc);
-out:
+ "0x%p)\n", entry, clip_vcc);
+ out:
spin_unlock_bh(&entry->neigh->dev->xmit_lock);
}
@@ -153,13 +150,13 @@ static int neigh_check_cb(struct neighbour *n)
DPRINTK("destruction postponed with ref %d\n",
atomic_read(&n->refcnt));
- while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
+ while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
dev_kfree_skb(skb);
return 0;
}
- DPRINTK("expired neigh %p\n",n);
+ DPRINTK("expired neigh %p\n", n);
return 1;
}
@@ -167,7 +164,7 @@ static void idle_timer_check(unsigned long dummy)
{
write_lock(&clip_tbl.lock);
__neigh_for_each_release(&clip_tbl, neigh_check_cb);
- mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
+ mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
write_unlock(&clip_tbl.lock);
}
@@ -177,13 +174,13 @@ static int clip_arp_rcv(struct sk_buff *skb)
DPRINTK("clip_arp_rcv\n");
vcc = ATM_SKB(skb)->vcc;
- if (!vcc || !atm_charge(vcc,skb->truesize)) {
+ if (!vcc || !atm_charge(vcc, skb->truesize)) {
dev_kfree_skb_any(skb);
return 0;
}
- DPRINTK("pushing to %p\n",vcc);
- DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push);
- CLIP_VCC(vcc)->old_push(vcc,skb);
+ DPRINTK("pushing to %p\n", vcc);
+ DPRINTK("using %p\n", CLIP_VCC(vcc)->old_push);
+ CLIP_VCC(vcc)->old_push(vcc, skb);
return 0;
}
@@ -193,34 +190,38 @@ static const unsigned char llc_oui[] = {
0x03, /* Ctrl: Unnumbered Information Command PDU */
0x00, /* OUI: EtherType */
0x00,
- 0x00 };
+ 0x00
+};
-static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
+static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
DPRINTK("clip push\n");
if (!skb) {
- DPRINTK("removing VCC %p\n",clip_vcc);
- if (clip_vcc->entry) unlink_clip_vcc(clip_vcc);
- clip_vcc->old_push(vcc,NULL); /* pass on the bad news */
+ DPRINTK("removing VCC %p\n", clip_vcc);
+ if (clip_vcc->entry)
+ unlink_clip_vcc(clip_vcc);
+ clip_vcc->old_push(vcc, NULL); /* pass on the bad news */
kfree(clip_vcc);
return;
}
- atm_return(vcc,skb->truesize);
+ atm_return(vcc, skb->truesize);
skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
- /* clip_vcc->entry == NULL if we don't have an IP address yet */
+ /* clip_vcc->entry == NULL if we don't have an IP address yet */
if (!skb->dev) {
dev_kfree_skb_any(skb);
return;
}
ATM_SKB(skb)->vcc = vcc;
skb->mac.raw = skb->data;
- if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data,
- llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP);
+ if (!clip_vcc->encap
+ || skb->len < RFC1483LLC_LEN
+ || memcmp(skb->data, llc_oui, sizeof (llc_oui)))
+ skb->protocol = htons(ETH_P_IP);
else {
skb->protocol = ((u16 *) skb->data)[3];
- skb_pull(skb,RFC1483LLC_LEN);
+ skb_pull(skb, RFC1483LLC_LEN);
if (skb->protocol == htons(ETH_P_ARP)) {
PRIV(skb->dev)->stats.rx_packets++;
PRIV(skb->dev)->stats.rx_bytes += skb->len;
@@ -235,58 +236,54 @@ static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
netif_rx(skb);
}
-
/*
* Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
* clip_pop is atomic with respect to the critical section in clip_start_xmit.
*/
-
-static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
struct net_device *dev = skb->dev;
int old;
unsigned long flags;
- DPRINTK("clip_pop(vcc %p)\n",vcc);
- clip_vcc->old_pop(vcc,skb);
+ DPRINTK("clip_pop(vcc %p)\n", vcc);
+ clip_vcc->old_pop(vcc, skb);
/* skb->dev == NULL in outbound ARP packets */
- if (!dev) return;
- spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
- if (atm_may_send(vcc,0)) {
- old = xchg(&clip_vcc->xoff,0);
- if (old) netif_wake_queue(dev);
+ if (!dev)
+ return;
+ spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
+ if (atm_may_send(vcc, 0)) {
+ old = xchg(&clip_vcc->xoff, 0);
+ if (old)
+ netif_wake_queue(dev);
}
- spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
+ spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
}
-
static void clip_neigh_destroy(struct neighbour *neigh)
{
- DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh);
+ DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh);
if (NEIGH2ENTRY(neigh)->vccs)
printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef;
}
-
-static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb)
+static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
{
- DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb);
- to_atmarpd(act_need,PRIV(neigh->dev)->number,NEIGH2ENTRY(neigh)->ip);
+ DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
+ to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip);
}
-
-static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb)
+static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
{
#ifndef CONFIG_ATM_CLIP_NO_ICMP
- icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
#endif
kfree_skb(skb);
}
-
static struct neigh_ops clip_neigh_ops = {
.family = AF_INET,
.solicit = clip_neigh_solicit,
@@ -297,7 +294,6 @@ static struct neigh_ops clip_neigh_ops = {
.queue_xmit = dev_queue_xmit,
};
-
static int clip_constructor(struct neighbour *neigh)
{
struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
@@ -305,9 +301,10 @@ static int clip_constructor(struct neighbour *neigh)
struct in_device *in_dev;
struct neigh_parms *parms;
- DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry);
+ DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
neigh->type = inet_addr_type(entry->ip);
- if (neigh->type != RTN_UNICAST) return -EINVAL;
+ if (neigh->type != RTN_UNICAST)
+ return -EINVAL;
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
@@ -326,13 +323,13 @@ static int clip_constructor(struct neighbour *neigh)
neigh->ops->connected_output : neigh->ops->output;
entry->neigh = neigh;
entry->vccs = NULL;
- entry->expires = jiffies-1;
+ entry->expires = jiffies - 1;
return 0;
}
static u32 clip_hash(const void *pkey, const struct net_device *dev)
{
- return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd);
+ return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
}
static struct neigh_table clip_tbl = {
@@ -366,7 +363,6 @@ static struct neigh_table clip_tbl = {
.gc_thresh3 = 1024,
};
-
/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
/*
@@ -376,15 +372,13 @@ static struct neigh_table clip_tbl = {
* clip_setentry.
*/
-
-static int clip_encap(struct atm_vcc *vcc,int mode)
+static int clip_encap(struct atm_vcc *vcc, int mode)
{
CLIP_VCC(vcc)->encap = mode;
return 0;
}
-
-static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
+static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct clip_priv *clip_priv = PRIV(dev);
struct atmarp_entry *entry;
@@ -392,7 +386,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
int old;
unsigned long flags;
- DPRINTK("clip_start_xmit (skb %p)\n",skb);
+ DPRINTK("clip_start_xmit (skb %p)\n", skb);
if (!skb->dst) {
printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
dev_kfree_skb(skb);
@@ -401,9 +395,9 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
}
if (!skb->dst->neighbour) {
#if 0
- skb->dst->neighbour = clip_find_neighbour(skb->dst,1);
+ skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
if (!skb->dst->neighbour) {
- dev_kfree_skb(skb); /* lost that one */
+ dev_kfree_skb(skb); /* lost that one */
clip_priv->stats.tx_dropped++;
return 0;
}
@@ -417,73 +411,73 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
if (!entry->vccs) {
if (time_after(jiffies, entry->expires)) {
/* should be resolved */
- entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ;
- to_atmarpd(act_need,PRIV(dev)->number,entry->ip);
+ entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
+ to_atmarpd(act_need, PRIV(dev)->number, entry->ip);
}
if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
- skb_queue_tail(&entry->neigh->arp_queue,skb);
+ skb_queue_tail(&entry->neigh->arp_queue, skb);
else {
dev_kfree_skb(skb);
clip_priv->stats.tx_dropped++;
}
return 0;
}
- DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs);
+ DPRINTK("neigh %p, vccs %p\n", entry, entry->vccs);
ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
- DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc);
+ DPRINTK("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc);
if (entry->vccs->encap) {
void *here;
- here = skb_push(skb,RFC1483LLC_LEN);
- memcpy(here,llc_oui,sizeof(llc_oui));
+ here = skb_push(skb, RFC1483LLC_LEN);
+ memcpy(here, llc_oui, sizeof(llc_oui));
((u16 *) here)[3] = skb->protocol;
}
atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = vcc->atm_options;
entry->vccs->last_use = jiffies;
- DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
- old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */
+ DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
+ old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
if (old) {
printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
return 0;
}
clip_priv->stats.tx_packets++;
clip_priv->stats.tx_bytes += skb->len;
- (void) vcc->send(vcc,skb);
- if (atm_may_send(vcc,0)) {
+ vcc->send(vcc, skb);
+ if (atm_may_send(vcc, 0)) {
entry->vccs->xoff = 0;
return 0;
}
- spin_lock_irqsave(&clip_priv->xoff_lock,flags);
- netif_stop_queue(dev); /* XOFF -> throttle immediately */
+ spin_lock_irqsave(&clip_priv->xoff_lock, flags);
+ netif_stop_queue(dev); /* XOFF -> throttle immediately */
barrier();
if (!entry->vccs->xoff)
netif_start_queue(dev);
- /* Oh, we just raced with clip_pop. netif_start_queue should be
- good enough, because nothing should really be asleep because
- of the brief netif_stop_queue. If this isn't true or if it
- changes, use netif_wake_queue instead. */
- spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
+ /* Oh, we just raced with clip_pop. netif_start_queue should be
+ good enough, because nothing should really be asleep because
+ of the brief netif_stop_queue. If this isn't true or if it
+ changes, use netif_wake_queue instead. */
+ spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
return 0;
}
-
static struct net_device_stats *clip_get_stats(struct net_device *dev)
{
return &PRIV(dev)->stats;
}
-
-static int clip_mkip(struct atm_vcc *vcc,int timeout)
+static int clip_mkip(struct atm_vcc *vcc, int timeout)
{
struct clip_vcc *clip_vcc;
struct sk_buff_head copy;
struct sk_buff *skb;
- if (!vcc->push) return -EBADFD;
- clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL);
- if (!clip_vcc) return -ENOMEM;
- DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc);
+ if (!vcc->push)
+ return -EBADFD;
+ clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
+ if (!clip_vcc)
+ return -ENOMEM;
+ DPRINTK("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
clip_vcc->vcc = vcc;
vcc->user_back = clip_vcc;
set_bit(ATM_VF_IS_CLIP, &vcc->flags);
@@ -491,7 +485,7 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
clip_vcc->xoff = 0;
clip_vcc->encap = 1;
clip_vcc->last_use = jiffies;
- clip_vcc->idle_timeout = timeout*HZ;
+ clip_vcc->idle_timeout = timeout * HZ;
clip_vcc->old_push = vcc->push;
clip_vcc->old_pop = vcc->pop;
vcc->push = clip_push;
@@ -501,27 +495,25 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
/* re-process everything received between connection setup and MKIP */
while ((skb = skb_dequeue(&copy)) != NULL)
if (!clip_devs) {
- atm_return(vcc,skb->truesize);
+ atm_return(vcc, skb->truesize);
kfree_skb(skb);
- }
- else {
+ } else {
unsigned int len = skb->len;
- clip_push(vcc,skb);
+ clip_push(vcc, skb);
PRIV(skb->dev)->stats.rx_packets--;
PRIV(skb->dev)->stats.rx_bytes -= len;
}
return 0;
}
-
-static int clip_setentry(struct atm_vcc *vcc,u32 ip)
+static int clip_setentry(struct atm_vcc *vcc, u32 ip)
{
struct neighbour *neigh;
struct atmarp_entry *entry;
int error;
struct clip_vcc *clip_vcc;
- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } };
+ struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
struct rtable *rt;
if (vcc->push != clip_push) {
@@ -538,28 +530,29 @@ static int clip_setentry(struct atm_vcc *vcc,u32 ip)
unlink_clip_vcc(clip_vcc);
return 0;
}
- error = ip_route_output_key(&rt,&fl);
- if (error) return error;
- neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
+ error = ip_route_output_key(&rt, &fl);
+ if (error)
+ return error;
+ neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1);
ip_rt_put(rt);
if (!neigh)
return -ENOMEM;
entry = NEIGH2ENTRY(neigh);
if (entry != clip_vcc->entry) {
- if (!clip_vcc->entry) DPRINTK("setentry: add\n");
+ if (!clip_vcc->entry)
+ DPRINTK("setentry: add\n");
else {
DPRINTK("setentry: update\n");
unlink_clip_vcc(clip_vcc);
}
- link_vcc(clip_vcc,entry);
+ link_vcc(clip_vcc, entry);
}
- error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
- NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
+ error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
+ NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
neigh_release(neigh);
return error;
}
-
static void clip_setup(struct net_device *dev)
{
dev->hard_start_xmit = clip_start_xmit;
@@ -568,15 +561,14 @@ static void clip_setup(struct net_device *dev)
dev->type = ARPHRD_ATM;
dev->hard_header_len = RFC1483LLC_LEN;
dev->mtu = RFC1626_MTU;
- dev->tx_queue_len = 100; /* "normal" queue (packets) */
- /* When using a "real" qdisc, the qdisc determines the queue */
- /* length. tx_queue_len is only used for the default case, */
- /* without any more elaborate queuing. 100 is a reasonable */
- /* compromise between decent burst-tolerance and protection */
- /* against memory hogs. */
+ dev->tx_queue_len = 100; /* "normal" queue (packets) */
+ /* When using a "real" qdisc, the qdisc determines the queue */
+ /* length. tx_queue_len is only used for the default case, */
+ /* without any more elaborate queuing. 100 is a reasonable */
+ /* compromise between decent burst-tolerance and protection */
+ /* against memory hogs. */
}
-
static int clip_create(int number)
{
struct net_device *dev;
@@ -585,19 +577,19 @@ static int clip_create(int number)
if (number != -1) {
for (dev = clip_devs; dev; dev = PRIV(dev)->next)
- if (PRIV(dev)->number == number) return -EEXIST;
- }
- else {
+ if (PRIV(dev)->number == number)
+ return -EEXIST;
+ } else {
number = 0;
for (dev = clip_devs; dev; dev = PRIV(dev)->next)
if (PRIV(dev)->number >= number)
- number = PRIV(dev)->number+1;
+ number = PRIV(dev)->number + 1;
}
dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
if (!dev)
return -ENOMEM;
clip_priv = PRIV(dev);
- sprintf(dev->name,"atm%d",number);
+ sprintf(dev->name, "atm%d", number);
spin_lock_init(&clip_priv->xoff_lock);
clip_priv->number = number;
error = register_netdev(dev);
@@ -607,53 +599,48 @@ static int clip_create(int number)
}
clip_priv->next = clip_devs;
clip_devs = dev;
- DPRINTK("registered (net:%s)\n",dev->name);
+ DPRINTK("registered (net:%s)\n", dev->name);
return number;
}
-
-static int clip_device_event(struct notifier_block *this,unsigned long event,
- void *dev)
+static int clip_device_event(struct notifier_block *this, unsigned long event,
+ void *arg)
{
+ struct net_device *dev = arg;
+
+ if (event == NETDEV_UNREGISTER) {
+ neigh_ifdown(&clip_tbl, dev);
+ return NOTIFY_DONE;
+ }
+
/* ignore non-CLIP devices */
- if (((struct net_device *) dev)->type != ARPHRD_ATM ||
- ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit)
+ if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
return NOTIFY_DONE;
+
switch (event) {
- case NETDEV_UP:
- DPRINTK("clip_device_event NETDEV_UP\n");
- (void) to_atmarpd(act_up,PRIV(dev)->number,0);
- break;
- case NETDEV_GOING_DOWN:
- DPRINTK("clip_device_event NETDEV_DOWN\n");
- (void) to_atmarpd(act_down,PRIV(dev)->number,0);
- break;
- case NETDEV_CHANGE:
- case NETDEV_CHANGEMTU:
- DPRINTK("clip_device_event NETDEV_CHANGE*\n");
- (void) to_atmarpd(act_change,PRIV(dev)->number,0);
- break;
- case NETDEV_REBOOT:
- case NETDEV_REGISTER:
- case NETDEV_DOWN:
- DPRINTK("clip_device_event %ld\n",event);
- /* ignore */
- break;
- default:
- printk(KERN_WARNING "clip_device_event: unknown event "
- "%ld\n",event);
- break;
+ case NETDEV_UP:
+ DPRINTK("clip_device_event NETDEV_UP\n");
+ to_atmarpd(act_up, PRIV(dev)->number, 0);
+ break;
+ case NETDEV_GOING_DOWN:
+ DPRINTK("clip_device_event NETDEV_DOWN\n");
+ to_atmarpd(act_down, PRIV(dev)->number, 0);
+ break;
+ case NETDEV_CHANGE:
+ case NETDEV_CHANGEMTU:
+ DPRINTK("clip_device_event NETDEV_CHANGE*\n");
+ to_atmarpd(act_change, PRIV(dev)->number, 0);
+ break;
}
return NOTIFY_DONE;
}
-
-static int clip_inet_event(struct notifier_block *this,unsigned long event,
- void *ifa)
+static int clip_inet_event(struct notifier_block *this, unsigned long event,
+ void *ifa)
{
struct in_device *in_dev;
- in_dev = ((struct in_ifaddr *) ifa)->ifa_dev;
+ in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
if (!in_dev || !in_dev->dev) {
printk(KERN_WARNING "clip_inet_event: no device\n");
return NOTIFY_DONE;
@@ -662,23 +649,20 @@ static int clip_inet_event(struct notifier_block *this,unsigned long event,
* Transitions are of the down-change-up type, so it's sufficient to
* handle the change on up.
*/
- if (event != NETDEV_UP) return NOTIFY_DONE;
- return clip_device_event(this,NETDEV_CHANGE,in_dev->dev);
+ if (event != NETDEV_UP)
+ return NOTIFY_DONE;
+ return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
}
static struct notifier_block clip_dev_notifier = {
- clip_device_event,
- NULL,
- 0
+ .notifier_call = clip_device_event,
};
static struct notifier_block clip_inet_notifier = {
- clip_inet_event,
- NULL,
- 0
+ .notifier_call = clip_inet_event,
};
@@ -686,14 +670,12 @@ static struct notifier_block clip_inet_notifier = {
static void atmarpd_close(struct atm_vcc *vcc)
{
DPRINTK("atmarpd_close\n");
- atmarpd = NULL; /* assumed to be atomic */
- barrier();
- unregister_inetaddr_notifier(&clip_inet_notifier);
- unregister_netdevice_notifier(&clip_dev_notifier);
- if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
- printk(KERN_ERR "atmarpd_close: closing with requests "
- "pending\n");
+
+ rtnl_lock();
+ atmarpd = NULL;
skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
+ rtnl_unlock();
+
DPRINTK("(done)\n");
module_put(THIS_MODULE);
}
@@ -714,14 +696,14 @@ static struct atm_dev atmarpd_dev = {
static int atm_init_atmarp(struct atm_vcc *vcc)
{
- if (atmarpd) return -EADDRINUSE;
- if (start_timer) {
- start_timer = 0;
- init_timer(&idle_timer);
- idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ;
- idle_timer.function = idle_timer_check;
- add_timer(&idle_timer);
+ rtnl_lock();
+ if (atmarpd) {
+ rtnl_unlock();
+ return -EADDRINUSE;
}
+
+ mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
+
atmarpd = vcc;
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
@@ -731,10 +713,7 @@ static int atm_init_atmarp(struct atm_vcc *vcc)
vcc->push = NULL;
vcc->pop = NULL; /* crash */
vcc->push_oam = NULL; /* crash */
- if (register_netdevice_notifier(&clip_dev_notifier))
- printk(KERN_ERR "register_netdevice_notifier failed\n");
- if (register_inetaddr_notifier(&clip_inet_notifier))
- printk(KERN_ERR "register_inetaddr_notifier failed\n");
+ rtnl_unlock();
return 0;
}
@@ -744,53 +723,53 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
int err = 0;
switch (cmd) {
- case SIOCMKCLIP:
- case ATMARPD_CTRL:
- case ATMARP_MKIP:
- case ATMARP_SETENTRY:
- case ATMARP_ENCAP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- break;
- default:
- return -ENOIOCTLCMD;
+ case SIOCMKCLIP:
+ case ATMARPD_CTRL:
+ case ATMARP_MKIP:
+ case ATMARP_SETENTRY:
+ case ATMARP_ENCAP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ break;
+ default:
+ return -ENOIOCTLCMD;
}
switch (cmd) {
- case SIOCMKCLIP:
- err = clip_create(arg);
- break;
- case ATMARPD_CTRL:
- err = atm_init_atmarp(vcc);
- if (!err) {
- sock->state = SS_CONNECTED;
- __module_get(THIS_MODULE);
- }
- break;
- case ATMARP_MKIP:
- err = clip_mkip(vcc ,arg);
- break;
- case ATMARP_SETENTRY:
- err = clip_setentry(vcc, arg);
- break;
- case ATMARP_ENCAP:
- err = clip_encap(vcc, arg);
- break;
+ case SIOCMKCLIP:
+ err = clip_create(arg);
+ break;
+ case ATMARPD_CTRL:
+ err = atm_init_atmarp(vcc);
+ if (!err) {
+ sock->state = SS_CONNECTED;
+ __module_get(THIS_MODULE);
+ }
+ break;
+ case ATMARP_MKIP:
+ err = clip_mkip(vcc, arg);
+ break;
+ case ATMARP_SETENTRY:
+ err = clip_setentry(vcc, arg);
+ break;
+ case ATMARP_ENCAP:
+ err = clip_encap(vcc, arg);
+ break;
}
return err;
}
static struct atm_ioctl clip_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = clip_ioctl,
+ .owner = THIS_MODULE,
+ .ioctl = clip_ioctl,
};
#ifdef CONFIG_PROC_FS
static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
{
- static int code[] = { 1,2,10,6,1,0 };
- static int e164[] = { 1,8,4,6,1,0 };
+ static int code[] = { 1, 2, 10, 6, 1, 0 };
+ static int e164[] = { 1, 8, 4, 6, 1, 0 };
if (*addr->sas_addr.pub) {
seq_printf(seq, "%s", addr->sas_addr.pub);
@@ -809,7 +788,7 @@ static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
for (i = 0; fields[i]; i++) {
for (j = fields[i]; j; j--)
seq_printf(seq, "%02X", *prv++);
- if (fields[i+1])
+ if (fields[i + 1])
seq_putc(seq, '.');
}
}
@@ -828,8 +807,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
(sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
- llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
- clip_vcc->encap);
+ llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
if (clip_vcc == SEQ_NO_VCC_TOKEN)
exp = entry->neigh->used;
@@ -839,10 +817,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
exp = (jiffies - exp) / HZ;
seq_printf(seq, "%-6s%-4s%-4s%5ld ",
- dev->name,
- svc ? "SVC" : "PVC",
- llc ? "LLC" : "NULL",
- exp);
+ dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
NIPQUAD(entry->ip));
@@ -860,8 +835,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
} else if (!svc) {
seq_printf(seq, "%d.%d.%d\n",
clip_vcc->vcc->dev->number,
- clip_vcc->vcc->vpi,
- clip_vcc->vcc->vci);
+ clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
} else {
svc_addr(seq, &clip_vcc->vcc->remote);
seq_putc(seq, '\n');
@@ -894,7 +868,7 @@ static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
}
static void *clip_seq_vcc_walk(struct clip_seq_state *state,
- struct atmarp_entry *e, loff_t *pos)
+ struct atmarp_entry *e, loff_t * pos)
{
struct clip_vcc *vcc = state->vcc;
@@ -911,24 +885,24 @@ static void *clip_seq_vcc_walk(struct clip_seq_state *state,
return vcc;
}
-
+
static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
- struct neighbour *n, loff_t *pos)
+ struct neighbour *n, loff_t * pos)
{
- struct clip_seq_state *state = (struct clip_seq_state *) _state;
+ struct clip_seq_state *state = (struct clip_seq_state *)_state;
return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
}
-static void *clip_seq_start(struct seq_file *seq, loff_t *pos)
+static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
{
return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
}
static int clip_seq_show(struct seq_file *seq, void *v)
{
- static char atm_arp_banner[] =
- "IPitf TypeEncp Idle IP address ATM address\n";
+ static char atm_arp_banner[] =
+ "IPitf TypeEncp Idle IP address ATM address\n";
if (v == SEQ_START_TOKEN) {
seq_puts(seq, atm_arp_banner);
@@ -939,7 +913,7 @@ static int clip_seq_show(struct seq_file *seq, void *v)
atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
}
- return 0;
+ return 0;
}
static struct seq_operations arp_seq_ops = {
@@ -988,20 +962,19 @@ static struct file_operations arp_seq_fops = {
static int __init atm_clip_init(void)
{
+ struct proc_dir_entry *p;
neigh_table_init(&clip_tbl);
clip_tbl_hook = &clip_tbl;
register_atm_ioctl(&clip_ioctl_ops);
+ register_netdevice_notifier(&clip_dev_notifier);
+ register_inetaddr_notifier(&clip_inet_notifier);
-#ifdef CONFIG_PROC_FS
-{
- struct proc_dir_entry *p;
+ setup_timer(&idle_timer, idle_timer_check, 0);
p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
if (p)
p->proc_fops = &arp_seq_fops;
-}
-#endif
return 0;
}
@@ -1012,13 +985,15 @@ static void __exit atm_clip_exit(void)
remove_proc_entry("arp", atm_proc_root);
+ unregister_inetaddr_notifier(&clip_inet_notifier);
+ unregister_netdevice_notifier(&clip_dev_notifier);
+
deregister_atm_ioctl(&clip_ioctl_ops);
/* First, stop the idle timer, so it stops banging
* on the table.
*/
- if (start_timer == 0)
- del_timer(&idle_timer);
+ del_timer_sync(&idle_timer);
/* Next, purge the table, so that the device
* unregister loop below does not hang due to
@@ -1042,5 +1017,6 @@ static void __exit atm_clip_exit(void)
module_init(atm_clip_init);
module_exit(atm_clip_exit);
-
+MODULE_AUTHOR("Werner Almesberger");
+MODULE_DESCRIPTION("Classical/IP over ATM interface");
MODULE_LICENSE("GPL");
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 6b61323ce23c..0c2d13ad69bb 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -255,7 +255,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
}
if ((err = hci_send_sco(conn->hcon, skb)) < 0)
- goto fail;
+ return err;
return count;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 2d24fb400e0c..56f3aa47e758 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
#include <linux/netfilter_bridge.h>
#include "br_private.h"
@@ -29,10 +30,15 @@ static inline int should_deliver(const struct net_bridge_port *p,
return 1;
}
+static inline unsigned packet_length(const struct sk_buff *skb)
+{
+ return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
+}
+
int br_dev_queue_push_xmit(struct sk_buff *skb)
{
/* drop mtu oversized packets except tso */
- if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
+ if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
kfree_skb(skb);
else {
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b7766562d72c..b0b7f55c1edd 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -125,9 +125,6 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
const unsigned char *dest = eth_hdr(skb)->h_dest;
- if (p->state == BR_STATE_DISABLED)
- goto err;
-
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f29450b788be..3da9264449f7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -765,6 +765,15 @@ out:
return NF_STOLEN;
}
+static int br_nf_dev_queue_xmit(struct sk_buff *skb)
+{
+ if (skb->protocol == htons(ETH_P_IP) &&
+ skb->len > skb->dev->mtu &&
+ !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+ return ip_fragment(skb, br_dev_queue_push_xmit);
+ else
+ return br_dev_queue_push_xmit(skb);
+}
/* PF_BRIDGE/POST_ROUTING ********************************************/
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
@@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
realoutdev = nf_bridge->netoutdev;
#endif
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
- br_dev_queue_push_xmit);
+ br_nf_dev_queue_xmit);
return NF_STOLEN;
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
if ((out->hard_start_xmit == br_dev_xmit &&
okfn != br_nf_forward_finish &&
- okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)
+ okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|| ((out->priv_flags & IFF_802_1Q_VLAN) &&
VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 01eae97c53d9..3a13ed643459 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -824,14 +824,14 @@ static int translate_table(struct ebt_replace *repl,
if (udc_cnt) {
/* this will get free'd in do_replace()/ebt_register_table()
if an error occurs */
- newinfo->chainstack = (struct ebt_chainstack **)
- vmalloc((highest_possible_processor_id()+1)
- * sizeof(struct ebt_chainstack));
+ newinfo->chainstack =
+ vmalloc((highest_possible_processor_id()+1)
+ * sizeof(*(newinfo->chainstack)));
if (!newinfo->chainstack)
return -ENOMEM;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
newinfo->chainstack[i] =
- vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+ vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
if (!newinfo->chainstack[i]) {
while (i)
vfree(newinfo->chainstack[--i]);
@@ -841,8 +841,7 @@ static int translate_table(struct ebt_replace *repl,
}
}
- cl_s = (struct ebt_cl_stack *)
- vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
+ cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
if (!cl_s)
return -ENOMEM;
i = 0; /* the i'th udc */
@@ -901,7 +900,7 @@ static void get_counters(struct ebt_counter *oldcounters,
sizeof(struct ebt_counter) * nentries);
/* add other counters to those of cpu 0 */
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == 0)
continue;
counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
@@ -944,8 +943,7 @@ static int do_replace(void __user *user, unsigned int len)
countersize = COUNTER_OFFSET(tmp.nentries) *
(highest_possible_processor_id()+1);
- newinfo = (struct ebt_table_info *)
- vmalloc(sizeof(struct ebt_table_info) + countersize);
+ newinfo = vmalloc(sizeof(*newinfo) + countersize);
if (!newinfo)
return -ENOMEM;
@@ -967,8 +965,7 @@ static int do_replace(void __user *user, unsigned int len)
/* the user wants counters back
the check on the size is done later, when we have the lock */
if (tmp.num_counters) {
- counterstmp = (struct ebt_counter *)
- vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
+ counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
if (!counterstmp) {
ret = -ENOMEM;
goto free_entries;
@@ -1036,7 +1033,7 @@ static int do_replace(void __user *user, unsigned int len)
vfree(table->entries);
if (table->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(table->chainstack[i]);
vfree(table->chainstack);
}
@@ -1054,7 +1051,7 @@ free_counterstmp:
vfree(counterstmp);
/* can be initialized in translate_table() */
if (newinfo->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
}
@@ -1148,8 +1145,7 @@ int ebt_register_table(struct ebt_table *table)
countersize = COUNTER_OFFSET(table->table->nentries) *
(highest_possible_processor_id()+1);
- newinfo = (struct ebt_table_info *)
- vmalloc(sizeof(struct ebt_table_info) + countersize);
+ newinfo = vmalloc(sizeof(*newinfo) + countersize);
ret = -ENOMEM;
if (!newinfo)
return -ENOMEM;
@@ -1201,7 +1197,7 @@ free_unlock:
mutex_unlock(&ebt_mutex);
free_chainstack:
if (newinfo->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
}
@@ -1224,7 +1220,7 @@ void ebt_unregister_table(struct ebt_table *table)
mutex_unlock(&ebt_mutex);
vfree(table->private->entries);
if (table->private->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(table->private->chainstack[i]);
vfree(table->private->chainstack);
}
@@ -1247,8 +1243,7 @@ static int update_counters(void __user *user, unsigned int len)
if (hlp.num_counters == 0)
return -EINVAL;
- if ( !(tmp = (struct ebt_counter *)
- vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
+ if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
MEMPRINT("Update_counters && nomemory\n");
return -ENOMEM;
}
@@ -1377,8 +1372,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
BUGPRINT("Num_counters wrong\n");
return -EINVAL;
}
- counterstmp = (struct ebt_counter *)
- vmalloc(nentries * sizeof(struct ebt_counter));
+ counterstmp = vmalloc(nentries * sizeof(*counterstmp));
if (!counterstmp) {
MEMPRINT("Couldn't copy counters, out of memory\n");
return -ENOMEM;
diff --git a/net/compat.c b/net/compat.c
index 8fd37cd7b501..d5d69fa15d07 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -476,8 +476,7 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
int err;
struct socket *sock;
- /* SO_SET_REPLACE seems to be the same in all levels */
- if (optname == IPT_SO_SET_REPLACE)
+ if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE)
return do_netfilter_replace(fd, level, optname,
optval, optlen);
diff --git a/net/core/dev.c b/net/core/dev.c
index 434220d093aa..3bad1afc89fa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2698,7 +2698,8 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
/* If command is `set a parameter', or
* `get the encoding parameters', check if
* the user has the right to do it */
- if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) {
+ if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE
+ || cmd == SIOCGIWENCODEEXT) {
if (!capable(CAP_NET_ADMIN))
return -EPERM;
}
@@ -3042,11 +3043,11 @@ void netdev_run_todo(void)
switch(dev->reg_state) {
case NETREG_REGISTERING:
+ dev->reg_state = NETREG_REGISTERED;
err = netdev_register_sysfs(dev);
if (err)
printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
dev->name, err);
- dev->reg_state = NETREG_REGISTERED;
break;
case NETREG_UNREGISTERING:
@@ -3100,12 +3101,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
- p = kmalloc(alloc_size, GFP_KERNEL);
+ p = kzalloc(alloc_size, GFP_KERNEL);
if (!p) {
printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
return NULL;
}
- memset(p, 0, alloc_size);
dev = (struct net_device *)
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
@@ -3347,7 +3347,7 @@ static int __init net_dev_init(void)
* Initialise the packet receive queues.
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct softnet_data *queue;
queue = &per_cpu(softnet_data, i);
diff --git a/net/core/dv.c b/net/core/dv.c
index cf581407538c..29ee77f15932 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev)
dev->divert = NULL;
if (dev->type == ARPHRD_ETHER) {
- dev->divert = (struct divert_blk *)
- kmalloc(alloc_size, GFP_KERNEL);
+ dev->divert = kzalloc(alloc_size, GFP_KERNEL);
if (dev->divert == NULL) {
printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
dev->name);
return -ENOMEM;
}
-
- memset(dev->divert, 0, sizeof(struct divert_blk));
dev_hold(dev);
}
diff --git a/net/core/filter.c b/net/core/filter.c
index 93fbd01d2259..5b4486a60cf6 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -34,6 +34,7 @@
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/unaligned.h>
#include <linux/filter.h>
/* No hurry in this branch */
@@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
load_w:
ptr = load_pointer(skb, k, 4, &tmp);
if (ptr != NULL) {
- A = ntohl(*(u32 *)ptr);
+ A = ntohl(get_unaligned((u32 *)ptr));
continue;
}
break;
@@ -186,7 +187,7 @@ load_w:
load_h:
ptr = load_pointer(skb, k, 2, &tmp);
if (ptr != NULL) {
- A = ntohs(*(u16 *)ptr);
+ A = ntohs(get_unaligned((u16 *)ptr));
continue;
}
break;
diff --git a/net/core/flow.c b/net/core/flow.c
index 55789f832eda..2191af5f26ac 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -79,7 +79,7 @@ static void flow_cache_new_hashrnd(unsigned long arg)
{
int i;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
flow_hash_rnd_recalc(i) = 1;
flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
@@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
/* NOTHING */;
flow_table(cpu) = (struct flow_cache_entry **)
- __get_free_pages(GFP_KERNEL, order);
+ __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
if (!flow_table(cpu))
panic("NET: failed to allocate flow cache order %lu\n", order);
- memset(flow_table(cpu), 0, PAGE_SIZE << order);
-
flow_hash_rnd_recalc(cpu) = 1;
flow_count(cpu) = 0;
@@ -363,7 +361,7 @@ static int __init flow_cache_init(void)
flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
add_timer(&flow_hash_rnd_timer);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
flow_cache_cpu_prepare(i);
hotcpu_notifier(flow_cache_cpu, 0);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index b07c029e8219..3cad026764f0 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
if (parm->interval < -2 || parm->interval > 3)
return -EINVAL;
- est = kmalloc(sizeof(*est), GFP_KERNEL);
+ est = kzalloc(sizeof(*est), GFP_KERNEL);
if (est == NULL)
return -ENOBUFS;
- memset(est, 0, sizeof(*est));
est->interval = parm->interval + 2;
est->bstats = bstats;
est->rate_est = rate_est;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0c8666872d10..4cf878efdb49 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries)
struct neighbour **ret;
if (size <= PAGE_SIZE) {
- ret = kmalloc(size, GFP_ATOMIC);
+ ret = kzalloc(size, GFP_ATOMIC);
} else {
ret = (struct neighbour **)
- __get_free_pages(GFP_ATOMIC, get_order(size));
+ __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
}
- if (ret)
- memset(ret, 0, size);
-
return ret;
}
@@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
if (hh->hh_type == protocol)
break;
- if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
- memset(hh, 0, sizeof(struct hh_cache));
+ if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
rwlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
@@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl)
tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
- tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
+ tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
if (!tbl->hash_buckets || !tbl->phash_buckets)
panic("cannot allocate neighbour cache hashes");
- memset(tbl->phash_buckets, 0, phsize);
-
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
rwlock_init(&tbl->lock);
@@ -1633,7 +1627,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
memset(&ndst, 0, sizeof(ndst));
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct neigh_statistics *st;
st = per_cpu_ptr(tbl->stats, cpu);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 21b68464cabb..c12990c9c603 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf)
operstate = IF_OPER_DOWN;
read_unlock(&dev_base_lock);
- if (operstate >= sizeof(operstates))
+ if (operstate >= ARRAY_SIZE(operstates))
return -EINVAL; /* should not happen */
return sprintf(buf, "%s\n", operstates[operstate]);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 1e44eda1fda9..79ebd75fbe4d 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
{
const int lopt_size = sizeof(struct listen_sock) +
nr_table_entries * sizeof(struct request_sock *);
- struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL);
+ struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
if (lopt == NULL)
return -ENOMEM;
- memset(lopt, 0, lopt_size);
-
for (lopt->max_qlen_log = 6;
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
lopt->max_qlen_log++);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 09464fa8d72f..fb3770f9c094 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -112,6 +112,14 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
BUG();
}
+void skb_truesize_bug(struct sk_buff *skb)
+{
+ printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
+ "len=%u, sizeof(sk_buff)=%Zd\n",
+ skb->truesize, skb->len, sizeof(struct sk_buff));
+}
+EXPORT_SYMBOL(skb_truesize_bug);
+
/* Allocate a new skbuff. We do this ourselves so we can fill in a few
* 'private' fields and also do memory statistics to find all the
* [BEEP] leaks.
diff --git a/net/core/stream.c b/net/core/stream.c
index 35e25259fd95..e9489696f694 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb)
{
struct sock *sk = skb->sk;
+ skb_truesize_check(skb);
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
sk->sk_forward_alloc += skb->truesize;
}
diff --git a/net/core/utils.c b/net/core/utils.c
index fdc4f38bc46c..4f96f389243d 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -121,7 +121,7 @@ void __init net_random_init(void)
{
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, i+jiffies);
}
@@ -133,7 +133,7 @@ static int net_random_reseed(void)
unsigned long seed[NR_CPUS];
get_random_bytes(seed, sizeof(seed));
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, seed[i]);
}
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 81d6995fcfdb..d2bc72d318f7 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -1726,6 +1726,14 @@ int wireless_rtnetlink_get(struct net_device * dev,
if(!IW_IS_GET(request->cmd))
return -EOPNOTSUPP;
+ /* If command is `get the encoding parameters', check if
+ * the user has the right to do it */
+ if (request->cmd == SIOCGIWENCODE ||
+ request->cmd == SIOCGIWENCODEEXT) {
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ }
+
/* Special cases */
if(request->cmd == SIOCGIWSTATS)
/* Get Wireless Stats */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 29047995c695..f2c011fd2ba1 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -498,7 +498,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop;
if (dccp_parse_options(sk, skb))
- goto drop;
+ goto drop_and_free;
dccp_openreq_init(req, &dp, skb);
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f3427be6..f2a27cc6ecb1 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
config IEEE80211_SOFTMAC
tristate "Software MAC add-on to the IEEE 802.11 networking stack"
depends on IEEE80211 && EXPERIMENTAL
+ select WIRELESS_EXT
---help---
This option enables the hardware independent software MAC addon
for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78dfa4..fb79ce7d6439 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -101,6 +101,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
mac->associated = 0;
mac->associnfo.associating = 0;
+ ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
spin_unlock_irqrestore(&mac->lock, flags);
}
@@ -143,6 +144,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
return 0;
+ /* assume that users know what they're doing ...
+ * (note we don't let them select a net we're incompatible with) */
+ if (mac->associnfo.bssfixed) {
+ return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
+ }
+
/* if 'ANY' network requested, take any that doesn't have privacy enabled */
if (mac->associnfo.req_essid.len == 0
&& !(net->capability & WLAN_CAPABILITY_PRIVACY))
@@ -175,7 +182,7 @@ ieee80211softmac_assoc_work(void *d)
ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
/* try to find the requested network in our list, if we found one already */
- if (mac->associnfo.bssvalid)
+ if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
/* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -240,19 +247,25 @@ ieee80211softmac_assoc_work(void *d)
if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
return;
- }
- else {
+ } else {
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 0;
mac->associated = 0;
spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
+ /* reset the retry counter for the next user request since we
+ * break out and don't reschedule ourselves after this point. */
+ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
return;
}
}
-
+
+ /* reset the retry counter for the next user request since we
+ * now found a net and will try to associate to it, but not
+ * schedule this function again. */
+ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
mac->associnfo.bssvalid = 1;
memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
/* copy the ESSID for displaying it */
@@ -373,6 +386,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.bssvalid = 0;
mac->associated = 0;
+ ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
schedule_work(&mac->associnfo.work);
spin_unlock_irqrestore(&mac->lock, flags);
@@ -391,6 +405,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
return 0;
}
- ieee80211softmac_assoc(mac, network);
+ schedule_work(&mac->associnfo.work);
+
return 0;
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbda1e4c..8cc8f3f0f8e7 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
"authenticating failed",
"authenticating timed out",
"associating failed because no suitable network was found",
+ "disassociated",
};
@@ -128,13 +129,42 @@ void
ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
{
struct ieee80211softmac_event *eventptr, *tmp;
- union iwreq_data wrqu;
- char *msg;
+ struct ieee80211softmac_network *network;
if (event >= 0) {
- msg = event_descriptions[event];
- wrqu.data.length = strlen(msg);
- wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
+ union iwreq_data wrqu;
+ int we_event;
+ char *msg = NULL;
+
+ switch(event) {
+ case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+ network = (struct ieee80211softmac_network *)event_ctx;
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ we_event = SIOCGIWAP;
+ break;
+ case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memset(&wrqu, '\0', sizeof (union iwreq_data));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ we_event = SIOCGIWAP;
+ break;
+ case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memset(&wrqu, '\0', sizeof (union iwreq_data));
+ we_event = SIOCGIWSCAN;
+ break;
+ default:
+ msg = event_descriptions[event];
+ wrqu.data.length = strlen(msg);
+ we_event = IWEVCUSTOM;
+ break;
+ }
+ wireless_send_event(mac->dev, we_event, &wrqu, msg);
}
if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51dbb412..cc6cd56c85b1 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
/* Fill in capability Info */
- (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ?
- cpu_to_le16(WLAN_CAPABILITY_ESS) :
- cpu_to_le16(WLAN_CAPABILITY_IBSS);
+ switch (mac->ieee->iw_mode) {
+ case IW_MODE_INFRA:
+ (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+ break;
+ case IW_MODE_ADHOC:
+ (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+ break;
+ case IW_MODE_AUTO:
+ (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+ break;
+ default:
+ /* bleh. we don't ever go to these modes */
+ printk(KERN_ERR PFX "invalid iw_mode!\n");
+ break;
+ }
/* Need to add this
(*pkt)->capability |= mac->ieee->short_slot ?
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 60f06a31f0d1..be83bdc1644a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
softmac->scaninfo = NULL;
+ softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+
/* TODO: initialise all the other callbacks in the ieee struct
* (once they're written)
*/
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b45d09..2b9e7edfa3ce 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
sm->scanning = 1;
spin_unlock_irqrestore(&sm->lock, flags);
+ netif_tx_disable(sm->ieee->dev);
ret = sm->start_scan(sm->dev);
if (ret) {
spin_lock_irqsave(&sm->lock, flags);
@@ -239,6 +240,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
if (net)
sm->set_channel(sm->dev, net->channel);
}
+ netif_wake_queue(sm->ieee->dev);
ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index b559aa9b5507..27edb2b5581a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -27,7 +27,8 @@
#include "ieee80211softmac_priv.h"
#include <net/iw_handler.h>
-
+/* for is_broadcast_ether_addr and is_zero_ether_addr */
+#include <linux/etherdevice.h>
int
ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
@@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
+/* if we're still scanning, return -EAGAIN so that userspace tools
+ * can get the complete scan results, otherwise return 0. */
int
ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
+ unsigned long flags;
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+
+ spin_lock_irqsave(&sm->lock, flags);
+ if (sm->scanning) {
+ spin_unlock_irqrestore(&sm->lock, flags);
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&sm->lock, flags);
return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
@@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
sm->associnfo.static_essid = 1;
}
}
- sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
/* set our requested ESSID length.
* If applicable, we have already copied the data in */
@@ -300,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
char *extra)
{
struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
- static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned long flags;
/* sanity check */
@@ -310,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
}
spin_lock_irqsave(&mac->lock, flags);
- if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
- !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
- schedule_work(&mac->associnfo.work);
- goto out;
+ if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
+ /* the bssid we have is not to be fixed any longer,
+ * and we should reassociate to the best AP. */
+ mac->associnfo.bssfixed = 0;
+ /* force reassociation */
+ mac->associnfo.bssvalid = 0;
+ if (mac->associated)
+ schedule_work(&mac->associnfo.work);
+ } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
+ /* the bssid we have is no longer fixed */
+ mac->associnfo.bssfixed = 0;
} else {
if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
if (mac->associnfo.associating || mac->associated) {
@@ -323,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
} else {
/* copy new value in data->ap_addr.sa_data to bssid */
memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
- }
+ }
+ /* tell the other code that this bssid should be used no matter what */
+ mac->associnfo.bssfixed = 1;
/* queue associate if new bssid or (old one again and not associated) */
schedule_work(&mac->associnfo.work);
}
-out:
+ out:
spin_unlock_irqrestore(&mac->lock, flags);
return 0;
}
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e16d8b42b953..e2e4771fa4c6 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -116,7 +116,7 @@ error:
return err;
}
-static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{
int ah_hlen;
struct iphdr *iph;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 041dadde31af..4749d504c629 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -928,7 +928,8 @@ static void parp_redo(struct sk_buff *skb)
* Receive an arp request from the device layer.
*/
-int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *arp;
@@ -1417,7 +1418,6 @@ static int __init arp_proc_init(void)
EXPORT_SYMBOL(arp_broken_ops);
EXPORT_SYMBOL(arp_find);
-EXPORT_SYMBOL(arp_rcv);
EXPORT_SYMBOL(arp_create);
EXPORT_SYMBOL(arp_xmit);
EXPORT_SYMBOL(arp_send);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 81c2f7885292..54419b27686f 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1556,7 +1556,6 @@ void __init devinet_init(void)
#endif
}
-EXPORT_SYMBOL(devinet_ioctl);
EXPORT_SYMBOL(in_dev_finish_destroy);
EXPORT_SYMBOL(inet_select_addr);
EXPORT_SYMBOL(inetdev_by_index);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index bf88c620a954..9d1881c07a32 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -133,7 +133,7 @@ error:
* expensive, so we only support truncated data, which is the recommended
* and common case.
*/
-static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph;
struct ip_esp_hdr *esph;
@@ -208,9 +208,6 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
struct xfrm_encap_tmpl *encap = x->encap;
struct udphdr *uh;
- if (encap->encap_type != decap->decap_type)
- goto out;
-
uh = (struct udphdr *)(iph + 1);
encap_len = (void*)esph - (void*)uh;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 4e3d3811dea2..cdde96390960 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -666,4 +666,3 @@ void __init ip_fib_init(void)
}
EXPORT_SYMBOL(inet_addr_type);
-EXPORT_SYMBOL(ip_rt_ioctl);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index ccd3efc6a173..95a639f2e3db 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
* Patrick McHardy <kaber@trash.net>
*/
-#define VERSION "0.406"
+#define VERSION "0.407"
#include <linux/config.h>
#include <asm/uaccess.h>
@@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head)
kfree(container_of(head, struct leaf, rcu));
}
-static inline void free_leaf(struct leaf *leaf)
-{
- call_rcu(&leaf->rcu, __leaf_free_rcu);
-}
-
static void __leaf_info_free_rcu(struct rcu_head *head)
{
kfree(container_of(head, struct leaf_info, rcu));
@@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head)
static inline void tnode_free(struct tnode *tn)
{
- call_rcu(&tn->rcu, __tnode_free_rcu);
+ if(IS_LEAF(tn)) {
+ struct leaf *l = (struct leaf *) tn;
+ call_rcu_bh(&l->rcu, __leaf_free_rcu);
+ }
+ else
+ call_rcu(&tn->rcu, __tnode_free_rcu);
}
static struct leaf *leaf_new(void)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 9831fd2c73a0..2a0455911ee0 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1107,7 +1107,7 @@ void __init icmp_init(struct net_proto_family *ops)
struct inet_sock *inet;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int err;
err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ef7366fc132f..ee9b5515b9ae 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -43,8 +43,6 @@ struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep,
return tb;
}
-EXPORT_SYMBOL(inet_bind_bucket_create);
-
/*
* Caller must hold hashbucket lock for this tb with local BH disabled
*/
@@ -64,8 +62,6 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
inet_csk(sk)->icsk_bind_hash = tb;
}
-EXPORT_SYMBOL(inet_bind_hash);
-
/*
* Get rid of any references to a local port held by the given sock.
*/
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 2a8adda15e11..da734c439179 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -304,13 +304,17 @@ out:
/* Creation primitives. */
-static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
+static struct ipq *ip_frag_intern(struct ipq *qp_in)
{
struct ipq *qp;
#ifdef CONFIG_SMP
struct hlist_node *n;
#endif
+ unsigned int hash;
+
write_lock(&ipfrag_lock);
+ hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
+ qp_in->protocol);
#ifdef CONFIG_SMP
/* With SMP race we have to recheck hash table, because
* such entry could be created on other cpu, while we
@@ -345,7 +349,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
}
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
+static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
{
struct ipq *qp;
@@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
spin_lock_init(&qp->lock);
atomic_set(&qp->refcnt, 1);
- return ip_frag_intern(hash, qp);
+ return ip_frag_intern(qp);
out_nomem:
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
@@ -387,11 +391,12 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
__u32 saddr = iph->saddr;
__u32 daddr = iph->daddr;
__u8 protocol = iph->protocol;
- unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
+ unsigned int hash;
struct ipq *qp;
struct hlist_node *n;
read_lock(&ipfrag_lock);
+ hash = ipqhashfn(id, saddr, daddr, protocol);
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
if(qp->id == id &&
qp->saddr == saddr &&
@@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
}
read_unlock(&ipfrag_lock);
- return ip_frag_create(hash, iph, user);
+ return ip_frag_create(iph, user);
}
/* Is the fragment too far ahead to be part of ipq? */
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9981dcd68f11..ab99bebdcdc8 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb)
read_unlock(&ipgre_lock);
return(0);
}
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
read_unlock(&ipgre_lock);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f75ff1d96551..cff9c3a72daf 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -86,8 +86,6 @@
int sysctl_ip_default_ttl = IPDEFTTL;
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
-
/* Generate a checksum for an outgoing IP datagram. */
__inline__ void ip_send_check(struct iphdr *iph)
{
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
* single device frame, and queue such a frame for sending.
*/
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
int raw = 0;
@@ -673,6 +671,8 @@ fail:
return err;
}
+EXPORT_SYMBOL(ip_fragment);
+
int
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
{
@@ -904,7 +904,7 @@ alloc_new_skb:
* because we have no idea what fragment will be
* the last.
*/
- if (datalen == length)
+ if (datalen == length + fraggap)
alloclen += rt->u.dst.trailer_len;
if (transhdrlen) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index c95020f7c81e..cd810f41af1a 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -81,8 +81,7 @@ out:
return err;
}
-static int ipcomp_input(struct xfrm_state *x,
- struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
u8 nexthdr;
int err = 0;
@@ -291,11 +290,8 @@ static void ipcomp_free_scratches(void)
if (!scratches)
return;
- for_each_cpu(i) {
- void *scratch = *per_cpu_ptr(scratches, i);
- if (scratch)
- vfree(scratch);
- }
+ for_each_possible_cpu(i)
+ vfree(*per_cpu_ptr(scratches, i));
free_percpu(scratches);
}
@@ -314,7 +310,7 @@ static void **ipcomp_alloc_scratches(void)
ipcomp_scratches = scratches;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
if (!scratch)
return NULL;
@@ -345,7 +341,7 @@ static void ipcomp_free_tfms(struct crypto_tfm **tfms)
if (!tfms)
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
crypto_free_tfm(tfm);
}
@@ -385,7 +381,7 @@ static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name)
if (!tfms)
goto error;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
if (!tfm)
goto error;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index eef07b0916a3..ea398ee43f28 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb)
struct iphdr *iph;
struct ip_tunnel *tunnel;
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
- goto out;
-
iph = skb->nh.iph;
read_lock(&ipip_lock);
@@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb)
}
read_unlock(&ipip_lock);
-out:
return -1;
}
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b5ad9ac2fbcc..6a9e34b794bc 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -133,7 +133,7 @@ struct ip_rt_info {
u_int8_t tos;
};
-static void queue_save(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
{
struct ip_rt_info *rt_info = nf_info_reroute(info);
@@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info)
}
}
-static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
{
const struct ip_rt_info *rt_info = nf_info_reroute(info);
@@ -161,20 +161,54 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
-static struct nf_queue_rerouter ip_reroute = {
- .rer_size = sizeof(struct ip_rt_info),
- .save = queue_save,
- .reroute = queue_reroute,
+unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol)
+{
+ struct iphdr *iph = skb->nh.iph;
+ unsigned int csum = 0;
+
+ switch (skb->ip_summed) {
+ case CHECKSUM_HW:
+ if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
+ break;
+ if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
+ !csum_tcpudp_magic(iph->saddr, iph->daddr,
+ skb->len - dataoff, protocol,
+ skb->csum)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ break;
+ }
+ /* fall through */
+ case CHECKSUM_NONE:
+ if (protocol == 0)
+ skb->csum = 0;
+ else
+ skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+ skb->len - dataoff,
+ protocol, 0);
+ csum = __skb_checksum_complete(skb);
+ }
+ return csum;
+}
+
+EXPORT_SYMBOL(nf_ip_checksum);
+
+static struct nf_afinfo nf_ip_afinfo = {
+ .family = AF_INET,
+ .checksum = nf_ip_checksum,
+ .saveroute = nf_ip_saveroute,
+ .reroute = nf_ip_reroute,
+ .route_key_size = sizeof(struct ip_rt_info),
};
static int ipv4_netfilter_init(void)
{
- return nf_register_queue_rerouter(PF_INET, &ip_reroute);
+ return nf_register_afinfo(&nf_ip_afinfo);
}
static void ipv4_netfilter_fini(void)
{
- nf_unregister_queue_rerouter(PF_INET);
+ nf_unregister_afinfo(&nf_ip_afinfo);
}
module_init(ipv4_netfilter_init);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 882b842c25d4..3d560dec63ab 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+ depends on IP_NF_NAT=n || IP_NF_NAT
help
This option enables support for a netlink-based userspace interface
@@ -221,16 +222,6 @@ config IP_NF_MATCH_IPRANGE
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_MULTIPORT
- tristate "Multiple port match support"
- depends on IP_NF_IPTABLES
- help
- Multiport matching allows you to match TCP or UDP packets based on
- a series of source or destination ports: normally a rule can only
- match a single range of ports.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_TOS
tristate "TOS match support"
depends on IP_NF_IPTABLES
@@ -272,12 +263,12 @@ config IP_NF_MATCH_DSCP
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_AH_ESP
- tristate "AH/ESP match support"
+config IP_NF_MATCH_AH
+ tristate "AH match support"
depends on IP_NF_IPTABLES
help
- These two match extensions (`ah' and `esp') allow you to match a
- range of SPIs inside AH or ESP headers of IPSec packets.
+ This match extension allows you to match a range of SPIs
+ inside AH header of IPSec packets.
To compile it as a module, choose M here. If unsure, say N.
@@ -354,7 +345,7 @@ config IP_NF_TARGET_LOG
To compile it as a module, choose M here. If unsure, say N.
config IP_NF_TARGET_ULOG
- tristate "ULOG target support (OBSOLETE)"
+ tristate "ULOG target support"
depends on IP_NF_IPTABLES
---help---
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index f2cd9a6c5b91..461cb1eb5de7 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -53,13 +53,12 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
# matches
obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
-obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
-obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
+obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index a44a5d73457d..c2d92f99a2b8 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -646,7 +646,7 @@ static int translate_table(const char *name,
}
/* And one copy for every other CPU */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (newinfo->entries[i] && newinfo->entries[i] != entry0)
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
@@ -696,7 +696,7 @@ static void get_counters(const struct xt_table_info *t,
counters,
&i);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == curcpu)
continue;
i = 0;
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index d0d379c7df9a..d7c472faa53b 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -181,33 +181,26 @@ static struct nf_hook_ops arpt_ops[] = {
static int __init arptable_filter_init(void)
{
- int ret, i;
+ int ret;
/* Register table */
ret = arpt_register_table(&packet_filter, &initial_table.repl);
if (ret < 0)
return ret;
- for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
- if ((ret = nf_register_hook(&arpt_ops[i])) < 0)
- goto cleanup_hooks;
+ ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
+ if (ret < 0)
+ goto cleanup_table;
return ret;
-cleanup_hooks:
- while (--i >= 0)
- nf_unregister_hook(&arpt_ops[i]);
-
+cleanup_table:
arpt_unregister_table(&packet_filter);
return ret;
}
static void __exit arptable_filter_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
- nf_unregister_hook(&arpt_ops[i]);
-
+ nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
arpt_unregister_table(&packet_filter);
}
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index ceaabc18202b..979a2eac6f00 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -133,7 +133,7 @@ static void ip_ct_event_cache_flush(void)
struct ip_conntrack_ecache *ecache;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
ecache = &per_cpu(ip_conntrack_ecache, cpu);
if (ecache->ct)
ip_conntrack_put(ecache->ct);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index daeb1395faa4..2c2fb700d835 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -9,37 +9,6 @@
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* For more information, please see http://nath323.sourceforge.net/
- *
- * Changes:
- * 2006-02-01 - initial version 0.1
- *
- * 2006-02-20 - version 0.2
- * 1. Changed source format to follow kernel conventions
- * 2. Deleted some unnecessary structures
- * 3. Minor fixes
- *
- * 2006-03-10 - version 0.3
- * 1. Added support for multiple TPKTs in one packet (suggested by
- * Patrick McHardy)
- * 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
- * 3. Added support for non-linear skb (based on Patrick McHardy's patch)
- * 4. Fixed missing H.245 module owner (Patrick McHardy)
- * 5. Avoid long RAS expectation chains (Patrick McHardy)
- * 6. Fixed incorrect __exit attribute (Patrick McHardy)
- * 7. Eliminated unnecessary return code
- * 8. Fixed incorrect use of NAT data from conntrack code (suggested by
- * Patrick McHardy)
- * 9. Fixed TTL calculation error in RCF
- * 10. Added TTL support in RRQ
- * 11. Better support for separate TPKT header and data
- *
- * 2006-03-15 - version 0.4
- * 1. Added support for T.120 channels
- * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
- * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
- * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
- * Patrick McHardy)
- * 5. Reset next TPKT data length in get_tpkt_data()
*/
#include <linux/config.h>
@@ -54,8 +23,6 @@
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/moduleparam.h>
-#include "ip_conntrack_helper_h323_asn1.h"
-
#if 0
#define DEBUGP printk
#else
@@ -63,6 +30,10 @@
#endif
/* Parameters */
+static unsigned int default_rrq_ttl = 300;
+module_param(default_rrq_ttl, uint, 0600);
+MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
+
static int gkrouted_only = 1;
module_param(gkrouted_only, int, 0600);
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
@@ -222,8 +193,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
}
/****************************************************************************/
-int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
- u_int32_t * ip, u_int16_t * port)
+static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port)
{
unsigned char *p;
@@ -1302,7 +1273,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
info->timeout = rrq->timeToLive;
} else
- info->timeout = 0;
+ info->timeout = default_rrq_ttl;
return 0;
}
@@ -1713,18 +1684,17 @@ static int __init init(void)
module_init(init);
module_exit(fini);
-EXPORT_SYMBOL(get_h245_addr);
-EXPORT_SYMBOL(get_h225_addr);
-EXPORT_SYMBOL(ip_conntrack_h245_expect);
-EXPORT_SYMBOL(ip_conntrack_q931_expect);
-EXPORT_SYMBOL(set_h245_addr_hook);
-EXPORT_SYMBOL(set_h225_addr_hook);
-EXPORT_SYMBOL(set_sig_addr_hook);
-EXPORT_SYMBOL(set_ras_addr_hook);
-EXPORT_SYMBOL(nat_rtp_rtcp_hook);
-EXPORT_SYMBOL(nat_t120_hook);
-EXPORT_SYMBOL(nat_h245_hook);
-EXPORT_SYMBOL(nat_q931_hook);
+EXPORT_SYMBOL_GPL(get_h225_addr);
+EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
+EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
+EXPORT_SYMBOL_GPL(set_h245_addr_hook);
+EXPORT_SYMBOL_GPL(set_h225_addr_hook);
+EXPORT_SYMBOL_GPL(set_sig_addr_hook);
+EXPORT_SYMBOL_GPL(set_ras_addr_hook);
+EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
+EXPORT_SYMBOL_GPL(nat_t120_hook);
+EXPORT_SYMBOL_GPL(nat_h245_hook);
+EXPORT_SYMBOL_GPL(nat_q931_hook);
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
MODULE_DESCRIPTION("H.323 connection tracking helper");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
index afa525129b51..48078002e450 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -15,7 +15,7 @@
#else
#include <stdio.h>
#endif
-#include "ip_conntrack_helper_h323_asn1.h"
+#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
/* Trace Flag */
#ifndef H323_TRACE
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 9b6e19bae90f..01bd7cab9367 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1658,7 +1658,7 @@ static void __exit ctnetlink_exit(void)
printk("ctnetlink: unregistering from nfnetlink.\n");
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
- ip_conntrack_unregister_notifier(&ctnl_notifier_exp);
+ ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
ip_conntrack_unregister_notifier(&ctnl_notifier);
#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 3021af0910f1..d8b14a9010a6 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
}
/* See ip_conntrack_proto_tcp.c */
- if (hooknum != NF_IP_PRE_ROUTING)
- goto checksum_skipped;
-
- switch (skb->ip_summed) {
- case CHECKSUM_HW:
- if (!(u16)csum_fold(skb->csum))
- break;
- /* fall through */
- case CHECKSUM_NONE:
- skb->csum = 0;
- if (__skb_checksum_complete(skb)) {
- if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
- "ip_ct_icmp: bad ICMP checksum ");
- return -NF_ACCEPT;
- }
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
+ if (LOG_INVALID(IPPROTO_ICMP))
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
+ "ip_ct_icmp: bad ICMP checksum ");
+ return -NF_ACCEPT;
}
-checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e0dc37063545..062b252b58ad 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
* and moreover root might send raw packets.
*/
/* FIXME: Source route IP option packets --RR */
- if (hooknum == NF_IP_PRE_ROUTING
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: bad TCP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 55b7d3210adf..70899868783b 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
* because the semantic of CHECKSUM_HW is different there
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
- if (hooknum == NF_IP_PRE_ROUTING
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: bad UDP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 52076026db36..929d61f7be91 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
-static struct nf_hook_ops ip_conntrack_defrag_ops = {
- .hook = ip_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_in_ops = {
- .hook = ip_conntrack_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
- .hook = ip_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_local_out_ops = {
- .hook = ip_conntrack_local,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ip_conntrack_helper_out_ops = {
- .hook = ip_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ip_conntrack_helper_in_ops = {
- .hook = ip_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ip_conntrack_out_ops = {
- .hook = ip_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ip_conntrack_local_in_ops = {
- .hook = ip_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ip_conntrack_ops[] = {
+ {
+ .hook = ip_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ip_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ip_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ip_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ip_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
+ {
+ .hook = ip_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
};
/* Sysctl support */
@@ -783,18 +776,46 @@ static ctl_table ip_ct_net_table[] = {
EXPORT_SYMBOL(ip_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
-static int init_or_cleanup(int init)
+/* FIXME: Allow NULL functions and sub in pointers to generic for
+ them. --RR */
+int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
+{
+ int ret = 0;
+
+ write_lock_bh(&ip_conntrack_lock);
+ if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+ ret = -EBUSY;
+ goto out;
+ }
+ ip_ct_protos[proto->proto] = proto;
+ out:
+ write_unlock_bh(&ip_conntrack_lock);
+ return ret;
+}
+
+void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
+{
+ write_lock_bh(&ip_conntrack_lock);
+ ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
+ write_unlock_bh(&ip_conntrack_lock);
+
+ /* Somebody could be still looking at the proto in bh. */
+ synchronize_net();
+
+ /* Remove all contrack entries for this protocol */
+ ip_ct_iterate_cleanup(kill_proto, &proto->proto);
+}
+
+static int __init ip_conntrack_standalone_init(void)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
#endif
int ret = 0;
- if (!init) goto cleanup;
-
ret = ip_conntrack_init();
if (ret < 0)
- goto cleanup_nothing;
+ return ret;
#ifdef CONFIG_PROC_FS
ret = -ENOMEM;
@@ -813,78 +834,25 @@ static int init_or_cleanup(int init)
proc_stat->owner = THIS_MODULE;
#endif
- ret = nf_register_hook(&ip_conntrack_defrag_ops);
+ ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
if (ret < 0) {
- printk("ip_conntrack: can't register pre-routing defrag hook.\n");
+ printk("ip_conntrack: can't register hooks.\n");
goto cleanup_proc_stat;
}
- ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local_out defrag hook.\n");
- goto cleanup_defragops;
- }
- ret = nf_register_hook(&ip_conntrack_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register pre-routing hook.\n");
- goto cleanup_defraglocalops;
- }
- ret = nf_register_hook(&ip_conntrack_local_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local out hook.\n");
- goto cleanup_inops;
- }
- ret = nf_register_hook(&ip_conntrack_helper_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local in helper hook.\n");
- goto cleanup_inandlocalops;
- }
- ret = nf_register_hook(&ip_conntrack_helper_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register postrouting helper hook.\n");
- goto cleanup_helperinops;
- }
- ret = nf_register_hook(&ip_conntrack_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register post-routing hook.\n");
- goto cleanup_helperoutops;
- }
- ret = nf_register_hook(&ip_conntrack_local_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local in hook.\n");
- goto cleanup_inoutandlocalops;
- }
#ifdef CONFIG_SYSCTL
ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
if (ip_ct_sysctl_header == NULL) {
printk("ip_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
- goto cleanup_localinops;
+ goto cleanup_hooks;
}
#endif
-
return ret;
- cleanup:
- synchronize_net();
#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(ip_ct_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+ nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
#endif
- nf_unregister_hook(&ip_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
- nf_unregister_hook(&ip_conntrack_out_ops);
- cleanup_helperoutops:
- nf_unregister_hook(&ip_conntrack_helper_out_ops);
- cleanup_helperinops:
- nf_unregister_hook(&ip_conntrack_helper_in_ops);
- cleanup_inandlocalops:
- nf_unregister_hook(&ip_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ip_conntrack_in_ops);
- cleanup_defraglocalops:
- nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
- cleanup_defragops:
- nf_unregister_hook(&ip_conntrack_defrag_ops);
cleanup_proc_stat:
#ifdef CONFIG_PROC_FS
remove_proc_entry("ip_conntrack", proc_net_stat);
@@ -895,48 +863,22 @@ static int init_or_cleanup(int init)
cleanup_init:
#endif /* CONFIG_PROC_FS */
ip_conntrack_cleanup();
- cleanup_nothing:
- return ret;
-}
-
-/* FIXME: Allow NULL functions and sub in pointers to generic for
- them. --RR */
-int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
-{
- int ret = 0;
-
- write_lock_bh(&ip_conntrack_lock);
- if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
- ret = -EBUSY;
- goto out;
- }
- ip_ct_protos[proto->proto] = proto;
- out:
- write_unlock_bh(&ip_conntrack_lock);
return ret;
}
-void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
-{
- write_lock_bh(&ip_conntrack_lock);
- ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
- write_unlock_bh(&ip_conntrack_lock);
-
- /* Somebody could be still looking at the proto in bh. */
- synchronize_net();
-
- /* Remove all contrack entries for this protocol */
- ip_ct_iterate_cleanup(kill_proto, &proto->proto);
-}
-
-static int __init ip_conntrack_standalone_init(void)
-{
- return init_or_cleanup(1);
-}
-
static void __exit ip_conntrack_standalone_fini(void)
{
- init_or_cleanup(0);
+ synchronize_net();
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(ip_ct_sysctl_header);
+#endif
+ nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("ip_conntrack", proc_net_stat);
+ proc_net_remove("ip_conntrack_expect");
+ proc_net_remove("ip_conntrack");
+#endif /* CONFIG_PROC_FS */
+ ip_conntrack_cleanup();
}
module_init(ip_conntrack_standalone_init);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index a0bc883928c0..d45663d137a7 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -7,24 +7,6 @@
*
* Based on the 'brute force' H.323 NAT module by
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * Changes:
- * 2006-02-01 - initial version 0.1
- *
- * 2006-02-20 - version 0.2
- * 1. Changed source format to follow kernel conventions
- * 2. Deleted some unnecessary structures
- * 3. Minor fixes
- *
- * 2006-03-10 - version 0.3
- * 1. Added support for multiple TPKTs in one packet (suggested by
- * Patrick McHardy)
- * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
- * 3. Eliminated unnecessary return code
- *
- * 2006-03-15 - version 0.4
- * 1. Added support for T.120 channels
- * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
*/
#include <linux/module.h>
@@ -41,65 +23,12 @@
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-#include "ip_conntrack_helper_h323_asn1.h"
-
#if 0
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif
-extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
- u_int32_t * ip, u_int16_t * port);
-extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
- u_int32_t * ip, u_int16_t * port);
-extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
- struct ip_conntrack_expect *this);
-extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
- struct ip_conntrack_expect *this);
-extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
- unsigned char **data, int dataoff,
- H245_TransportAddress * addr,
- u_int32_t ip, u_int16_t port);
-extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
- unsigned char **data, int dataoff,
- TransportAddress * addr,
- u_int32_t ip, u_int16_t port);
-extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
- struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data,
- TransportAddress * addr, int count);
-extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
- struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data,
- TransportAddress * addr, int count);
-extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
- struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, int dataoff,
- H245_TransportAddress * addr,
- u_int16_t port, u_int16_t rtp_port,
- struct ip_conntrack_expect * rtp_exp,
- struct ip_conntrack_expect * rtcp_exp);
-extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, int dataoff,
- H245_TransportAddress * addr, u_int16_t port,
- struct ip_conntrack_expect * exp);
-extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, int dataoff,
- TransportAddress * addr, u_int16_t port,
- struct ip_conntrack_expect * exp);
-extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, TransportAddress * addr,
- int idx, u_int16_t port,
- struct ip_conntrack_expect * exp);
-
-
/****************************************************************************/
static int set_addr(struct sk_buff **pskb,
unsigned char **data, int dataoff,
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index efba8c4e42e0..1aba926c1cb0 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = {
.target = ipt_dnat_target,
.targetsize = sizeof(struct ip_nat_multi_range_compat),
.table = "nat",
- .hooks = 1 << NF_IP_PRE_ROUTING,
+ .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
.checkentry = ipt_dnat_checkentry,
};
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 3505b0de2e04..8f760b28617e 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -299,69 +299,63 @@ ip_nat_adjust(unsigned int hooknum,
/* We must be after connection tracking and before packet filtering. */
-/* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_in_ops = {
- .hook = ip_nat_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_NAT_DST,
+static struct nf_hook_ops ip_nat_ops[] = {
+ /* Before packet filtering, change destination */
+ {
+ .hook = ip_nat_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_NAT_DST,
+ },
+ /* After packet filtering, change source */
+ {
+ .hook = ip_nat_out,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SRC,
+ },
+ /* After conntrack, adjust sequence number */
+ {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+ },
+ /* Before packet filtering, change destination */
+ {
+ .hook = ip_nat_local_fn,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_NAT_DST,
+ },
+ /* After packet filtering, change source */
+ {
+ .hook = ip_nat_fn,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SRC,
+ },
+ /* After conntrack, adjust sequence number */
+ {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+ },
};
-/* After packet filtering, change source */
-static struct nf_hook_ops ip_nat_out_ops = {
- .hook = ip_nat_out,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SRC,
-};
-
-/* After conntrack, adjust sequence number */
-static struct nf_hook_ops ip_nat_adjust_out_ops = {
- .hook = ip_nat_adjust,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
-};
-
-/* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_local_out_ops = {
- .hook = ip_nat_local_fn,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_NAT_DST,
-};
-
-/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
-static struct nf_hook_ops ip_nat_local_in_ops = {
- .hook = ip_nat_fn,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_NAT_SRC,
-};
-
-/* After conntrack, adjust sequence number */
-static struct nf_hook_ops ip_nat_adjust_in_ops = {
- .hook = ip_nat_adjust,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
-};
-
-
-static int init_or_cleanup(int init)
+static int __init ip_nat_standalone_init(void)
{
int ret = 0;
need_conntrack();
- if (!init) goto cleanup;
-
#ifdef CONFIG_XFRM
BUG_ON(ip_nat_decode_session != NULL);
ip_nat_decode_session = nat_decode_session;
@@ -371,50 +365,13 @@ static int init_or_cleanup(int init)
printk("ip_nat_init: can't setup rules.\n");
goto cleanup_decode_session;
}
- ret = nf_register_hook(&ip_nat_in_ops);
+ ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
if (ret < 0) {
- printk("ip_nat_init: can't register in hook.\n");
+ printk("ip_nat_init: can't register hooks.\n");
goto cleanup_rule_init;
}
- ret = nf_register_hook(&ip_nat_out_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register out hook.\n");
- goto cleanup_inops;
- }
- ret = nf_register_hook(&ip_nat_adjust_in_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register adjust in hook.\n");
- goto cleanup_outops;
- }
- ret = nf_register_hook(&ip_nat_adjust_out_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register adjust out hook.\n");
- goto cleanup_adjustin_ops;
- }
- ret = nf_register_hook(&ip_nat_local_out_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register local out hook.\n");
- goto cleanup_adjustout_ops;
- }
- ret = nf_register_hook(&ip_nat_local_in_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register local in hook.\n");
- goto cleanup_localoutops;
- }
return ret;
- cleanup:
- nf_unregister_hook(&ip_nat_local_in_ops);
- cleanup_localoutops:
- nf_unregister_hook(&ip_nat_local_out_ops);
- cleanup_adjustout_ops:
- nf_unregister_hook(&ip_nat_adjust_out_ops);
- cleanup_adjustin_ops:
- nf_unregister_hook(&ip_nat_adjust_in_ops);
- cleanup_outops:
- nf_unregister_hook(&ip_nat_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ip_nat_in_ops);
cleanup_rule_init:
ip_nat_rule_cleanup();
cleanup_decode_session:
@@ -425,14 +382,14 @@ static int init_or_cleanup(int init)
return ret;
}
-static int __init ip_nat_standalone_init(void)
-{
- return init_or_cleanup(1);
-}
-
static void __exit ip_nat_standalone_fini(void)
{
- init_or_cleanup(0);
+ nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
+ ip_nat_rule_cleanup();
+#ifdef CONFIG_XFRM
+ ip_nat_decode_session = NULL;
+ synchronize_net();
+#endif
}
module_init(ip_nat_standalone_init);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 896a244f8f91..b93f0494362f 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = {
.outfn = &ipq_enqueue_packet,
};
-static int
-init_or_cleanup(int init)
+static int __init ip_queue_init(void)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
- if (!init)
- goto cleanup;
-
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
THIS_MODULE);
@@ -697,11 +693,6 @@ init_or_cleanup(int init)
}
return status;
-cleanup:
- nf_unregister_queue_handlers(&nfqh);
- synchronize_net();
- ipq_flush(NF_DROP);
-
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -717,15 +708,21 @@ cleanup_netlink_notifier:
return status;
}
-static int __init ip_queue_init(void)
-{
-
- return init_or_cleanup(1);
-}
-
static void __exit ip_queue_fini(void)
{
- init_or_cleanup(0);
+ nf_unregister_queue_handlers(&nfqh);
+ synchronize_net();
+ ipq_flush(NF_DROP);
+
+ unregister_sysctl_table(ipq_sysctl_header);
+ unregister_netdevice_notifier(&ipq_dev_notifier);
+ proc_net_remove(IPQ_PROC_FS_NAME);
+
+ sock_release(ipqnl->sk_socket);
+ mutex_lock(&ipqnl_mutex);
+ mutex_unlock(&ipqnl_mutex);
+
+ netlink_unregister_notifier(&ipq_nl_notifier);
}
MODULE_DESCRIPTION("IPv4 packet queue handler");
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 460fd905fad0..d25ac8ba6eba 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/icmp.h>
#include <net/ip.h>
+#include <net/compat.h>
#include <asm/uaccess.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
@@ -734,7 +735,7 @@ translate_table(const char *name,
}
/* And one copy for every other CPU */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (newinfo->entries[i] && newinfo->entries[i] != entry0)
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
@@ -787,7 +788,7 @@ get_counters(const struct xt_table_info *t,
counters,
&i);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == curcpu)
continue;
i = 0;
@@ -799,17 +800,11 @@ get_counters(const struct xt_table_info *t,
}
}
-static int
-copy_entries_to_user(unsigned int total_size,
- struct ipt_table *table,
- void __user *userptr)
+static inline struct xt_counters * alloc_counters(struct ipt_table *table)
{
- unsigned int off, num, countersize;
- struct ipt_entry *e;
+ unsigned int countersize;
struct xt_counters *counters;
struct xt_table_info *private = table->private;
- int ret = 0;
- void *loc_cpu_entry;
/* We need atomic snapshot of counters: rest doesn't change
(other than comefrom, which userspace doesn't care
@@ -818,13 +813,32 @@ copy_entries_to_user(unsigned int total_size,
counters = vmalloc_node(countersize, numa_node_id());
if (counters == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
/* First, sum counters... */
write_lock_bh(&table->lock);
get_counters(private, counters);
write_unlock_bh(&table->lock);
+ return counters;
+}
+
+static int
+copy_entries_to_user(unsigned int total_size,
+ struct ipt_table *table,
+ void __user *userptr)
+{
+ unsigned int off, num;
+ struct ipt_entry *e;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
+ int ret = 0;
+ void *loc_cpu_entry;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+ return PTR_ERR(counters);
+
/* choose the copy that is on our node/cpu, ...
* This choice is lazy (because current thread is
* allowed to migrate to another cpu)
@@ -884,25 +898,278 @@ copy_entries_to_user(unsigned int total_size,
return ret;
}
+#ifdef CONFIG_COMPAT
+struct compat_delta {
+ struct compat_delta *next;
+ u_int16_t offset;
+ short delta;
+};
+
+static struct compat_delta *compat_offsets = NULL;
+
+static int compat_add_offset(u_int16_t offset, short delta)
+{
+ struct compat_delta *tmp;
+
+ tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ tmp->offset = offset;
+ tmp->delta = delta;
+ if (compat_offsets) {
+ tmp->next = compat_offsets->next;
+ compat_offsets->next = tmp;
+ } else {
+ compat_offsets = tmp;
+ tmp->next = NULL;
+ }
+ return 0;
+}
+
+static void compat_flush_offsets(void)
+{
+ struct compat_delta *tmp, *next;
+
+ if (compat_offsets) {
+ for(tmp = compat_offsets; tmp; tmp = next) {
+ next = tmp->next;
+ kfree(tmp);
+ }
+ compat_offsets = NULL;
+ }
+}
+
+static short compat_calc_jump(u_int16_t offset)
+{
+ struct compat_delta *tmp;
+ short delta;
+
+ for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
+ if (tmp->offset < offset)
+ delta += tmp->delta;
+ return delta;
+}
+
+struct compat_ipt_standard_target
+{
+ struct compat_xt_entry_target target;
+ compat_int_t verdict;
+};
+
+#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \
+ sizeof(struct compat_ipt_standard_target))
+
+struct compat_ipt_standard
+{
+ struct compat_ipt_entry entry;
+ struct compat_ipt_standard_target target;
+};
+
+static int compat_ipt_standard_fn(void *target,
+ void **dstptr, int *size, int convert)
+{
+ struct compat_ipt_standard_target compat_st, *pcompat_st;
+ struct ipt_standard_target st, *pst;
+ int ret;
+
+ ret = 0;
+ switch (convert) {
+ case COMPAT_TO_USER:
+ pst = (struct ipt_standard_target *)target;
+ memcpy(&compat_st.target, &pst->target,
+ sizeof(struct ipt_entry_target));
+ compat_st.verdict = pst->verdict;
+ if (compat_st.verdict > 0)
+ compat_st.verdict -=
+ compat_calc_jump(compat_st.verdict);
+ compat_st.target.u.user.target_size =
+ sizeof(struct compat_ipt_standard_target);
+ if (__copy_to_user(*dstptr, &compat_st,
+ sizeof(struct compat_ipt_standard_target)))
+ ret = -EFAULT;
+ *size -= IPT_ST_OFFSET;
+ *dstptr += sizeof(struct compat_ipt_standard_target);
+ break;
+ case COMPAT_FROM_USER:
+ pcompat_st =
+ (struct compat_ipt_standard_target *)target;
+ memcpy(&st.target, &pcompat_st->target,
+ sizeof(struct ipt_entry_target));
+ st.verdict = pcompat_st->verdict;
+ if (st.verdict > 0)
+ st.verdict += compat_calc_jump(st.verdict);
+ st.target.u.user.target_size =
+ sizeof(struct ipt_standard_target);
+ memcpy(*dstptr, &st,
+ sizeof(struct ipt_standard_target));
+ *size += IPT_ST_OFFSET;
+ *dstptr += sizeof(struct ipt_standard_target);
+ break;
+ case COMPAT_CALC_SIZE:
+ *size += IPT_ST_OFFSET;
+ break;
+ default:
+ ret = -ENOPROTOOPT;
+ break;
+ }
+ return ret;
+}
+
+static inline int
+compat_calc_match(struct ipt_entry_match *m, int * size)
+{
+ if (m->u.kernel.match->compat)
+ m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+ else
+ xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+ return 0;
+}
+
+static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
+ void *base, struct xt_table_info *newinfo)
+{
+ struct ipt_entry_target *t;
+ u_int16_t entry_offset;
+ int off, i, ret;
+
+ off = 0;
+ entry_offset = (void *)e - base;
+ IPT_MATCH_ITERATE(e, compat_calc_match, &off);
+ t = ipt_get_target(e);
+ if (t->u.kernel.target->compat)
+ t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+ else
+ xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+ newinfo->size -= off;
+ ret = compat_add_offset(entry_offset, off);
+ if (ret)
+ return ret;
+
+ for (i = 0; i< NF_IP_NUMHOOKS; i++) {
+ if (info->hook_entry[i] && (e < (struct ipt_entry *)
+ (base + info->hook_entry[i])))
+ newinfo->hook_entry[i] -= off;
+ if (info->underflow[i] && (e < (struct ipt_entry *)
+ (base + info->underflow[i])))
+ newinfo->underflow[i] -= off;
+ }
+ return 0;
+}
+
+static int compat_table_info(struct xt_table_info *info,
+ struct xt_table_info *newinfo)
+{
+ void *loc_cpu_entry;
+ int i;
+
+ if (!newinfo || !info)
+ return -EINVAL;
+
+ memset(newinfo, 0, sizeof(struct xt_table_info));
+ newinfo->size = info->size;
+ newinfo->number = info->number;
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ newinfo->hook_entry[i] = info->hook_entry[i];
+ newinfo->underflow[i] = info->underflow[i];
+ }
+ loc_cpu_entry = info->entries[raw_smp_processor_id()];
+ return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
+ compat_calc_entry, info, loc_cpu_entry, newinfo);
+}
+#endif
+
+static int get_info(void __user *user, int *len, int compat)
+{
+ char name[IPT_TABLE_MAXNAMELEN];
+ struct ipt_table *t;
+ int ret;
+
+ if (*len != sizeof(struct ipt_getinfo)) {
+ duprintf("length %u != %u\n", *len,
+ (unsigned int)sizeof(struct ipt_getinfo));
+ return -EINVAL;
+ }
+
+ if (copy_from_user(name, user, sizeof(name)) != 0)
+ return -EFAULT;
+
+ name[IPT_TABLE_MAXNAMELEN-1] = '\0';
+#ifdef CONFIG_COMPAT
+ if (compat)
+ xt_compat_lock(AF_INET);
+#endif
+ t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+ "iptable_%s", name);
+ if (t && !IS_ERR(t)) {
+ struct ipt_getinfo info;
+ struct xt_table_info *private = t->private;
+
+#ifdef CONFIG_COMPAT
+ if (compat) {
+ struct xt_table_info tmp;
+ ret = compat_table_info(private, &tmp);
+ compat_flush_offsets();
+ private = &tmp;
+ }
+#endif
+ info.valid_hooks = t->valid_hooks;
+ memcpy(info.hook_entry, private->hook_entry,
+ sizeof(info.hook_entry));
+ memcpy(info.underflow, private->underflow,
+ sizeof(info.underflow));
+ info.num_entries = private->number;
+ info.size = private->size;
+ strcpy(info.name, name);
+
+ if (copy_to_user(user, &info, *len) != 0)
+ ret = -EFAULT;
+ else
+ ret = 0;
+
+ xt_table_unlock(t);
+ module_put(t->me);
+ } else
+ ret = t ? PTR_ERR(t) : -ENOENT;
+#ifdef CONFIG_COMPAT
+ if (compat)
+ xt_compat_unlock(AF_INET);
+#endif
+ return ret;
+}
+
static int
-get_entries(const struct ipt_get_entries *entries,
- struct ipt_get_entries __user *uptr)
+get_entries(struct ipt_get_entries __user *uptr, int *len)
{
int ret;
+ struct ipt_get_entries get;
struct ipt_table *t;
- t = xt_find_table_lock(AF_INET, entries->name);
+ if (*len < sizeof(get)) {
+ duprintf("get_entries: %u < %d\n", *len,
+ (unsigned int)sizeof(get));
+ return -EINVAL;
+ }
+ if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+ return -EFAULT;
+ if (*len != sizeof(struct ipt_get_entries) + get.size) {
+ duprintf("get_entries: %u != %u\n", *len,
+ (unsigned int)(sizeof(struct ipt_get_entries) +
+ get.size));
+ return -EINVAL;
+ }
+
+ t = xt_find_table_lock(AF_INET, get.name);
if (t && !IS_ERR(t)) {
struct xt_table_info *private = t->private;
duprintf("t->private->number = %u\n",
private->number);
- if (entries->size == private->size)
+ if (get.size == private->size)
ret = copy_entries_to_user(private->size,
t, uptr->entrytable);
else {
duprintf("get_entries: I've got %u not %u!\n",
private->size,
- entries->size);
+ get.size);
ret = -EINVAL;
}
module_put(t->me);
@@ -914,79 +1181,47 @@ get_entries(const struct ipt_get_entries *entries,
}
static int
-do_replace(void __user *user, unsigned int len)
+__do_replace(const char *name, unsigned int valid_hooks,
+ struct xt_table_info *newinfo, unsigned int num_counters,
+ void __user *counters_ptr)
{
int ret;
- struct ipt_replace tmp;
struct ipt_table *t;
- struct xt_table_info *newinfo, *oldinfo;
+ struct xt_table_info *oldinfo;
struct xt_counters *counters;
- void *loc_cpu_entry, *loc_cpu_old_entry;
+ void *loc_cpu_old_entry;
- if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
- return -EFAULT;
-
- /* Hack: Causes ipchains to give correct error msg --RR */
- if (len != sizeof(tmp) + tmp.size)
- return -ENOPROTOOPT;
-
- /* overflow check */
- if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
- SMP_CACHE_BYTES)
- return -ENOMEM;
- if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
- return -ENOMEM;
-
- newinfo = xt_alloc_table_info(tmp.size);
- if (!newinfo)
- return -ENOMEM;
-
- /* choose the copy that is our node/cpu */
- loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
- if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
- tmp.size) != 0) {
- ret = -EFAULT;
- goto free_newinfo;
- }
-
- counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
+ ret = 0;
+ counters = vmalloc(num_counters * sizeof(struct xt_counters));
if (!counters) {
ret = -ENOMEM;
- goto free_newinfo;
+ goto out;
}
- ret = translate_table(tmp.name, tmp.valid_hooks,
- newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
- tmp.hook_entry, tmp.underflow);
- if (ret != 0)
- goto free_newinfo_counters;
-
- duprintf("ip_tables: Translated table\n");
-
- t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
- "iptable_%s", tmp.name);
+ t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+ "iptable_%s", name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free_newinfo_counters_untrans;
}
/* You lied! */
- if (tmp.valid_hooks != t->valid_hooks) {
+ if (valid_hooks != t->valid_hooks) {
duprintf("Valid hook crap: %08X vs %08X\n",
- tmp.valid_hooks, t->valid_hooks);
+ valid_hooks, t->valid_hooks);
ret = -EINVAL;
goto put_module;
}
- oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
+ oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
if (!oldinfo)
goto put_module;
/* Update module usage count based on number of rules */
duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
oldinfo->number, oldinfo->initial_entries, newinfo->number);
- if ((oldinfo->number > oldinfo->initial_entries) ||
- (newinfo->number <= oldinfo->initial_entries))
+ if ((oldinfo->number > oldinfo->initial_entries) ||
+ (newinfo->number <= oldinfo->initial_entries))
module_put(t->me);
if ((oldinfo->number > oldinfo->initial_entries) &&
(newinfo->number <= oldinfo->initial_entries))
@@ -998,8 +1233,8 @@ do_replace(void __user *user, unsigned int len)
loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
xt_free_table_info(oldinfo);
- if (copy_to_user(tmp.counters, counters,
- sizeof(struct xt_counters) * tmp.num_counters) != 0)
+ if (copy_to_user(counters_ptr, counters,
+ sizeof(struct xt_counters) * num_counters) != 0)
ret = -EFAULT;
vfree(counters);
xt_table_unlock(t);
@@ -1009,9 +1244,62 @@ do_replace(void __user *user, unsigned int len)
module_put(t->me);
xt_table_unlock(t);
free_newinfo_counters_untrans:
- IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
- free_newinfo_counters:
vfree(counters);
+ out:
+ return ret;
+}
+
+static int
+do_replace(void __user *user, unsigned int len)
+{
+ int ret;
+ struct ipt_replace tmp;
+ struct xt_table_info *newinfo;
+ void *loc_cpu_entry;
+
+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (len != sizeof(tmp) + tmp.size)
+ return -ENOPROTOOPT;
+
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
+ newinfo = xt_alloc_table_info(tmp.size);
+ if (!newinfo)
+ return -ENOMEM;
+
+ /* choose the copy that is our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
+ tmp.size) != 0) {
+ ret = -EFAULT;
+ goto free_newinfo;
+ }
+
+ ret = translate_table(tmp.name, tmp.valid_hooks,
+ newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
+ tmp.hook_entry, tmp.underflow);
+ if (ret != 0)
+ goto free_newinfo;
+
+ duprintf("ip_tables: Translated table\n");
+
+ ret = __do_replace(tmp.name, tmp.valid_hooks,
+ newinfo, tmp.num_counters,
+ tmp.counters);
+ if (ret)
+ goto free_newinfo_untrans;
+ return 0;
+
+ free_newinfo_untrans:
+ IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
free_newinfo:
xt_free_table_info(newinfo);
return ret;
@@ -1040,31 +1328,59 @@ add_counter_to_entry(struct ipt_entry *e,
}
static int
-do_add_counters(void __user *user, unsigned int len)
+do_add_counters(void __user *user, unsigned int len, int compat)
{
unsigned int i;
- struct xt_counters_info tmp, *paddc;
+ struct xt_counters_info tmp;
+ struct xt_counters *paddc;
+ unsigned int num_counters;
+ char *name;
+ int size;
+ void *ptmp;
struct ipt_table *t;
struct xt_table_info *private;
int ret = 0;
void *loc_cpu_entry;
+#ifdef CONFIG_COMPAT
+ struct compat_xt_counters_info compat_tmp;
- if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ if (compat) {
+ ptmp = &compat_tmp;
+ size = sizeof(struct compat_xt_counters_info);
+ } else
+#endif
+ {
+ ptmp = &tmp;
+ size = sizeof(struct xt_counters_info);
+ }
+
+ if (copy_from_user(ptmp, user, size) != 0)
return -EFAULT;
- if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
+#ifdef CONFIG_COMPAT
+ if (compat) {
+ num_counters = compat_tmp.num_counters;
+ name = compat_tmp.name;
+ } else
+#endif
+ {
+ num_counters = tmp.num_counters;
+ name = tmp.name;
+ }
+
+ if (len != size + num_counters * sizeof(struct xt_counters))
return -EINVAL;
- paddc = vmalloc_node(len, numa_node_id());
+ paddc = vmalloc_node(len - size, numa_node_id());
if (!paddc)
return -ENOMEM;
- if (copy_from_user(paddc, user, len) != 0) {
+ if (copy_from_user(paddc, user + size, len - size) != 0) {
ret = -EFAULT;
goto free;
}
- t = xt_find_table_lock(AF_INET, tmp.name);
+ t = xt_find_table_lock(AF_INET, name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
@@ -1072,7 +1388,7 @@ do_add_counters(void __user *user, unsigned int len)
write_lock_bh(&t->lock);
private = t->private;
- if (private->number != paddc->num_counters) {
+ if (private->number != num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1083,7 +1399,7 @@ do_add_counters(void __user *user, unsigned int len)
IPT_ENTRY_ITERATE(loc_cpu_entry,
private->size,
add_counter_to_entry,
- paddc->counters,
+ paddc,
&i);
unlock_up_free:
write_unlock_bh(&t->lock);
@@ -1095,8 +1411,438 @@ do_add_counters(void __user *user, unsigned int len)
return ret;
}
+#ifdef CONFIG_COMPAT
+struct compat_ipt_replace {
+ char name[IPT_TABLE_MAXNAMELEN];
+ u32 valid_hooks;
+ u32 num_entries;
+ u32 size;
+ u32 hook_entry[NF_IP_NUMHOOKS];
+ u32 underflow[NF_IP_NUMHOOKS];
+ u32 num_counters;
+ compat_uptr_t counters; /* struct ipt_counters * */
+ struct compat_ipt_entry entries[0];
+};
+
+static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
+ void __user **dstptr, compat_uint_t *size)
+{
+ if (m->u.kernel.match->compat)
+ return m->u.kernel.match->compat(m, dstptr, size,
+ COMPAT_TO_USER);
+ else
+ return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
+}
+
+static int compat_copy_entry_to_user(struct ipt_entry *e,
+ void __user **dstptr, compat_uint_t *size)
+{
+ struct ipt_entry_target __user *t;
+ struct compat_ipt_entry __user *ce;
+ u_int16_t target_offset, next_offset;
+ compat_uint_t origsize;
+ int ret;
+
+ ret = -EFAULT;
+ origsize = *size;
+ ce = (struct compat_ipt_entry __user *)*dstptr;
+ if (__copy_to_user(ce, e, sizeof(struct ipt_entry)))
+ goto out;
+
+ *dstptr += sizeof(struct compat_ipt_entry);
+ ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
+ target_offset = e->target_offset - (origsize - *size);
+ if (ret)
+ goto out;
+ t = ipt_get_target(e);
+ if (t->u.kernel.target->compat)
+ ret = t->u.kernel.target->compat(t, dstptr, size,
+ COMPAT_TO_USER);
+ else
+ ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
+ if (ret)
+ goto out;
+ ret = -EFAULT;
+ next_offset = e->next_offset - (origsize - *size);
+ if (__put_user(target_offset, &ce->target_offset))
+ goto out;
+ if (__put_user(next_offset, &ce->next_offset))
+ goto out;
+ return 0;
+out:
+ return ret;
+}
+
+static inline int
+compat_check_calc_match(struct ipt_entry_match *m,
+ const char *name,
+ const struct ipt_ip *ip,
+ unsigned int hookmask,
+ int *size, int *i)
+{
+ struct ipt_match *match;
+
+ match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
+ m->u.user.revision),
+ "ipt_%s", m->u.user.name);
+ if (IS_ERR(match) || !match) {
+ duprintf("compat_check_calc_match: `%s' not found\n",
+ m->u.user.name);
+ return match ? PTR_ERR(match) : -ENOENT;
+ }
+ m->u.kernel.match = match;
+
+ if (m->u.kernel.match->compat)
+ m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+ else
+ xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+
+ (*i)++;
+ return 0;
+}
+
+static inline int
+check_compat_entry_size_and_hooks(struct ipt_entry *e,
+ struct xt_table_info *newinfo,
+ unsigned int *size,
+ unsigned char *base,
+ unsigned char *limit,
+ unsigned int *hook_entries,
+ unsigned int *underflows,
+ unsigned int *i,
+ const char *name)
+{
+ struct ipt_entry_target *t;
+ struct ipt_target *target;
+ u_int16_t entry_offset;
+ int ret, off, h, j;
+
+ duprintf("check_compat_entry_size_and_hooks %p\n", e);
+ if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
+ || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
+ duprintf("Bad offset %p, limit = %p\n", e, limit);
+ return -EINVAL;
+ }
+
+ if (e->next_offset < sizeof(struct compat_ipt_entry) +
+ sizeof(struct compat_xt_entry_target)) {
+ duprintf("checking: element %p size %u\n",
+ e, e->next_offset);
+ return -EINVAL;
+ }
+
+ if (!ip_checkentry(&e->ip)) {
+ duprintf("ip_tables: ip check failed %p %s.\n", e, name);
+ return -EINVAL;
+ }
+
+ off = 0;
+ entry_offset = (void *)e - (void *)base;
+ j = 0;
+ ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+ e->comefrom, &off, &j);
+ if (ret != 0)
+ goto out;
+
+ t = ipt_get_target(e);
+ target = try_then_request_module(xt_find_target(AF_INET,
+ t->u.user.name,
+ t->u.user.revision),
+ "ipt_%s", t->u.user.name);
+ if (IS_ERR(target) || !target) {
+ duprintf("check_entry: `%s' not found\n", t->u.user.name);
+ ret = target ? PTR_ERR(target) : -ENOENT;
+ goto out;
+ }
+ t->u.kernel.target = target;
+
+ if (t->u.kernel.target->compat)
+ t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+ else
+ xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+ *size += off;
+ ret = compat_add_offset(entry_offset, off);
+ if (ret)
+ goto out;
+
+ /* Check hooks & underflows */
+ for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ if ((unsigned char *)e - base == hook_entries[h])
+ newinfo->hook_entry[h] = hook_entries[h];
+ if ((unsigned char *)e - base == underflows[h])
+ newinfo->underflow[h] = underflows[h];
+ }
+
+ /* Clear counters and comefrom */
+ e->counters = ((struct ipt_counters) { 0, 0 });
+ e->comefrom = 0;
+
+ (*i)++;
+ return 0;
+out:
+ IPT_MATCH_ITERATE(e, cleanup_match, &j);
+ return ret;
+}
+
+static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
+ void **dstptr, compat_uint_t *size, const char *name,
+ const struct ipt_ip *ip, unsigned int hookmask)
+{
+ struct ipt_entry_match *dm;
+ struct ipt_match *match;
+ int ret;
+
+ dm = (struct ipt_entry_match *)*dstptr;
+ match = m->u.kernel.match;
+ if (match->compat)
+ match->compat(m, dstptr, size, COMPAT_FROM_USER);
+ else
+ xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
+
+ ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
+ name, hookmask, ip->proto,
+ ip->invflags & IPT_INV_PROTO);
+ if (ret)
+ return ret;
+
+ if (m->u.kernel.match->checkentry
+ && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
+ dm->u.match_size - sizeof(*dm),
+ hookmask)) {
+ duprintf("ip_tables: check failed for `%s'.\n",
+ m->u.kernel.match->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
+ unsigned int *size, const char *name,
+ struct xt_table_info *newinfo, unsigned char *base)
+{
+ struct ipt_entry_target *t;
+ struct ipt_target *target;
+ struct ipt_entry *de;
+ unsigned int origsize;
+ int ret, h;
+
+ ret = 0;
+ origsize = *size;
+ de = (struct ipt_entry *)*dstptr;
+ memcpy(de, e, sizeof(struct ipt_entry));
+
+ *dstptr += sizeof(struct compat_ipt_entry);
+ ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
+ name, &de->ip, de->comefrom);
+ if (ret)
+ goto out;
+ de->target_offset = e->target_offset - (origsize - *size);
+ t = ipt_get_target(e);
+ target = t->u.kernel.target;
+ if (target->compat)
+ target->compat(t, dstptr, size, COMPAT_FROM_USER);
+ else
+ xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
+
+ de->next_offset = e->next_offset - (origsize - *size);
+ for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ if ((unsigned char *)de - base < newinfo->hook_entry[h])
+ newinfo->hook_entry[h] -= origsize - *size;
+ if ((unsigned char *)de - base < newinfo->underflow[h])
+ newinfo->underflow[h] -= origsize - *size;
+ }
+
+ t = ipt_get_target(de);
+ target = t->u.kernel.target;
+ ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+ name, e->comefrom, e->ip.proto,
+ e->ip.invflags & IPT_INV_PROTO);
+ if (ret)
+ goto out;
+
+ ret = -EINVAL;
+ if (t->u.kernel.target == &ipt_standard_target) {
+ if (!standard_check(t, *size))
+ goto out;
+ } else if (t->u.kernel.target->checkentry
+ && !t->u.kernel.target->checkentry(name, de, target,
+ t->data, t->u.target_size - sizeof(*t),
+ de->comefrom)) {
+ duprintf("ip_tables: compat: check failed for `%s'.\n",
+ t->u.kernel.target->name);
+ goto out;
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
static int
-do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+translate_compat_table(const char *name,
+ unsigned int valid_hooks,
+ struct xt_table_info **pinfo,
+ void **pentry0,
+ unsigned int total_size,
+ unsigned int number,
+ unsigned int *hook_entries,
+ unsigned int *underflows)
+{
+ unsigned int i;
+ struct xt_table_info *newinfo, *info;
+ void *pos, *entry0, *entry1;
+ unsigned int size;
+ int ret;
+
+ info = *pinfo;
+ entry0 = *pentry0;
+ size = total_size;
+ info->number = number;
+
+ /* Init all hooks to impossible value. */
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ info->hook_entry[i] = 0xFFFFFFFF;
+ info->underflow[i] = 0xFFFFFFFF;
+ }
+
+ duprintf("translate_compat_table: size %u\n", info->size);
+ i = 0;
+ xt_compat_lock(AF_INET);
+ /* Walk through entries, checking offsets. */
+ ret = IPT_ENTRY_ITERATE(entry0, total_size,
+ check_compat_entry_size_and_hooks,
+ info, &size, entry0,
+ entry0 + total_size,
+ hook_entries, underflows, &i, name);
+ if (ret != 0)
+ goto out_unlock;
+
+ ret = -EINVAL;
+ if (i != number) {
+ duprintf("translate_compat_table: %u not %u entries\n",
+ i, number);
+ goto out_unlock;
+ }
+
+ /* Check hooks all assigned */
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ /* Only hooks which are valid */
+ if (!(valid_hooks & (1 << i)))
+ continue;
+ if (info->hook_entry[i] == 0xFFFFFFFF) {
+ duprintf("Invalid hook entry %u %u\n",
+ i, hook_entries[i]);
+ goto out_unlock;
+ }
+ if (info->underflow[i] == 0xFFFFFFFF) {
+ duprintf("Invalid underflow %u %u\n",
+ i, underflows[i]);
+ goto out_unlock;
+ }
+ }
+
+ ret = -ENOMEM;
+ newinfo = xt_alloc_table_info(size);
+ if (!newinfo)
+ goto out_unlock;
+
+ newinfo->number = number;
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ newinfo->hook_entry[i] = info->hook_entry[i];
+ newinfo->underflow[i] = info->underflow[i];
+ }
+ entry1 = newinfo->entries[raw_smp_processor_id()];
+ pos = entry1;
+ size = total_size;
+ ret = IPT_ENTRY_ITERATE(entry0, total_size,
+ compat_copy_entry_from_user, &pos, &size,
+ name, newinfo, entry1);
+ compat_flush_offsets();
+ xt_compat_unlock(AF_INET);
+ if (ret)
+ goto free_newinfo;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry1))
+ goto free_newinfo;
+
+ /* And one copy for every other CPU */
+ for_each_cpu(i)
+ if (newinfo->entries[i] && newinfo->entries[i] != entry1)
+ memcpy(newinfo->entries[i], entry1, newinfo->size);
+
+ *pinfo = newinfo;
+ *pentry0 = entry1;
+ xt_free_table_info(info);
+ return 0;
+
+free_newinfo:
+ xt_free_table_info(newinfo);
+out:
+ return ret;
+out_unlock:
+ xt_compat_unlock(AF_INET);
+ goto out;
+}
+
+static int
+compat_do_replace(void __user *user, unsigned int len)
+{
+ int ret;
+ struct compat_ipt_replace tmp;
+ struct xt_table_info *newinfo;
+ void *loc_cpu_entry;
+
+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (len != sizeof(tmp) + tmp.size)
+ return -ENOPROTOOPT;
+
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
+ newinfo = xt_alloc_table_info(tmp.size);
+ if (!newinfo)
+ return -ENOMEM;
+
+ /* choose the copy that is our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
+ tmp.size) != 0) {
+ ret = -EFAULT;
+ goto free_newinfo;
+ }
+
+ ret = translate_compat_table(tmp.name, tmp.valid_hooks,
+ &newinfo, &loc_cpu_entry, tmp.size,
+ tmp.num_entries, tmp.hook_entry, tmp.underflow);
+ if (ret != 0)
+ goto free_newinfo;
+
+ duprintf("compat_do_replace: Translated table\n");
+
+ ret = __do_replace(tmp.name, tmp.valid_hooks,
+ newinfo, tmp.num_counters,
+ compat_ptr(tmp.counters));
+ if (ret)
+ goto free_newinfo_untrans;
+ return 0;
+
+ free_newinfo_untrans:
+ IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
+ free_newinfo:
+ xt_free_table_info(newinfo);
+ return ret;
+}
+
+static int
+compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
+ unsigned int len)
{
int ret;
@@ -1105,11 +1851,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
switch (cmd) {
case IPT_SO_SET_REPLACE:
- ret = do_replace(user, len);
+ ret = compat_do_replace(user, len);
break;
case IPT_SO_SET_ADD_COUNTERS:
- ret = do_add_counters(user, len);
+ ret = do_add_counters(user, len, 1);
break;
default:
@@ -1120,75 +1866,196 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
return ret;
}
+struct compat_ipt_get_entries
+{
+ char name[IPT_TABLE_MAXNAMELEN];
+ compat_uint_t size;
+ struct compat_ipt_entry entrytable[0];
+};
+
+static int compat_copy_entries_to_user(unsigned int total_size,
+ struct ipt_table *table, void __user *userptr)
+{
+ unsigned int off, num;
+ struct compat_ipt_entry e;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
+ void __user *pos;
+ unsigned int size;
+ int ret = 0;
+ void *loc_cpu_entry;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+ return PTR_ERR(counters);
+
+ /* choose the copy that is on our node/cpu, ...
+ * This choice is lazy (because current thread is
+ * allowed to migrate to another cpu)
+ */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ pos = userptr;
+ size = total_size;
+ ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
+ compat_copy_entry_to_user, &pos, &size);
+ if (ret)
+ goto free_counters;
+
+ /* ... then go back and fix counters and names */
+ for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
+ unsigned int i;
+ struct ipt_entry_match m;
+ struct ipt_entry_target t;
+
+ ret = -EFAULT;
+ if (copy_from_user(&e, userptr + off,
+ sizeof(struct compat_ipt_entry)))
+ goto free_counters;
+ if (copy_to_user(userptr + off +
+ offsetof(struct compat_ipt_entry, counters),
+ &counters[num], sizeof(counters[num])))
+ goto free_counters;
+
+ for (i = sizeof(struct compat_ipt_entry);
+ i < e.target_offset; i += m.u.match_size) {
+ if (copy_from_user(&m, userptr + off + i,
+ sizeof(struct ipt_entry_match)))
+ goto free_counters;
+ if (copy_to_user(userptr + off + i +
+ offsetof(struct ipt_entry_match, u.user.name),
+ m.u.kernel.match->name,
+ strlen(m.u.kernel.match->name) + 1))
+ goto free_counters;
+ }
+
+ if (copy_from_user(&t, userptr + off + e.target_offset,
+ sizeof(struct ipt_entry_target)))
+ goto free_counters;
+ if (copy_to_user(userptr + off + e.target_offset +
+ offsetof(struct ipt_entry_target, u.user.name),
+ t.u.kernel.target->name,
+ strlen(t.u.kernel.target->name) + 1))
+ goto free_counters;
+ }
+ ret = 0;
+free_counters:
+ vfree(counters);
+ return ret;
+}
+
static int
-do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
{
int ret;
+ struct compat_ipt_get_entries get;
+ struct ipt_table *t;
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- switch (cmd) {
- case IPT_SO_GET_INFO: {
- char name[IPT_TABLE_MAXNAMELEN];
- struct ipt_table *t;
+ if (*len < sizeof(get)) {
+ duprintf("compat_get_entries: %u < %u\n",
+ *len, (unsigned int)sizeof(get));
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+ return -EFAULT;
+
+ if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
+ duprintf("compat_get_entries: %u != %u\n", *len,
+ (unsigned int)(sizeof(struct compat_ipt_get_entries) +
+ get.size));
+ return -EINVAL;
+ }
- if (*len != sizeof(struct ipt_getinfo)) {
- duprintf("length %u != %u\n", *len,
- sizeof(struct ipt_getinfo));
+ xt_compat_lock(AF_INET);
+ t = xt_find_table_lock(AF_INET, get.name);
+ if (t && !IS_ERR(t)) {
+ struct xt_table_info *private = t->private;
+ struct xt_table_info info;
+ duprintf("t->private->number = %u\n",
+ private->number);
+ ret = compat_table_info(private, &info);
+ if (!ret && get.size == info.size) {
+ ret = compat_copy_entries_to_user(private->size,
+ t, uptr->entrytable);
+ } else if (!ret) {
+ duprintf("compat_get_entries: I've got %u not %u!\n",
+ private->size,
+ get.size);
ret = -EINVAL;
- break;
}
+ compat_flush_offsets();
+ module_put(t->me);
+ xt_table_unlock(t);
+ } else
+ ret = t ? PTR_ERR(t) : -ENOENT;
- if (copy_from_user(name, user, sizeof(name)) != 0) {
- ret = -EFAULT;
- break;
- }
- name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-
- t = try_then_request_module(xt_find_table_lock(AF_INET, name),
- "iptable_%s", name);
- if (t && !IS_ERR(t)) {
- struct ipt_getinfo info;
- struct xt_table_info *private = t->private;
-
- info.valid_hooks = t->valid_hooks;
- memcpy(info.hook_entry, private->hook_entry,
- sizeof(info.hook_entry));
- memcpy(info.underflow, private->underflow,
- sizeof(info.underflow));
- info.num_entries = private->number;
- info.size = private->size;
- memcpy(info.name, name, sizeof(info.name));
-
- if (copy_to_user(user, &info, *len) != 0)
- ret = -EFAULT;
- else
- ret = 0;
- xt_table_unlock(t);
- module_put(t->me);
- } else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ xt_compat_unlock(AF_INET);
+ return ret;
+}
+
+static int
+compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+{
+ int ret;
+
+ switch (cmd) {
+ case IPT_SO_GET_INFO:
+ ret = get_info(user, len, 1);
+ break;
+ case IPT_SO_GET_ENTRIES:
+ ret = compat_get_entries(user, len);
+ break;
+ default:
+ duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
+ ret = -EINVAL;
}
- break;
+ return ret;
+}
+#endif
- case IPT_SO_GET_ENTRIES: {
- struct ipt_get_entries get;
+static int
+do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+{
+ int ret;
- if (*len < sizeof(get)) {
- duprintf("get_entries: %u < %u\n", *len, sizeof(get));
- ret = -EINVAL;
- } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
- ret = -EFAULT;
- } else if (*len != sizeof(struct ipt_get_entries) + get.size) {
- duprintf("get_entries: %u != %u\n", *len,
- sizeof(struct ipt_get_entries) + get.size);
- ret = -EINVAL;
- } else
- ret = get_entries(&get, user);
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ switch (cmd) {
+ case IPT_SO_SET_REPLACE:
+ ret = do_replace(user, len);
break;
+
+ case IPT_SO_SET_ADD_COUNTERS:
+ ret = do_add_counters(user, len, 0);
+ break;
+
+ default:
+ duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
+ ret = -EINVAL;
}
+ return ret;
+}
+
+static int
+do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+{
+ int ret;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ switch (cmd) {
+ case IPT_SO_GET_INFO:
+ ret = get_info(user, len, 0);
+ break;
+
+ case IPT_SO_GET_ENTRIES:
+ ret = get_entries(user, len);
+ break;
+
case IPT_SO_GET_REVISION_MATCH:
case IPT_SO_GET_REVISION_TARGET: {
struct ipt_get_revision rev;
@@ -1336,6 +2203,9 @@ static struct ipt_target ipt_standard_target = {
.name = IPT_STANDARD_TARGET,
.targetsize = sizeof(int),
.family = AF_INET,
+#ifdef CONFIG_COMPAT
+ .compat = &compat_ipt_standard_fn,
+#endif
};
static struct ipt_target ipt_error_target = {
@@ -1350,9 +2220,15 @@ static struct nf_sockopt_ops ipt_sockopts = {
.set_optmin = IPT_BASE_CTL,
.set_optmax = IPT_SO_SET_MAX+1,
.set = do_ipt_set_ctl,
+#ifdef CONFIG_COMPAT
+ .compat_set = compat_do_ipt_set_ctl,
+#endif
.get_optmin = IPT_BASE_CTL,
.get_optmax = IPT_SO_GET_MAX+1,
.get = do_ipt_get_ctl,
+#ifdef CONFIG_COMPAT
+ .compat_get = compat_do_ipt_get_ctl,
+#endif
};
static struct ipt_match icmp_matchstruct = {
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index e4768a31718b..aad9d28c8d71 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = {
#endif /* CONFIG_PROC_FS */
-static int init_or_cleanup(int fini)
+static int __init ipt_clusterip_init(void)
{
int ret;
- if (fini)
- goto cleanup;
-
- if (ipt_register_target(&clusterip_tgt)) {
- ret = -EINVAL;
- goto cleanup_none;
- }
+ ret = ipt_register_target(&clusterip_tgt);
+ if (ret < 0)
+ return ret;
- if (nf_register_hook(&cip_arp_ops) < 0) {
- ret = -EINVAL;
+ ret = nf_register_hook(&cip_arp_ops);
+ if (ret < 0)
goto cleanup_target;
- }
#ifdef CONFIG_PROC_FS
clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
@@ -753,31 +748,24 @@ static int init_or_cleanup(int fini)
printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
CLUSTERIP_VERSION);
-
return 0;
-cleanup:
- printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
- CLUSTERIP_VERSION);
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
-#endif
cleanup_hook:
nf_unregister_hook(&cip_arp_ops);
cleanup_target:
ipt_unregister_target(&clusterip_tgt);
-cleanup_none:
- return -EINVAL;
-}
-
-static int __init ipt_clusterip_init(void)
-{
- return init_or_cleanup(0);
+ return ret;
}
static void __exit ipt_clusterip_fini(void)
{
- init_or_cleanup(1);
+ printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
+ CLUSTERIP_VERSION);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
+#endif
+ nf_unregister_hook(&cip_arp_ops);
+ ipt_unregister_target(&clusterip_tgt);
}
module_init(ipt_clusterip_init);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 4269a5440d43..0bba3c2bb786 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
struct rtable *rt;
u_int16_t tmp_port;
u_int32_t tmp_addr;
- unsigned int tcplen;
int needs_ack;
int hh_len;
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
return;
/* Check checksum */
- tcplen = oldskb->len - iph->ihl * 4;
- if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
- (hook == NF_IP_LOCAL_IN &&
- oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
- csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
- oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
- skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
+ if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
return;
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
deleted file mode 100644
index ac95d8390bcc..000000000000
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
- the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.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/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-
-#include <linux/netfilter_ipv4/ipt_multiport.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("iptables multiple port match module");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ipt_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 != IPT_MULTIPORT_DESTINATION
- && portlist[i] == src)
- return 1;
-
- if (flags != IPT_MULTIPORT_SOURCE
- && portlist[i] == dst)
- return 1;
- }
-
- return 0;
-}
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match_v1(const struct ipt_multiport_v1 *minfo,
- u_int16_t src, u_int16_t dst)
-{
- unsigned int i;
- u_int16_t s, e;
-
- for (i=0; i < minfo->count; i++) {
- s = minfo->ports[i];
-
- if (minfo->pflags[i]) {
- /* range port matching */
- e = minfo->ports[++i];
- duprintf("src or dst matches with %d-%d?\n", s, e);
-
- if (minfo->flags == IPT_MULTIPORT_SOURCE
- && src >= s && src <= e)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_DESTINATION
- && dst >= s && dst <= e)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_EITHER
- && ((dst >= s && dst <= e)
- || (src >= s && src <= e)))
- return 1 ^ minfo->invert;
- } else {
- /* exact port matching */
- duprintf("src or dst matches with %d?\n", s);
-
- if (minfo->flags == IPT_MULTIPORT_SOURCE
- && src == s)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_DESTINATION
- && dst == s)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_EITHER
- && (src == s || dst == s))
- return 1 ^ minfo->invert;
- }
- }
-
- return minfo->invert;
-}
-
-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)
-{
- u16 _ports[2], *pptr;
- const struct ipt_multiport *multiinfo = matchinfo;
-
- if (offset)
- return 0;
-
- pptr = skb_header_pointer(skb, protoff,
- sizeof(_ports), _ports);
- if (pptr == NULL) {
- /* We've been asked to examine this packet, and we
- * can't. Hence, no choice but to drop.
- */
- duprintf("ipt_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return ports_match(multiinfo->ports,
- multiinfo->flags, multiinfo->count,
- ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static int
-match_v1(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)
-{
- u16 _ports[2], *pptr;
- const struct ipt_multiport_v1 *multiinfo = matchinfo;
-
- if (offset)
- return 0;
-
- pptr = skb_header_pointer(skb, protoff,
- sizeof(_ports), _ports);
- if (pptr == NULL) {
- /* We've been asked to examine this packet, and we
- * can't. Hence, no choice but to drop.
- */
- duprintf("ipt_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static struct ipt_match multiport_match = {
- .name = "multiport",
- .revision = 0,
- .match = match,
- .matchsize = sizeof(struct ipt_multiport),
- .me = THIS_MODULE,
-};
-
-static struct ipt_match multiport_match_v1 = {
- .name = "multiport",
- .revision = 1,
- .match = match_v1,
- .matchsize = sizeof(struct ipt_multiport_v1),
- .me = THIS_MODULE,
-};
-
-static int __init ipt_multiport_init(void)
-{
- int err;
-
- err = ipt_register_match(&multiport_match);
- if (!err) {
- err = ipt_register_match(&multiport_match_v1);
- if (err)
- ipt_unregister_match(&multiport_match);
- }
-
- return err;
-}
-
-static void __exit ipt_multiport_fini(void)
-{
- ipt_unregister_match(&multiport_match);
- ipt_unregister_match(&multiport_match_v1);
-}
-
-module_init(ipt_multiport_init);
-module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 3d80aefe9cfa..7f417484bfbf 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -157,37 +157,20 @@ static int __init iptable_filter_init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ipt_ops[0]);
+ ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ipt_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ipt_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
return ret;
- cleanup_hook1:
- nf_unregister_hook(&ipt_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_filter);
-
return ret;
}
static void __exit iptable_filter_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ipt_ops[i]);
-
+ nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_filter);
}
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 412fc96cc896..397b95cc026b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -211,49 +211,20 @@ static int __init iptable_mangle_init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ipt_ops[0]);
+ ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ipt_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ipt_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
- ret = nf_register_hook(&ipt_ops[3]);
- if (ret < 0)
- goto cleanup_hook2;
-
- ret = nf_register_hook(&ipt_ops[4]);
- if (ret < 0)
- goto cleanup_hook3;
-
return ret;
- cleanup_hook3:
- nf_unregister_hook(&ipt_ops[3]);
- cleanup_hook2:
- nf_unregister_hook(&ipt_ops[2]);
- cleanup_hook1:
- nf_unregister_hook(&ipt_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_mangler);
-
return ret;
}
static void __exit iptable_mangle_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ipt_ops[i]);
-
+ nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_mangler);
}
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 03cc79a6160a..7912cce1e1b8 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -101,18 +101,18 @@ ipt_hook(unsigned int hook,
/* 'raw' is the very first table. */
static struct nf_hook_ops ipt_ops[] = {
{
- .hook = ipt_hook,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_RAW,
- .owner = THIS_MODULE,
+ .hook = ipt_hook,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_RAW,
+ .owner = THIS_MODULE,
},
{
- .hook = ipt_hook,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_RAW,
- .owner = THIS_MODULE,
+ .hook = ipt_hook,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_RAW,
+ .owner = THIS_MODULE,
},
};
@@ -126,31 +126,20 @@ static int __init iptable_raw_init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ipt_ops[0]);
+ ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ipt_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
return ret;
- cleanup_hook0:
- nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_raw);
-
return ret;
}
static void __exit iptable_raw_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ipt_ops[i]);
-
+ nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_raw);
}
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 4afbc699d3ba..5bc9f64d7b5b 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
-static struct nf_hook_ops ipv4_conntrack_defrag_ops = {
- .hook = ipv4_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv4_conntrack_in_ops = {
- .hook = ipv4_conntrack_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = {
- .hook = ipv4_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv4_conntrack_local_out_ops = {
- .hook = ipv4_conntrack_local,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ipv4_conntrack_helper_out_ops = {
- .hook = ipv4_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
- .hook = ipv4_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv4_conntrack_out_ops = {
- .hook = ipv4_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
- .hook = ipv4_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ipv4_conntrack_ops[] = {
+ {
+ .hook = ipv4_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv4_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv4_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv4_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv4_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ipv4_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ipv4_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
+ {
+ .hook = ipv4_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
};
#ifdef CONFIG_SYSCTL
@@ -440,16 +432,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
+MODULE_LICENSE("GPL");
+
+static int __init nf_conntrack_l3proto_ipv4_init(void)
{
int ret = 0;
- if (!init) goto cleanup;
+ need_conntrack();
ret = nf_register_sockopt(&so_getorigdst);
if (ret < 0) {
printk(KERN_ERR "Unable to register netfilter socket option\n");
- goto cleanup_nothing;
+ return ret;
}
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
@@ -476,84 +472,26 @@ static int init_or_cleanup(int init)
goto cleanup_icmp;
}
- ret = nf_register_hook(&ipv4_conntrack_defrag_ops);
+ ret = nf_register_hooks(ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n");
+ printk("nf_conntrack_ipv4: can't register hooks.\n");
goto cleanup_ipv4;
}
- ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
- goto cleanup_defragops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
- goto cleanup_defraglocalops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local out hook.\n");
- goto cleanup_inops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local helper hook.\n");
- goto cleanup_inandlocalops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
- goto cleanup_helperinops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
- goto cleanup_helperoutops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local in hook.\n");
- goto cleanup_inoutandlocalops;
- }
-
#ifdef CONFIG_SYSCTL
nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_ipv4_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
- goto cleanup_localinops;
+ goto cleanup_hooks;
}
#endif
return ret;
- cleanup:
- synchronize_net();
#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+ nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif
- nf_unregister_hook(&ipv4_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
- nf_unregister_hook(&ipv4_conntrack_out_ops);
- cleanup_helperoutops:
- nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
- cleanup_helperinops:
- nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
- cleanup_inandlocalops:
- nf_unregister_hook(&ipv4_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ipv4_conntrack_in_ops);
- cleanup_defraglocalops:
- nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
- cleanup_defragops:
- nf_unregister_hook(&ipv4_conntrack_defrag_ops);
cleanup_ipv4:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
cleanup_icmp:
@@ -564,22 +502,21 @@ static int init_or_cleanup(int init)
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst);
- cleanup_nothing:
return ret;
}
-MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
-MODULE_LICENSE("GPL");
-
-static int __init nf_conntrack_l3proto_ipv4_init(void)
-{
- need_conntrack();
- return init_or_cleanup(1);
-}
-
static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
- init_or_cleanup(0);
+ synchronize_net();
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
+#endif
+ nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
+ nf_unregister_sockopt(&so_getorigdst);
}
module_init(nf_conntrack_l3proto_ipv4_init);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 52dc175be39a..4b0d361cc6e6 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
}
/* See ip_conntrack_proto_tcp.c */
- if (hooknum != NF_IP_PRE_ROUTING)
- goto checksum_skipped;
-
- switch (skb->ip_summed) {
- case CHECKSUM_HW:
- if (!(u16)csum_fold(skb->csum))
- break;
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, dataoff, 0)) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"nf_ct_icmp: bad HW ICMP checksum ");
return -NF_ACCEPT;
- case CHECKSUM_NONE:
- if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
- if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
- NULL,
- "nf_ct_icmp: bad ICMP checksum ");
- return -NF_ACCEPT;
- }
- default:
- break;
}
-checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 1b167c4bb3be..d61e2a9d394d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto)
int res = 0;
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
res += proto->stats[cpu].inuse;
return res;
@@ -91,7 +91,7 @@ fold_field(void *mib[], int offt)
unsigned long res = 0;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94fcbc5e5a1b..cc9423de7311 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2741,7 +2741,10 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
/* Reserve room for dummy headers, this skb can pass
through good chunk of routing engine.
*/
- skb->mac.raw = skb->data;
+ skb->mac.raw = skb->nh.raw = skb->data;
+
+ /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
+ skb->nh.iph->protocol = IPPROTO_ICMP;
skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
if (rta[RTA_SRC - 1])
@@ -3083,7 +3086,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
memcpy(dst, src, length);
/* Add the other cpus in, one int at a time */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
unsigned int j;
src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 195d83584558..9f0cca4c4fae 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4559,7 +4559,6 @@ discard:
EXPORT_SYMBOL(sysctl_tcp_ecn);
EXPORT_SYMBOL(sysctl_tcp_reordering);
-EXPORT_SYMBOL(sysctl_tcp_abc);
EXPORT_SYMBOL(tcp_parse_options);
EXPORT_SYMBOL(tcp_rcv_established);
EXPORT_SYMBOL(tcp_rcv_state_process);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9e85c0416109..672950e54c49 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1859,5 +1859,4 @@ EXPORT_SYMBOL(tcp_proc_unregister);
#endif
EXPORT_SYMBOL(sysctl_local_port_range);
EXPORT_SYMBOL(sysctl_tcp_low_latency);
-EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9d79546d384e..a28ae593b976 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,9 +59,6 @@ int sysctl_tcp_tso_win_divisor = 3;
int sysctl_tcp_mtu_probing = 0;
int sysctl_tcp_base_mss = 512;
-EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
-EXPORT_SYMBOL(sysctl_tcp_base_mss);
-
static void update_send_head(struct sock *sk, struct tcp_sock *tp,
struct sk_buff *skb)
{
@@ -536,6 +533,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *buff;
int nsize, old_factor;
+ int nlen;
u16 flags;
BUG_ON(len > skb->len);
@@ -554,7 +552,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
if (buff == NULL)
return -ENOMEM; /* We'll just try again later. */
+
sk_charge_skb(sk, buff);
+ nlen = skb->len - len - nsize;
+ buff->truesize += nlen;
+ skb->truesize -= nlen;
/* Correct the sequence numbers. */
TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
@@ -1040,7 +1042,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
if (unlikely(buff == NULL))
return -ENOMEM;
- buff->truesize = nlen;
+ sk_charge_skb(sk, buff);
+ buff->truesize += nlen;
skb->truesize -= nlen;
/* Correct the sequence numbers. */
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 0d7d386dac22..8d30c48f090e 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -8,6 +8,8 @@
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <net/icmp.h>
+#include <net/ip.h>
#include <net/protocol.h>
#include <net/xfrm.h>
@@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb)
{
struct xfrm_tunnel *handler;
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ goto drop;
+
for (handler = tunnel4_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+drop:
kfree_skb(skb);
return 0;
}
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 850d919591d1..3e174c83bfe7 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
{
switch (nexthdr) {
case IPPROTO_IPIP:
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
- return -EINVAL;
*spi = skb->nh.iph->saddr;
*seq = 0;
return 0;
@@ -68,7 +66,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
{
int err;
u32 spi, seq;
- struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+ struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
struct xfrm_state *x;
int xfrm_nr = 0;
int decaps = 0;
@@ -90,14 +88,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (unlikely(x->km.state != XFRM_STATE_VALID))
goto drop_unlock;
+ if ((x->encap ? x->encap->encap_type : 0) != encap_type)
+ goto drop_unlock;
+
if (x->props.replay_window && xfrm_replay_check(x, seq))
goto drop_unlock;
if (xfrm_state_check_expire(x))
goto drop_unlock;
- xfrm_vec[xfrm_nr].decap.decap_type = encap_type;
- if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb))
+ if (x->type->input(x, skb))
goto drop_unlock;
/* only the first xfrm gets the encap type */
@@ -111,7 +111,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
spin_unlock(&x->lock);
- xfrm_vec[xfrm_nr++].xvec = x;
+ xfrm_vec[xfrm_nr++] = x;
iph = skb->nh.iph;
@@ -153,7 +153,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
goto drop;
- memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+ memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+ xfrm_nr * sizeof(xfrm_vec[0]));
skb->sp->len += xfrm_nr;
nf_reset(skb);
@@ -184,7 +185,7 @@ drop_unlock:
xfrm_state_put(x);
drop:
while (--xfrm_nr >= 0)
- xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+ xfrm_state_put(xfrm_vec[xfrm_nr]);
kfree_skb(skb);
return 0;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 2d670935c2b5..f8ceaa127c83 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -21,7 +21,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
{
return 0;
}
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index cf58251df4b3..6778173a3dda 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -229,7 +229,7 @@ error:
return err;
}
-static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
{
/*
* Before process AH
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 3dcaac7a0972..22f046079037 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -130,7 +130,7 @@ error:
return err;
}
-static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *iph;
struct ipv6_esp_hdr *esph;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2a1e7e45b890..a18d4256372c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
{ -1, }
};
-int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
+int ipv6_parse_hopopts(struct sk_buff *skb)
{
struct inet6_skb_parm *opt = IP6CB(skb);
+ /*
+ * skb->nh.raw is equal to skb->data, and
+ * skb->h.raw - skb->nh.raw is always equal to
+ * sizeof(struct ipv6hdr) by definition of
+ * hop-by-hop options.
+ */
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
+ !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
+ kfree_skb(skb);
+ return -1;
+ }
+
opt->hop = sizeof(struct ipv6hdr);
if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
skb->h.raw += (skb->h.raw[1]+1)<<3;
opt->nhoff = sizeof(struct ipv6hdr);
- return sizeof(struct ipv6hdr);
+ return 1;
}
return -1;
}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 21eb725e885f..1044b6fce0d5 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -717,7 +717,7 @@ int __init icmpv6_init(struct net_proto_family *ops)
struct sock *sk;
int err, i, j;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
&per_cpu(__icmpv6_socket, i));
if (err < 0) {
@@ -763,7 +763,7 @@ void icmpv6_cleanup(void)
{
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
sock_release(per_cpu(__icmpv6_socket, i));
}
inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index bb8ffb8a14c5..2ae84c961678 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -23,6 +23,86 @@
#include <net/inet6_hashtables.h>
#include <net/ip.h>
+void __inet6_hash(struct inet_hashinfo *hashinfo,
+ struct sock *sk)
+{
+ struct hlist_head *list;
+ rwlock_t *lock;
+
+ BUG_TRAP(sk_unhashed(sk));
+
+ if (sk->sk_state == TCP_LISTEN) {
+ list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
+ lock = &hashinfo->lhash_lock;
+ inet_listen_wlock(hashinfo);
+ } else {
+ unsigned int hash;
+ sk->sk_hash = hash = inet6_sk_ehashfn(sk);
+ hash &= (hashinfo->ehash_size - 1);
+ list = &hashinfo->ehash[hash].chain;
+ lock = &hashinfo->ehash[hash].lock;
+ write_lock(lock);
+ }
+
+ __sk_add_node(sk, list);
+ sock_prot_inc_use(sk->sk_prot);
+ write_unlock(lock);
+}
+EXPORT_SYMBOL(__inet6_hash);
+
+/*
+ * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ *
+ * The sockhash lock must be held as a reader here.
+ */
+struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const u16 sport,
+ const struct in6_addr *daddr,
+ const u16 hnum,
+ const int dif)
+{
+ struct sock *sk;
+ const struct hlist_node *node;
+ const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+ /* Optimize here for direct hit, only listening connections can
+ * have wildcards anyways.
+ */
+ unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
+ struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
+
+ prefetch(head->chain.first);
+ read_lock(&head->lock);
+ sk_for_each(sk, node, &head->chain) {
+ /* For IPV6 do the cheaper port and family tests first. */
+ if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
+ goto hit; /* You sunk my battleship! */
+ }
+ /* Must check for a TIME_WAIT'er before going to listener hash. */
+ sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
+ const struct inet_timewait_sock *tw = inet_twsk(sk);
+
+ if(*((__u32 *)&(tw->tw_dport)) == ports &&
+ sk->sk_family == PF_INET6) {
+ const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
+
+ if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
+ ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
+ (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
+ goto hit;
+ }
+ }
+ read_unlock(&head->lock);
+ return NULL;
+
+hit:
+ sock_hold(sk);
+ read_unlock(&head->lock);
+ return sk;
+}
+EXPORT_SYMBOL(__inet6_lookup_established);
+
struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
const unsigned short hnum, const int dif)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 29f73592e68e..aceee252503d 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
}
if (hdr->nexthdr == NEXTHDR_HOP) {
- if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
+ if (ipv6_parse_hopopts(skb) < 0) {
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
return 0;
}
- hdr = skb->nh.ipv6h;
}
return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index ff9040c92556..a995796b5a57 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb)
struct ipv6hdr *ipv6h;
struct ip6_tnl *t;
- if (!pskb_may_pull(skb, sizeof (*ipv6h)))
- goto discard;
-
ipv6h = skb->nh.ipv6h;
read_lock(&ip6ip6_lock);
@@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb)
if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
read_unlock(&ip6ip6_lock);
- kfree_skb(skb);
- return 0;
+ goto discard;
}
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb)
return 0;
}
read_unlock(&ip6ip6_lock);
- icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
-discard:
return 1;
+
+discard:
+ kfree_skb(skb);
+ return 0;
}
static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index d4cfec3f414e..05eb67def39f 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -63,7 +63,7 @@ static void **ipcomp6_scratches;
static int ipcomp6_scratch_users;
static LIST_HEAD(ipcomp6_tfms_list);
-static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
int err = 0;
u8 nexthdr = 0;
@@ -290,7 +290,7 @@ static void ipcomp6_free_scratches(void)
if (!scratches)
return;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
void *scratch = *per_cpu_ptr(scratches, i);
vfree(scratch);
@@ -313,7 +313,7 @@ static void **ipcomp6_alloc_scratches(void)
ipcomp6_scratches = scratches;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
if (!scratch)
return NULL;
@@ -344,7 +344,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
if (!tfms)
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
crypto_free_tfm(tfm);
}
@@ -384,7 +384,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
if (!tfms)
goto error;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
if (!tfm)
goto error;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d750cfc019dc..395a417ba955 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -7,6 +7,7 @@
#include <net/ipv6.h>
#include <net/ip6_route.h>
#include <net/xfrm.h>
+#include <net/ip6_checksum.h>
int ip6_route_me_harder(struct sk_buff *skb)
{
@@ -54,7 +55,7 @@ struct ip6_rt_info {
struct in6_addr saddr;
};
-static void save(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
@@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info)
}
}
-static int reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
@@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
-static struct nf_queue_rerouter ip6_reroute = {
- .rer_size = sizeof(struct ip6_rt_info),
- .save = &save,
- .reroute = &reroute,
+unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol)
+{
+ struct ipv6hdr *ip6h = skb->nh.ipv6h;
+ unsigned int csum = 0;
+
+ switch (skb->ip_summed) {
+ case CHECKSUM_HW:
+ if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
+ break;
+ if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ skb->len - dataoff, protocol,
+ csum_sub(skb->csum,
+ skb_checksum(skb, 0,
+ dataoff, 0)))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ break;
+ }
+ /* fall through */
+ case CHECKSUM_NONE:
+ skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ skb->len - dataoff,
+ protocol,
+ csum_sub(0,
+ skb_checksum(skb, 0,
+ dataoff, 0)));
+ csum = __skb_checksum_complete(skb);
+ }
+ return csum;
+}
+
+EXPORT_SYMBOL(nf_ip6_checksum);
+
+static struct nf_afinfo nf_ip6_afinfo = {
+ .family = AF_INET6,
+ .checksum = nf_ip6_checksum,
+ .saveroute = nf_ip6_saveroute,
+ .reroute = nf_ip6_reroute,
+ .route_key_size = sizeof(struct ip6_rt_info),
};
int __init ipv6_netfilter_init(void)
{
- return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
+ return nf_register_afinfo(&nf_ip6_afinfo);
}
/* This can be called from inet6_init() on errors, so it cannot
@@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void)
*/
void ipv6_netfilter_fini(void)
{
- nf_unregister_queue_rerouter(PF_INET6);
+ nf_unregister_afinfo(&nf_ip6_afinfo);
}
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 98f78759f1ab..4bc4e5b33794 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -87,16 +87,6 @@ config IP6_NF_MATCH_HL
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_MULTIPORT
- tristate "Multiple port match support"
- depends on IP6_NF_IPTABLES
- help
- Multiport matching allows you to match TCP or UDP packets based on
- a series of source or destination ports: normally a rule can only
- match a single range of ports.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP6_NF_MATCH_OWNER
tristate "Owner match support"
depends on IP6_NF_IPTABLES
@@ -115,11 +105,11 @@ config IP6_NF_MATCH_IPV6HEADER
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_AHESP
- tristate "AH/ESP match support"
+config IP6_NF_MATCH_AH
+ tristate "AH match support"
depends on IP6_NF_IPTABLES
help
- This module allows one to match AH and ESP packets.
+ This module allows one to match AH packets.
To compile it as a module, choose M here. If unsure, say N.
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 8436a1a1731f..eeeb57d4c9c5 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -8,9 +8,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
-obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
+obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
-obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index e81c6a9dab81..b4b7d441af25 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = {
.outfn = &ipq_enqueue_packet,
};
-static int
-init_or_cleanup(int init)
+static int __init ip6_queue_init(void)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
- if (!init)
- goto cleanup;
-
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
THIS_MODULE);
@@ -693,11 +689,6 @@ init_or_cleanup(int init)
}
return status;
-cleanup:
- nf_unregister_queue_handlers(&nfqh);
- synchronize_net();
- ipq_flush(NF_DROP);
-
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -713,15 +704,21 @@ cleanup_netlink_notifier:
return status;
}
-static int __init ip6_queue_init(void)
-{
-
- return init_or_cleanup(1);
-}
-
static void __exit ip6_queue_fini(void)
{
- init_or_cleanup(0);
+ nf_unregister_queue_handlers(&nfqh);
+ synchronize_net();
+ ipq_flush(NF_DROP);
+
+ unregister_sysctl_table(ipq_sysctl_header);
+ unregister_netdevice_notifier(&ipq_dev_notifier);
+ proc_net_remove(IPQ_PROC_FS_NAME);
+
+ sock_release(ipqnl->sk_socket);
+ mutex_lock(&ipqnl_mutex);
+ mutex_unlock(&ipqnl_mutex);
+
+ netlink_unregister_notifier(&ipq_nl_notifier);
}
MODULE_DESCRIPTION("IPv6 packet queue handler");
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 3ecf2db841f8..0a673038344f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -288,19 +288,6 @@ ip6t_do_table(struct sk_buff **pskb,
table_base = (void *)private->entries[smp_processor_id()];
e = get_entry(table_base, private->hook_entry[hook]);
-#ifdef CONFIG_NETFILTER_DEBUG
- /* Check noone else using our table */
- if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
- && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
- printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
- smp_processor_id(),
- table->name,
- &((struct ip6t_entry *)table_base)->comefrom,
- ((struct ip6t_entry *)table_base)->comefrom);
- }
- ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
-#endif
-
/* For return from builtin chain */
back = get_entry(table_base, private->underflow[hook]);
@@ -788,7 +775,7 @@ translate_table(const char *name,
}
/* And one copy for every other CPU */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (newinfo->entries[i] && newinfo->entries[i] != entry0)
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
@@ -841,7 +828,7 @@ get_counters(const struct xt_table_info *t,
counters,
&i);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == curcpu)
continue;
i = 0;
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
deleted file mode 100644
index 36bedad2c6f7..000000000000
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Kernel module to match ESP parameters. */
-/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
- *
- * 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/skbuff.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/types.h>
-#include <net/checksum.h>
-#include <net/ipv6.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_esp.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IPv6 ESP 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)
-{
- int r=0;
- DEBUGP("esp 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");
- return r;
-}
-
-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)
-{
- struct ip_esp_hdr _esp, *eh;
- const struct ip6t_esp *espinfo = matchinfo;
- unsigned int ptr;
-
- /* Make sure this isn't an evil packet */
- /*DEBUGP("ipv6_esp entered \n");*/
-
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0)
- return 0;
-
- eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
- if (eh == NULL) {
- *hotdrop = 1;
- return 0;
- }
-
- DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
-
- return (eh != NULL)
- && spi_match(espinfo->spis[0], espinfo->spis[1],
- ntohl(eh->spi),
- !!(espinfo->invflags & IP6T_ESP_INV_SPI));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
-{
- const struct ip6t_esp *espinfo = matchinfo;
-
- if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
- DEBUGP("ip6t_esp: unknown flags %X\n",
- espinfo->invflags);
- return 0;
- }
- return 1;
-}
-
-static struct ip6t_match esp_match = {
- .name = "esp",
- .match = match,
- .matchsize = sizeof(struct ip6t_esp),
- .checkentry = checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init ip6t_esp_init(void)
-{
- return ip6t_register_match(&esp_match);
-}
-
-static void __exit ip6t_esp_fini(void)
-{
- ip6t_unregister_match(&esp_match);
-}
-
-module_init(ip6t_esp_init);
-module_exit(ip6t_esp_fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
deleted file mode 100644
index 10c48ba596d6..000000000000
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
- the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.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/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("ip6tables match for multiple ports");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ip6t_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 != IP6T_MULTIPORT_DESTINATION
- && portlist[i] == src)
- return 1;
-
- if (flags != IP6T_MULTIPORT_SOURCE
- && portlist[i] == dst)
- return 1;
- }
-
- return 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)
-{
- u16 _ports[2], *pptr;
- const struct ip6t_multiport *multiinfo = matchinfo;
-
- /* Must not be a fragment. */
- if (offset)
- return 0;
-
- /* Must be big enough to read ports (both UDP and TCP have
- them at the start). */
- pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
- if (pptr == NULL) {
- /* We've been asked to examine this packet, and we
- * can't. Hence, no choice but to drop.
- */
- duprintf("ip6t_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return ports_match(multiinfo->ports,
- multiinfo->flags, multiinfo->count,
- ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- const struct ip6t_ip6 *ip = info;
- const struct ip6t_multiport *multiinfo = matchinfo;
-
- /* Must specify proto == TCP/UDP, no unknown flags or bad count */
- return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
- && !(ip->invflags & IP6T_INV_PROTO)
- && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
- || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
- || multiinfo->flags == IP6T_MULTIPORT_EITHER)
- && multiinfo->count <= IP6T_MULTI_PORTS;
-}
-
-static struct ip6t_match multiport_match = {
- .name = "multiport",
- .match = match,
- .matchsize = sizeof(struct ip6t_multiport),
- .checkentry = checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init ip6t_multiport_init(void)
-{
- return ip6t_register_match(&multiport_match);
-}
-
-static void __exit ip6t_multiport_fini(void)
-{
- ip6t_unregister_match(&multiport_match);
-}
-
-module_init(ip6t_multiport_init);
-module_exit(ip6t_multiport_fini);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index e5e724d9ee60..60976c0c58e8 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -177,37 +177,20 @@ static int __init ip6table_filter_init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ip6t_ops[0]);
+ ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ip6t_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ip6t_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
return ret;
- cleanup_hook1:
- nf_unregister_hook(&ip6t_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_filter);
-
return ret;
}
static void __exit ip6table_filter_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ip6t_ops[i]);
-
+ nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_filter);
}
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index e1f0f6ae9841..03a13eab1dae 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -238,49 +238,20 @@ static int __init ip6table_mangle_init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ip6t_ops[0]);
+ ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ip6t_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ip6t_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
- ret = nf_register_hook(&ip6t_ops[3]);
- if (ret < 0)
- goto cleanup_hook2;
-
- ret = nf_register_hook(&ip6t_ops[4]);
- if (ret < 0)
- goto cleanup_hook3;
-
return ret;
- cleanup_hook3:
- nf_unregister_hook(&ip6t_ops[3]);
- cleanup_hook2:
- nf_unregister_hook(&ip6t_ops[2]);
- cleanup_hook1:
- nf_unregister_hook(&ip6t_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_mangler);
-
return ret;
}
static void __exit ip6table_mangle_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ip6t_ops[i]);
-
+ nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_mangler);
}
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 54d1fffd62ba..61a7c58e99f8 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -152,31 +152,20 @@ static int __init ip6table_raw_init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ip6t_ops[0]);
+ ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ip6t_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
return ret;
- cleanup_hook0:
- nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_raw);
-
return ret;
}
static void __exit ip6table_raw_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ip6t_ops[i]);
-
+ nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_raw);
}
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c8b5a96cbb0f..93bae36f2663 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
}
-/* Connection tracking may drop packets, but never alters them, so
- make it the first hook. */
-static struct nf_hook_ops ipv6_conntrack_defrag_ops = {
- .hook = ipv6_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_PRE_ROUTING,
- .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv6_conntrack_in_ops = {
- .hook = ipv6_conntrack_in,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_PRE_ROUTING,
- .priority = NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_out_ops = {
- .hook = ipv6_conntrack_local,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_OUT,
- .priority = NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = {
- .hook = ipv6_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_OUT,
- .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv6_conntrack_out_ops = {
- .hook = ipv6_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_POST_ROUTING,
- .priority = NF_IP6_PRI_LAST,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
- .hook = ipv6_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_IN,
- .priority = NF_IP6_PRI_LAST-1,
+static struct nf_hook_ops ipv6_conntrack_ops[] = {
+ {
+ .hook = ipv6_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_PRE_ROUTING,
+ .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv6_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_PRE_ROUTING,
+ .priority = NF_IP6_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv6_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_LOCAL_OUT,
+ .priority = NF_IP6_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv6_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_LOCAL_OUT,
+ .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv6_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_POST_ROUTING,
+ .priority = NF_IP6_PRI_LAST,
+ },
+ {
+ .hook = ipv6_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_LOCAL_IN,
+ .priority = NF_IP6_PRI_LAST-1,
+ },
};
#ifdef CONFIG_SYSCTL
@@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
extern int nf_ct_frag6_init(void);
extern void nf_ct_frag6_cleanup(void);
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
+
+static int __init nf_conntrack_l3proto_ipv6_init(void)
{
int ret = 0;
- if (!init) goto cleanup;
+ need_conntrack();
ret = nf_ct_frag6_init();
if (ret < 0) {
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
- goto cleanup_nothing;
+ return ret;
}
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
if (ret < 0) {
@@ -505,71 +504,27 @@ static int init_or_cleanup(int init)
goto cleanup_icmpv6;
}
- ret = nf_register_hook(&ipv6_conntrack_defrag_ops);
+ ret = nf_register_hooks(ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register pre-routing defrag "
"hook.\n");
goto cleanup_ipv6;
}
-
- ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register local_out defrag "
- "hook.\n");
- goto cleanup_defragops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
- goto cleanup_defraglocalops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register local out hook.\n");
- goto cleanup_inops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
- goto cleanup_inandlocalops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register local in hook.\n");
- goto cleanup_inoutandlocalops;
- }
-
#ifdef CONFIG_SYSCTL
nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_ipv6_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
- goto cleanup_localinops;
+ goto cleanup_hooks;
}
#endif
return ret;
- cleanup:
- synchronize_net();
#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+ nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
#endif
- nf_unregister_hook(&ipv6_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
- nf_unregister_hook(&ipv6_conntrack_out_ops);
- cleanup_inandlocalops:
- nf_unregister_hook(&ipv6_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ipv6_conntrack_in_ops);
- cleanup_defraglocalops:
- nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
- cleanup_defragops:
- nf_unregister_hook(&ipv6_conntrack_defrag_ops);
cleanup_ipv6:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
cleanup_icmpv6:
@@ -580,23 +535,21 @@ static int init_or_cleanup(int init)
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
cleanup_frag6:
nf_ct_frag6_cleanup();
- cleanup_nothing:
return ret;
}
-MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
-
-static int __init nf_conntrack_l3proto_ipv6_init(void)
-{
- need_conntrack();
- return init_or_cleanup(1);
-}
-
static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
- init_or_cleanup(0);
+ synchronize_net();
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
+#endif
+ nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+ nf_ct_frag6_cleanup();
}
module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 09945c333055..86c6703265d0 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
return -NF_ACCEPT;
}
- if (hooknum != NF_IP6_PRE_ROUTING)
- goto skipped;
-
- /* Ignore it if the checksum's bogus. */
- if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- skb->len - dataoff, IPPROTO_ICMPV6,
- skb_checksum(skb, dataoff,
- skb->len - dataoff, 0))) {
+ if (hooknum == NF_IP6_PRE_ROUTING &&
+ nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
"nf_ct_icmpv6: ICMPv6 checksum failed\n");
return -NF_ACCEPT;
}
-skipped:
-
/* is not error message ? */
if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 4238b1ed8860..779ddf77f4d4 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto)
int res = 0;
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
res += proto->stats[cpu].inuse;
return res;
@@ -140,7 +140,7 @@ fold_field(void *mib[], int offt)
unsigned long res = 0;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
}
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index b67a45fb93e9..eef985e010ea 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -121,6 +121,10 @@ static __inline__ void fq_unlink(struct frag_queue *fq)
write_unlock(&ip6_frag_lock);
}
+/*
+ * callers should be careful not to use the hash value outside the ipfrag_lock
+ * as doing so could race with ipfrag_hash_rnd being recalculated.
+ */
static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
struct in6_addr *daddr)
{
@@ -324,15 +328,16 @@ out:
/* Creation primitives. */
-static struct frag_queue *ip6_frag_intern(unsigned int hash,
- struct frag_queue *fq_in)
+static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
{
struct frag_queue *fq;
+ unsigned int hash;
#ifdef CONFIG_SMP
struct hlist_node *n;
#endif
write_lock(&ip6_frag_lock);
+ hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr);
#ifdef CONFIG_SMP
hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
if (fq->id == fq_in->id &&
@@ -362,7 +367,7 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
static struct frag_queue *
-ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
+ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct frag_queue *fq;
@@ -379,7 +384,7 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr
spin_lock_init(&fq->lock);
atomic_set(&fq->refcnt, 1);
- return ip6_frag_intern(hash, fq);
+ return ip6_frag_intern(fq);
oom:
IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
@@ -391,9 +396,10 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct frag_queue *fq;
struct hlist_node *n;
- unsigned int hash = ip6qhashfn(id, src, dst);
+ unsigned int hash;
read_lock(&ip6_frag_lock);
+ hash = ip6qhashfn(id, src, dst);
hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
if (fq->id == id &&
ipv6_addr_equal(src, &fq->saddr) &&
@@ -405,7 +411,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
}
read_unlock(&ip6_frag_lock);
- return ip6_frag_create(hash, id, src, dst);
+ return ip6_frag_create(id, src, dst);
}
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c2d3e17beae6..6578c3080f47 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb)
return 0;
}
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
kfree_skb(skb);
read_unlock(&ipip6_lock);
out:
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 5659b52284bd..0ef9a35798d1 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -19,11 +19,13 @@
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
*/
+#include <linux/icmpv6.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>
@@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler;
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ goto drop;
+
for (handler = tunnel6_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
+
+drop:
kfree_skb(skb);
return 0;
}
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index cccf8b76f046..00cfdee18dca 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -32,7 +32,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
{
int err;
u32 seq;
- struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+ struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
struct xfrm_state *x;
int xfrm_nr = 0;
int decaps = 0;
@@ -65,7 +65,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
if (xfrm_state_check_expire(x))
goto drop_unlock;
- nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb);
+ nexthdr = x->type->input(x, skb);
if (nexthdr <= 0)
goto drop_unlock;
@@ -79,7 +79,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
spin_unlock(&x->lock);
- xfrm_vec[xfrm_nr++].xvec = x;
+ xfrm_vec[xfrm_nr++] = x;
if (x->props.mode) { /* XXX */
if (nexthdr != IPPROTO_IPV6)
@@ -118,7 +118,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
goto drop;
- memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+ memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+ xfrm_nr * sizeof(xfrm_vec[0]));
skb->sp->len += xfrm_nr;
skb->ip_summed = CHECKSUM_NONE;
@@ -149,7 +150,7 @@ drop_unlock:
xfrm_state_put(x);
drop:
while (--xfrm_nr >= 0)
- xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+ xfrm_state_put(xfrm_vec[xfrm_nr]);
kfree_skb(skb);
return -1;
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 91cce8b2d7a5..88c840f1beb6 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -191,16 +191,18 @@ error:
static inline void
_decode_session6(struct sk_buff *skb, struct flowi *fl)
{
- u16 offset = sizeof(struct ipv6hdr);
+ u16 offset = skb->h.raw - skb->nh.raw;
struct ipv6hdr *hdr = skb->nh.ipv6h;
- struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
+ struct ipv6_opt_hdr *exthdr;
+ u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
memset(fl, 0, sizeof(struct flowi));
ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+ exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+
switch (nexthdr) {
case NEXTHDR_ROUTING:
case NEXTHDR_HOP:
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index a8f6776c518d..d37768e5064f 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -351,7 +351,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
return 0;
}
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 8f3addf0724c..d62e0f9b9da3 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -118,7 +118,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
u16 pdulen = eth_hdr(skb)->h_proto,
data_size = ntohs(pdulen) - llc_len;
- skb_trim(skb, data_size);
+ if (unlikely(pskb_trim_rcsum(skb, data_size)))
+ return 0;
}
return 1;
}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 332acb37b385..e2893effdfaa 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -231,6 +231,15 @@ config NETFILTER_XT_MATCH_DCCP
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_MATCH_ESP
+ tristate '"ESP" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This match extension allows you to match a range of SPIs
+ inside ESP header of IPSec packets.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_HELPER
tristate '"helper" match support'
depends on NETFILTER_XTABLES
@@ -289,6 +298,16 @@ config NETFILTER_XT_MATCH_POLICY
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_MULTIPORT
+ tristate "Multiple port match support"
+ depends on NETFILTER_XTABLES
+ help
+ Multiport matching allows you to match TCP or UDP packets based on
+ a series of source or destination ports: normally a rule can only
+ match a single range of ports.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_PHYSDEV
tristate '"physdev" match support'
depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 9558727f5e79..95b7e416512d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -35,11 +35,13 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.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
+obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1ceb1a6c254b..8455a32ea5c4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,6 +27,29 @@
#include "nf_internals.h"
+static DEFINE_SPINLOCK(afinfo_lock);
+
+struct nf_afinfo *nf_afinfo[NPROTO];
+EXPORT_SYMBOL(nf_afinfo);
+
+int nf_register_afinfo(struct nf_afinfo *afinfo)
+{
+ spin_lock(&afinfo_lock);
+ rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
+ spin_unlock(&afinfo_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_register_afinfo);
+
+void nf_unregister_afinfo(struct nf_afinfo *afinfo)
+{
+ spin_lock(&afinfo_lock);
+ rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
+ spin_unlock(&afinfo_lock);
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
+
/* In this code, we can be waiting indefinitely for userspace to
* service a packet if a hook returns NF_QUEUE. We could keep a count
* of skbuffs queued for userspace, and not deregister a hook unless
@@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
}
EXPORT_SYMBOL(nf_unregister_hook);
+int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
+{
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; i < n; i++) {
+ err = nf_register_hook(&reg[i]);
+ if (err)
+ goto err;
+ }
+ return err;
+
+err:
+ if (i > 0)
+ nf_unregister_hooks(reg, i);
+ return err;
+}
+EXPORT_SYMBOL(nf_register_hooks);
+
+void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ nf_unregister_hook(&reg[i]);
+}
+EXPORT_SYMBOL(nf_unregister_hooks);
+
unsigned int nf_iterate(struct list_head *head,
struct sk_buff **skb,
int hook,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 56389c83557c..f9b83f91371a 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -146,7 +146,7 @@ static void nf_ct_event_cache_flush(void)
struct nf_conntrack_ecache *ecache;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
ecache = &per_cpu(nf_conntrack_ecache, cpu);
if (ecache->ct)
nf_ct_put(ecache->ct);
@@ -178,9 +178,6 @@ static struct {
/* allocated slab cache + modules which uses this slab cache */
int use;
- /* Initialization */
- int (*init_conntrack)(struct nf_conn *, u_int32_t);
-
} nf_ct_cache[NF_CT_F_NUM];
/* protect members of nf_ct_cache except of "use" */
@@ -208,10 +205,8 @@ nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
preempt_disable();
p = __nf_ct_proto_find(l3proto, protocol);
- if (p) {
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_protocol;
- }
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_protocol;
preempt_enable();
return p;
@@ -229,10 +224,8 @@ nf_ct_l3proto_find_get(u_int16_t l3proto)
preempt_disable();
p = __nf_ct_l3proto_find(l3proto);
- if (p) {
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_l3proto;
- }
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_l3proto;
preempt_enable();
return p;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 7de4f06c63c5..3fc58e454d4e 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -94,5 +94,4 @@ struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = {
.print_conntrack = generic_print_conntrack,
.prepare = generic_prepare,
.get_features = generic_get_features,
- .me = THIS_MODULE,
};
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 0e0e9d7b34c8..bd10eb944b65 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1022,7 +1022,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
return err;
}
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
@@ -1062,7 +1062,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
return err;
}
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
@@ -1687,7 +1687,7 @@ static void __exit ctnetlink_exit(void)
printk("ctnetlink: unregistering from nfnetlink.\n");
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
+ nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
nf_conntrack_unregister_notifier(&ctnl_notifier);
#endif
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6492ed66fb3c..69899f27d26a 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
- unsigned int hooknum,
- int(*csum)(const struct sk_buff *,unsigned int))
+ unsigned int hooknum)
{
struct tcphdr _tcph, *th;
unsigned int tcplen = skb->len - dataoff;
@@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
*/
/* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum(skb, dataoff)) {
+ (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+ nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: bad TCP checksum ");
@@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
return NF_ACCEPT;
}
-static int csum4(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
- skb->len - dataoff, IPPROTO_TCP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, dataoff,
- skb->len - dataoff, 0));
-}
-
-static int csum6(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- skb->len - dataoff, IPPROTO_TCP,
- skb->ip_summed == CHECKSUM_HW
- ? csum_sub(skb->csum,
- skb_checksum(skb, 0, dataoff, 0))
- : skb_checksum(skb, dataoff, skb->len - dataoff,
- 0));
-}
-
-static int tcp_error4(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
-}
-
-static int tcp_error6(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
-}
-
/* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *conntrack,
const struct sk_buff *skb,
@@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
.print_conntrack = tcp_print_conntrack,
.packet = tcp_packet,
.new = tcp_new,
- .error = tcp_error4,
+ .error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr,
@@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
.print_conntrack = tcp_print_conntrack,
.packet = tcp_packet,
.new = tcp_new,
- .error = tcp_error6,
+ .error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 831d206344e0..d93edbfde9e3 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
static int udp_error(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
- unsigned int hooknum,
- int (*csum)(const struct sk_buff *, unsigned int))
+ unsigned int hooknum)
{
unsigned int udplen = skb->len - dataoff;
struct udphdr _hdr, *hdr;
@@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum(skb, dataoff)) {
+ (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+ nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: bad UDP checksum ");
@@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
return NF_ACCEPT;
}
-static int csum4(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
- skb->len - dataoff, IPPROTO_UDP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, dataoff,
- skb->len - dataoff, 0));
-}
-
-static int csum6(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- skb->len - dataoff, IPPROTO_UDP,
- skb->ip_summed == CHECKSUM_HW
- ? csum_sub(skb->csum,
- skb_checksum(skb, 0, dataoff, 0))
- : skb_checksum(skb, dataoff, skb->len - dataoff,
- 0));
-}
-
-static int udp_error4(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
-}
-
-static int udp_error6(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
-}
-
struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
{
.l3proto = PF_INET,
@@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
- .error = udp_error4,
+ .error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
- .error = udp_error6,
+ .error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index c72aa3cd22e4..408960c6a544 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = {
EXPORT_SYMBOL(nf_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
-static int init_or_cleanup(int init)
-{
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc, *proc_exp, *proc_stat;
-#endif
- int ret = 0;
-
- if (!init) goto cleanup;
-
- ret = nf_conntrack_init();
- if (ret < 0)
- goto cleanup_nothing;
-
-#ifdef CONFIG_PROC_FS
- 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;
-
- proc_stat->proc_fops = &ct_cpu_seq_fops;
- proc_stat->owner = THIS_MODULE;
-#endif
-#ifdef CONFIG_SYSCTL
- nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
- if (nf_ct_sysctl_header == NULL) {
- printk("nf_conntrack: can't register to sysctl.\n");
- ret = -ENOMEM;
- goto cleanup_proc_stat;
- }
-#endif
-
- return ret;
-
- cleanup:
-#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_sysctl_header);
- cleanup_proc_stat:
-#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:
-#endif /* CNFIG_PROC_FS */
- nf_conntrack_cleanup();
- cleanup_nothing:
- return ret;
-}
-
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
{
int ret = 0;
@@ -808,12 +751,66 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
static int __init nf_conntrack_standalone_init(void)
{
- return init_or_cleanup(1);
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
+ int ret = 0;
+
+ ret = nf_conntrack_init();
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_PROC_FS
+ 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;
+
+ proc_stat->proc_fops = &ct_cpu_seq_fops;
+ proc_stat->owner = THIS_MODULE;
+#endif
+#ifdef CONFIG_SYSCTL
+ nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
+ if (nf_ct_sysctl_header == NULL) {
+ printk("nf_conntrack: can't register to sysctl.\n");
+ ret = -ENOMEM;
+ goto cleanup_proc_stat;
+ }
+#endif
+ return ret;
+
+#ifdef CONFIG_SYSCTL
+ cleanup_proc_stat:
+#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:
+#endif /* CNFIG_PROC_FS */
+ nf_conntrack_cleanup();
+ return ret;
}
static void __exit nf_conntrack_standalone_fini(void)
{
- init_or_cleanup(0);
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nf_ct_sysctl_header);
+#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();
}
module_init(nf_conntrack_standalone_init);
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d9f0d7ef103b..ee8f70889f47 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,6 @@
* for queueing and must reinject all packets it receives, no matter what.
*/
static struct nf_queue_handler *queue_handler[NPROTO];
-static struct nf_queue_rerouter *queue_rerouter[NPROTO];
static DEFINE_RWLOCK(queue_handler_lock);
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
}
EXPORT_SYMBOL(nf_unregister_queue_handler);
-int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
-{
- if (pf >= NPROTO)
- return -EINVAL;
-
- write_lock_bh(&queue_handler_lock);
- rcu_assign_pointer(queue_rerouter[pf], rer);
- write_unlock_bh(&queue_handler_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
-
-int nf_unregister_queue_rerouter(int pf)
-{
- if (pf >= NPROTO)
- return -EINVAL;
-
- write_lock_bh(&queue_handler_lock);
- rcu_assign_pointer(queue_rerouter[pf], NULL);
- write_unlock_bh(&queue_handler_lock);
- synchronize_rcu();
- return 0;
-}
-EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
-
void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
{
int pf;
@@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
struct net_device *physindev = NULL;
struct net_device *physoutdev = NULL;
#endif
- struct nf_queue_rerouter *rerouter;
+ struct nf_afinfo *afinfo;
/* QUEUE == DROP if noone is waiting, to be safe. */
read_lock(&queue_handler_lock);
@@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
return 1;
}
- info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC);
+ afinfo = nf_get_afinfo(pf);
+ if (!afinfo) {
+ read_unlock(&queue_handler_lock);
+ kfree_skb(*skb);
+ return 1;
+ }
+
+ info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
if (!info) {
if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n",
@@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
if (physoutdev) dev_hold(physoutdev);
}
#endif
- rerouter = rcu_dereference(queue_rerouter[pf]);
- if (rerouter)
- rerouter->save(*skb, info);
-
+ afinfo->saveroute(*skb, info);
status = queue_handler[pf]->outfn(*skb, info, queuenum,
queue_handler[pf]->data);
@@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
{
struct list_head *elem = &info->elem->list;
struct list_head *i;
- struct nf_queue_rerouter *rerouter;
+ struct nf_afinfo *afinfo;
rcu_read_lock();
@@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
}
if (verdict == NF_ACCEPT) {
- rerouter = rcu_dereference(queue_rerouter[info->pf]);
- if (rerouter && rerouter->reroute(&skb, info) < 0)
+ afinfo = nf_get_afinfo(info->pf);
+ if (!afinfo || afinfo->reroute(&skb, info) < 0)
verdict = NF_DROP;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 3e3f5448bacb..c60273cad778 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = {
#endif /* PROC_FS */
-static int
-init_or_cleanup(int init)
+static int __init nfnetlink_log_init(void)
{
int i, status = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_nful;
#endif
- if (!init)
- goto cleanup;
-
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
@@ -1066,30 +1062,25 @@ init_or_cleanup(int init)
goto cleanup_subsys;
proc_nful->proc_fops = &nful_file_ops;
#endif
-
return status;
-cleanup:
- nf_log_unregister_logger(&nfulnl_logger);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nfnetlink_log", proc_net_netfilter);
cleanup_subsys:
-#endif
nfnetlink_subsys_unregister(&nfulnl_subsys);
+#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
return status;
}
-static int __init nfnetlink_log_init(void)
-{
-
- return init_or_cleanup(1);
-}
-
static void __exit nfnetlink_log_fini(void)
{
- init_or_cleanup(0);
+ nf_log_unregister_logger(&nfulnl_logger);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("nfnetlink_log", proc_net_netfilter);
+#endif
+ nfnetlink_subsys_unregister(&nfulnl_subsys);
+ netlink_unregister_notifier(&nfulnl_rtnl_notifier);
}
MODULE_DESCRIPTION("netfilter userspace logging");
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index d0e62f68139f..86a4ac33de34 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = {
#endif /* PROC_FS */
-static int
-init_or_cleanup(int init)
+static int __init nfnetlink_queue_init(void)
{
int i, status = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_nfqueue;
#endif
- if (!init)
- goto cleanup;
-
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
@@ -1101,31 +1097,26 @@ init_or_cleanup(int init)
#endif
register_netdevice_notifier(&nfqnl_dev_notifier);
-
return status;
-cleanup:
- nf_unregister_queue_handlers(&nfqh);
- unregister_netdevice_notifier(&nfqnl_dev_notifier);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
cleanup_subsys:
-#endif
nfnetlink_subsys_unregister(&nfqnl_subsys);
+#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
return status;
}
-static int __init nfnetlink_queue_init(void)
-{
-
- return init_or_cleanup(1);
-}
-
static void __exit nfnetlink_queue_fini(void)
{
- init_or_cleanup(0);
+ nf_unregister_queue_handlers(&nfqh);
+ unregister_netdevice_notifier(&nfqnl_dev_notifier);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
+#endif
+ nfnetlink_subsys_unregister(&nfqnl_subsys);
+ netlink_unregister_notifier(&nfqnl_rtnl_notifier);
}
MODULE_DESCRIPTION("netfilter packet queue handler");
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index a657ab5394c3..17abf60f9570 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -38,6 +38,7 @@ struct xt_af {
struct list_head match;
struct list_head target;
struct list_head tables;
+ struct mutex compat_mutex;
};
static struct xt_af *xt;
@@ -272,6 +273,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
}
EXPORT_SYMBOL_GPL(xt_check_match);
+#ifdef CONFIG_COMPAT
+int xt_compat_match(void *match, void **dstptr, int *size, int convert)
+{
+ struct xt_match *m;
+ struct compat_xt_entry_match *pcompat_m;
+ struct xt_entry_match *pm;
+ u_int16_t msize;
+ int off, ret;
+
+ ret = 0;
+ m = ((struct xt_entry_match *)match)->u.kernel.match;
+ off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize);
+ switch (convert) {
+ case COMPAT_TO_USER:
+ pm = (struct xt_entry_match *)match;
+ msize = pm->u.user.match_size;
+ if (__copy_to_user(*dstptr, pm, msize)) {
+ ret = -EFAULT;
+ break;
+ }
+ msize -= off;
+ if (put_user(msize, (u_int16_t *)*dstptr))
+ ret = -EFAULT;
+ *size -= off;
+ *dstptr += msize;
+ break;
+ case COMPAT_FROM_USER:
+ pcompat_m = (struct compat_xt_entry_match *)match;
+ pm = (struct xt_entry_match *)*dstptr;
+ msize = pcompat_m->u.user.match_size;
+ memcpy(pm, pcompat_m, msize);
+ msize += off;
+ pm->u.user.match_size = msize;
+ *size += off;
+ *dstptr += msize;
+ break;
+ case COMPAT_CALC_SIZE:
+ *size += off;
+ break;
+ default:
+ ret = -ENOPROTOOPT;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_match);
+#endif
+
int xt_check_target(const struct xt_target *target, unsigned short family,
unsigned int size, const char *table, unsigned int hook_mask,
unsigned short proto, int inv_proto)
@@ -301,6 +350,54 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
}
EXPORT_SYMBOL_GPL(xt_check_target);
+#ifdef CONFIG_COMPAT
+int xt_compat_target(void *target, void **dstptr, int *size, int convert)
+{
+ struct xt_target *t;
+ struct compat_xt_entry_target *pcompat;
+ struct xt_entry_target *pt;
+ u_int16_t tsize;
+ int off, ret;
+
+ ret = 0;
+ t = ((struct xt_entry_target *)target)->u.kernel.target;
+ off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize);
+ switch (convert) {
+ case COMPAT_TO_USER:
+ pt = (struct xt_entry_target *)target;
+ tsize = pt->u.user.target_size;
+ if (__copy_to_user(*dstptr, pt, tsize)) {
+ ret = -EFAULT;
+ break;
+ }
+ tsize -= off;
+ if (put_user(tsize, (u_int16_t *)*dstptr))
+ ret = -EFAULT;
+ *size -= off;
+ *dstptr += tsize;
+ break;
+ case COMPAT_FROM_USER:
+ pcompat = (struct compat_xt_entry_target *)target;
+ pt = (struct xt_entry_target *)*dstptr;
+ tsize = pcompat->u.user.target_size;
+ memcpy(pt, pcompat, tsize);
+ tsize += off;
+ pt->u.user.target_size = tsize;
+ *size += off;
+ *dstptr += tsize;
+ break;
+ case COMPAT_CALC_SIZE:
+ *size += off;
+ break;
+ default:
+ ret = -ENOPROTOOPT;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_target);
+#endif
+
struct xt_table_info *xt_alloc_table_info(unsigned int size)
{
struct xt_table_info *newinfo;
@@ -316,7 +413,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
newinfo->size = size;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (size <= PAGE_SIZE)
newinfo->entries[cpu] = kmalloc_node(size,
GFP_KERNEL,
@@ -339,7 +436,7 @@ void xt_free_table_info(struct xt_table_info *info)
{
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (info->size <= PAGE_SIZE)
kfree(info->entries[cpu]);
else
@@ -371,6 +468,19 @@ void xt_table_unlock(struct xt_table *table)
}
EXPORT_SYMBOL_GPL(xt_table_unlock);
+#ifdef CONFIG_COMPAT
+void xt_compat_lock(int af)
+{
+ mutex_lock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_lock);
+
+void xt_compat_unlock(int af)
+{
+ mutex_unlock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_unlock);
+#endif
struct xt_table_info *
xt_replace_table(struct xt_table *table,
@@ -419,6 +529,7 @@ int xt_register_table(struct xt_table *table,
/* Simplifies replace_table code. */
table->private = bootstrap;
+ rwlock_init(&table->lock);
if (!xt_replace_table(table, 0, newinfo, &ret))
goto unlock;
@@ -428,7 +539,6 @@ int xt_register_table(struct xt_table *table,
/* save number of initial entries */
private->initial_entries = private->number;
- rwlock_init(&table->lock);
list_prepend(&xt[table->af].tables, table);
ret = 0;
@@ -671,6 +781,9 @@ static int __init xt_init(void)
for (i = 0; i < NPROTO; i++) {
mutex_init(&xt[i].mutex);
+#ifdef CONFIG_COMPAT
+ mutex_init(&xt[i].compat_mutex);
+#endif
INIT_LIST_HEAD(&xt[i].target);
INIT_LIST_HEAD(&xt[i].match);
INIT_LIST_HEAD(&xt[i].tables);
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/netfilter/xt_esp.c
index 3840b417a3c5..9dad6281e0c1 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -9,16 +9,22 @@
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/in.h>
#include <linux/ip.h>
-#include <linux/netfilter_ipv4/ipt_esp.h>
+#include <linux/netfilter/xt_esp.h>
+#include <linux/netfilter/x_tables.h>
+
#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
-MODULE_DESCRIPTION("iptables ESP SPI match module");
+MODULE_DESCRIPTION("x_tables ESP SPI match module");
+MODULE_ALIAS("ipt_esp");
+MODULE_ALIAS("ip6t_esp");
-#ifdef DEBUG_CONNTRACK
+#if 0
#define duprintf(format, args...) printk(format , ## args)
#else
#define duprintf(format, args...)
@@ -28,11 +34,11 @@ MODULE_DESCRIPTION("iptables ESP SPI match module");
static inline int
spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
{
- int r=0;
- duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
- r=(spi >= min && spi <= max) ^ invert;
- duprintf(" result %s\n",r? "PASS" : "FAILED");
+ int r = 0;
+ duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+ min, spi, max);
+ r = (spi >= min && spi <= max) ^ invert;
+ duprintf(" result %s\n", r ? "PASS" : "FAILED");
return r;
}
@@ -47,14 +53,13 @@ match(const struct sk_buff *skb,
int *hotdrop)
{
struct ip_esp_hdr _esp, *eh;
- const struct ipt_esp *espinfo = matchinfo;
+ const struct xt_esp *espinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
return 0;
- eh = skb_header_pointer(skb, protoff,
- sizeof(_esp), &_esp);
+ eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
if (eh == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
@@ -64,9 +69,8 @@ match(const struct sk_buff *skb,
return 0;
}
- return spi_match(espinfo->spis[0], espinfo->spis[1],
- ntohl(eh->spi),
- !!(espinfo->invflags & IPT_ESP_INV_SPI));
+ return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
+ !!(espinfo->invflags & XT_ESP_INV_SPI));
}
/* Called when user tries to insert an entry of this type. */
@@ -78,34 +82,55 @@ checkentry(const char *tablename,
unsigned int matchinfosize,
unsigned int hook_mask)
{
- const struct ipt_esp *espinfo = matchinfo;
+ const struct xt_esp *espinfo = matchinfo;
- /* Must specify no unknown invflags */
- if (espinfo->invflags & ~IPT_ESP_INV_MASK) {
- duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
+ if (espinfo->invflags & ~XT_ESP_INV_MASK) {
+ duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
return 0;
}
+
return 1;
}
-static struct ipt_match esp_match = {
+static struct xt_match esp_match = {
.name = "esp",
- .match = match,
- .matchsize = sizeof(struct ipt_esp),
+ .family = AF_INET,
.proto = IPPROTO_ESP,
- .checkentry = checkentry,
+ .match = &match,
+ .matchsize = sizeof(struct xt_esp),
+ .checkentry = &checkentry,
.me = THIS_MODULE,
};
-static int __init ipt_esp_init(void)
+static struct xt_match esp6_match = {
+ .name = "esp",
+ .family = AF_INET6,
+ .proto = IPPROTO_ESP,
+ .match = &match,
+ .matchsize = sizeof(struct xt_esp),
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_esp_init(void)
{
- return ipt_register_match(&esp_match);
+ int ret;
+ ret = xt_register_match(&esp_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(&esp6_match);
+ if (ret)
+ xt_unregister_match(&esp_match);
+
+ return ret;
}
-static void __exit ipt_esp_fini(void)
+static void __exit xt_esp_cleanup(void)
{
- ipt_unregister_match(&esp_match);
+ xt_unregister_match(&esp_match);
+ xt_unregister_match(&esp6_match);
}
-module_init(ipt_esp_init);
-module_exit(ipt_esp_fini);
+module_init(xt_esp_init);
+module_exit(xt_esp_cleanup);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
new file mode 100644
index 000000000000..b56cd2baaac2
--- /dev/null
+++ b/net/netfilter/xt_multiport.c
@@ -0,0 +1,314 @@
+/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+ the same place so we can treat them as equal. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.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/types.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include <linux/netfilter/xt_multiport.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_DESCRIPTION("x_tables multiple port match module");
+MODULE_ALIAS("ipt_multiport");
+MODULE_ALIAS("ip6t_multiport");
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+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;
+
+ if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match_v1(const struct xt_multiport_v1 *minfo,
+ u_int16_t src, u_int16_t dst)
+{
+ unsigned int i;
+ u_int16_t s, e;
+
+ for (i = 0; i < minfo->count; i++) {
+ s = minfo->ports[i];
+
+ if (minfo->pflags[i]) {
+ /* range port matching */
+ e = minfo->ports[++i];
+ duprintf("src or dst matches with %d-%d?\n", s, e);
+
+ if (minfo->flags == XT_MULTIPORT_SOURCE
+ && src >= s && src <= e)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_DESTINATION
+ && dst >= s && dst <= e)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_EITHER
+ && ((dst >= s && dst <= e)
+ || (src >= s && src <= e)))
+ return 1 ^ 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;
+ if (minfo->flags == XT_MULTIPORT_DESTINATION
+ && dst == s)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_EITHER
+ && (src == s || dst == s))
+ return 1 ^ minfo->invert;
+ }
+ }
+
+ return minfo->invert;
+}
+
+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)
+{
+ u16 _ports[2], *pptr;
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ if (offset)
+ return 0;
+
+ pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+ if (pptr == NULL) {
+ /* We've been asked to examine this packet, and we
+ * can't. Hence, no choice but to drop.
+ */
+ duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ return ports_match(multiinfo->ports,
+ multiinfo->flags, multiinfo->count,
+ ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static int
+match_v1(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)
+{
+ u16 _ports[2], *pptr;
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ if (offset)
+ return 0;
+
+ pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+ if (pptr == NULL) {
+ /* We've been asked to examine this packet, and we
+ * can't. Hence, no choice but to drop.
+ */
+ duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static inline int
+check(u_int16_t proto,
+ u_int8_t ip_invflags,
+ u_int8_t match_flags,
+ u_int8_t count)
+{
+ /* Must specify proto == TCP/UDP, no unknown flags or bad count */
+ return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+ && !(ip_invflags & XT_INV_PROTO)
+ && (match_flags == XT_MULTIPORT_SOURCE
+ || match_flags == XT_MULTIPORT_DESTINATION
+ || match_flags == XT_MULTIPORT_EITHER)
+ && count <= XT_MULTI_PORTS;
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_ip *ip = info;
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static int
+checkentry_v1(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_ip *ip = info;
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static int
+checkentry6(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ip = info;
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static int
+checkentry6_v1(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ip = info;
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static struct xt_match multiport_match = {
+ .name = "multiport",
+ .revision = 0,
+ .matchsize = sizeof(struct xt_multiport),
+ .match = &match,
+ .checkentry = &checkentry,
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match multiport_match_v1 = {
+ .name = "multiport",
+ .revision = 1,
+ .matchsize = sizeof(struct xt_multiport_v1),
+ .match = &match_v1,
+ .checkentry = &checkentry_v1,
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match multiport6_match = {
+ .name = "multiport",
+ .revision = 0,
+ .matchsize = sizeof(struct xt_multiport),
+ .match = &match,
+ .checkentry = &checkentry6,
+ .family = AF_INET6,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match multiport6_match_v1 = {
+ .name = "multiport",
+ .revision = 1,
+ .matchsize = sizeof(struct xt_multiport_v1),
+ .match = &match_v1,
+ .checkentry = &checkentry6_v1,
+ .family = AF_INET6,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_multiport_init(void)
+{
+ int ret;
+
+ ret = xt_register_match(&multiport_match);
+ if (ret)
+ goto out;
+
+ ret = xt_register_match(&multiport_match_v1);
+ if (ret)
+ goto out_unreg_multi_v0;
+
+ ret = xt_register_match(&multiport6_match);
+ if (ret)
+ goto out_unreg_multi_v1;
+
+ ret = xt_register_match(&multiport6_match_v1);
+ if (ret)
+ goto out_unreg_multi6_v0;
+
+ return ret;
+
+out_unreg_multi6_v0:
+ xt_unregister_match(&multiport6_match);
+out_unreg_multi_v1:
+ xt_unregister_match(&multiport_match_v1);
+out_unreg_multi_v0:
+ xt_unregister_match(&multiport_match);
+out:
+ return ret;
+}
+
+static void __exit xt_multiport_fini(void)
+{
+ xt_unregister_match(&multiport_match);
+ xt_unregister_match(&multiport_match_v1);
+ xt_unregister_match(&multiport6_match);
+ xt_unregister_match(&multiport6_match_v1);
+}
+
+module_init(xt_multiport_init);
+module_exit(xt_multiport_fini);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 1099cb005fcc..a3aa62fbda6f 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -71,7 +71,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info,
return 0;
e = &info->pol[pos];
- if (match_xfrm_state(sp->x[i].xvec, e, family)) {
+ if (match_xfrm_state(sp->xvec[i], e, family)) {
if (!strict)
return 1;
} else if (strict)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 6056d20ef429..37640c6fc014 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -69,6 +69,11 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
DPRINTK("ipt_init_target: found %s\n", target->name);
t->u.kernel.target = target;
+ ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+ table, hook, 0, 0);
+ if (ret)
+ return ret;
+
if (t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(table, NULL,
t->u.kernel.target, t->data,
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fa877f8f652c..24c348fa8922 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
}
#ifdef CONFIG_NET_CLS_ACT
-static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
int type, struct tc_action *a)
{
struct tcf_police *p;
@@ -113,7 +113,7 @@ rtattr_failure:
}
static inline int
-tcf_hash_search(struct tc_action *a, u32 index)
+tcf_act_police_hash_search(struct tc_action *a, u32 index)
{
struct tcf_police *p = tcf_police_lookup(index);
@@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = {
.act = tcf_act_police,
.dump = tcf_act_police_dump,
.cleanup = tcf_act_police_cleanup,
- .lookup = tcf_hash_search,
+ .lookup = tcf_act_police_hash_search,
.init = tcf_act_police_locate,
- .walk = tcf_generic_walker
+ .walk = tcf_act_police_walker
};
static int __init
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index d47a52c303a8..5b3b0e0ae7e5 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -69,7 +69,7 @@ fold_field(void *mib[], int nr)
unsigned long res = 0;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
res +=
*((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
sizeof (unsigned long) * nr));
diff --git a/net/socket.c b/net/socket.c
index b13042f68c02..0ce12dfc7a71 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -119,10 +119,6 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector,
static ssize_t sock_sendpage(struct file *file, struct page *page,
int offset, size_t size, loff_t *ppos, int more);
-extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
- size_t len, unsigned int flags);
-
-
/*
* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
* in the operation structures but are done directly via the socketcall() multiplexor.
@@ -494,6 +490,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
struct file *file;
struct socket *sock;
+ *err = -EBADF;
file = fget_light(fd, fput_needed);
if (file) {
sock = sock_from_file(file, err);
@@ -1418,7 +1415,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
newfd = sock_alloc_fd(&newfile);
if (unlikely(newfd < 0)) {
err = newfd;
- goto out_release;
+ sock_release(newsock);
+ goto out_put;
}
err = sock_attach_fd(newsock, newfile);
@@ -1455,10 +1453,8 @@ out_put:
out:
return err;
out_fd:
- put_filp(newfile);
+ fput(newfile);
put_unused_fd(newfd);
-out_release:
- sock_release(newsock);
goto out_put;
}
@@ -2137,7 +2133,7 @@ void socket_seq_show(struct seq_file *seq)
int cpu;
int counter = 0;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
counter += per_cpu(sockets_in_use, cpu);
/* It can be negative, by the way. 8) */
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 900ef31f5a0e..519ebc17c028 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -794,7 +794,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
out_err:
dprintk("RPC: gss_create_cred failed with error %d\n", err);
- if (cred) gss_destroy_cred(&cred->gc_base);
return ERR_PTR(err);
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 97c981fa6b8e..76b969e6904f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -212,7 +212,6 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
char *cksumname;
struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */
struct scatterlist sg[1];
- u32 code = GSS_S_FAILURE;
switch (cksumtype) {
case CKSUMTYPE_RSA_MD5:
@@ -221,13 +220,11 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
default:
dprintk("RPC: krb5_make_checksum:"
" unsupported checksum %d", cksumtype);
- goto out;
+ return GSS_S_FAILURE;
}
if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
- goto out;
+ return GSS_S_FAILURE;
cksum->len = crypto_tfm_alg_digestsize(tfm);
- if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
- goto out;
crypto_digest_init(tfm);
sg_set_buf(sg, header, hdrlen);
@@ -235,10 +232,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
process_xdr_buf(body, body_offset, body->len - body_offset,
checksummer, tfm);
crypto_digest_final(tfm, cksum->data);
- code = 0;
-out:
crypto_free_tfm(tfm);
- return code;
+ return 0;
}
EXPORT_SYMBOL(make_checksum);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 4d7eb9e704da..d51e316c5821 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1122,18 +1122,20 @@ svcauth_gss_release(struct svc_rqst *rqstp)
integ_len))
BUG();
if (resbuf->page_len == 0
- && resbuf->tail[0].iov_len + RPC_MAX_AUTH_SIZE
+ && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
< PAGE_SIZE) {
BUG_ON(resbuf->tail[0].iov_len);
/* Use head for everything */
resv = &resbuf->head[0];
} else if (resbuf->tail[0].iov_base == NULL) {
- /* copied from nfsd4_encode_read */
- svc_take_page(rqstp);
- resbuf->tail[0].iov_base = page_address(rqstp
- ->rq_respages[rqstp->rq_resused-1]);
- rqstp->rq_restailpage = rqstp->rq_resused-1;
+ if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
+ > PAGE_SIZE)
+ goto out_err;
+ resbuf->tail[0].iov_base =
+ resbuf->head[0].iov_base
+ + resbuf->head[0].iov_len;
resbuf->tail[0].iov_len = 0;
+ rqstp->rq_restailpage = 0;
resv = &resbuf->tail[0];
} else {
resv = &resbuf->tail[0];
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index dea529666d69..15c2db26767b 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -176,7 +176,8 @@ void rpc_count_iostats(struct rpc_task *task)
op_metrics->om_execute += execute;
}
-void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs)
+static void _print_name(struct seq_file *seq, unsigned int op,
+ struct rpc_procinfo *procs)
{
if (procs[op].p_name)
seq_printf(seq, "\t%12s: ", procs[op].p_name);
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 953307a9df1d..a3bbc891f959 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ)
publ->node, publ->ref, publ->key);
assert(p == publ);
write_unlock_bh(&tipc_nametbl_lock);
- if (publ)
- kfree(publ);
+ kfree(publ);
}
/**
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 8b9bf4a763b5..b1265187b4a8 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -55,12 +55,10 @@
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/wanpipe.h>
#include <linux/if_wanpipe.h>
#include <linux/pkt_sched.h>
#include <linux/tcp_states.h>
#include <linux/if_wanpipe_common.h>
-#include <linux/sdla_x25.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2407a7072327..b54971059f16 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -18,7 +18,7 @@ void __secpath_destroy(struct sec_path *sp)
{
int i;
for (i = 0; i < sp->len; i++)
- xfrm_state_put(sp->x[i].xvec);
+ xfrm_state_put(sp->xvec[i]);
kmem_cache_free(secpath_cachep, sp);
}
EXPORT_SYMBOL(__secpath_destroy);
@@ -37,7 +37,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
memcpy(sp, src, sizeof(*sp));
for (i = 0; i < sp->len; i++)
- xfrm_state_hold(sp->x[i].xvec);
+ xfrm_state_hold(sp->xvec[i]);
}
atomic_set(&sp->refcnt, 1);
return sp;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f5eae9febd26..c3725fe2a8fb 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -943,9 +943,9 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
} else
start = -1;
for (; idx < sp->len; idx++) {
- if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family))
+ if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
return ++idx;
- if (sp->x[idx].xvec->props.mode)
+ if (sp->xvec[idx]->props.mode)
break;
}
return start;
@@ -968,7 +968,7 @@ EXPORT_SYMBOL(xfrm_decode_session);
static inline int secpath_has_tunnel(struct sec_path *sp, int k)
{
for (; k < sp->len; k++) {
- if (sp->x[k].xvec->props.mode)
+ if (sp->xvec[k]->props.mode)
return 1;
}
@@ -994,8 +994,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
int i;
for (i=skb->sp->len-1; i>=0; i--) {
- struct sec_decap_state *xvec = &(skb->sp->x[i]);
- if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
+ struct xfrm_state *x = skb->sp->xvec[i];
+ if (!xfrm_selector_match(&x->sel, &fl, family))
return 0;
}
}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a8e14dc1b04e..3dc3e1f3b7aa 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -805,16 +805,22 @@ void xfrm_replay_notify(struct xfrm_state *x, int event)
case XFRM_REPLAY_UPDATE:
if (x->replay_maxdiff &&
(x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
- (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
- return;
+ (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+ if (x->xflags & XFRM_TIME_DEFER)
+ event = XFRM_REPLAY_TIMEOUT;
+ else
+ return;
+ }
break;
case XFRM_REPLAY_TIMEOUT:
if ((x->replay.seq == x->preplay.seq) &&
(x->replay.bitmap == x->preplay.bitmap) &&
- (x->replay.oseq == x->preplay.oseq))
+ (x->replay.oseq == x->preplay.oseq)) {
+ x->xflags |= XFRM_TIME_DEFER;
return;
+ }
break;
}
@@ -825,8 +831,10 @@ void xfrm_replay_notify(struct xfrm_state *x, int event)
km_state_notify(x, &c);
if (x->replay_maxage &&
- !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) {
xfrm_state_hold(x);
+ x->xflags &= ~XFRM_TIME_DEFER;
+ }
}
EXPORT_SYMBOL(xfrm_replay_notify);
@@ -836,10 +844,15 @@ static void xfrm_replay_timer_handler(unsigned long data)
spin_lock(&x->lock);
- if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
- xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ if (x->km.state == XFRM_STATE_VALID) {
+ if (xfrm_aevent_is_on())
+ xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ else
+ x->xflags |= XFRM_TIME_DEFER;
+ }
spin_unlock(&x->lock);
+ xfrm_state_put(x);
}
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 59620b1554e0..b0d067be7390 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -87,6 +87,11 @@ cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
# $(Q)$(MAKE) $(build)=dir
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+# Prefix -I with $(srctree) if it is not an absolute path
+addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+# Find all -I options and call addtree
+flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
+
# If quiet is set, only print short version of command
cmd = @$(echo-cmd) $(cmd_$(1))
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 550798f57da5..2cb4935e85d1 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -99,11 +99,6 @@ __a_flags = $(_a_flags)
__cpp_flags = $(_cpp_flags)
else
-# Prefix -I with $(srctree) if it is not an absolute path
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
-# Find all -I options and call addtree
-flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
-
# -I$(obj) locates generated .h files
# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
# and locates generated .h files
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index 75f21d843c1d..75f21d843c1d 100644..100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index dadfa20ffec0..dadfa20ffec0 100644..100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 6d411169bfa6..56b3bed1108f 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -1,22 +1,55 @@
#!/bin/bash
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
-# Released under the terms of the GNU GPL
-#
-# Generate a newline separated list of entries from the file/directory
-# supplied as an argument.
-#
-# If a file/directory is not supplied then generate a small dummy file.
+# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
#
-# The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c.
+# Released under the terms of the GNU GPL
#
+# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
+# the cpio archive, and gzip to pack it.
+# The script may also be used to generate the inputfile used for gen_init_cpio
+# This script assumes that gen_init_cpio is located in usr/ directory
+
+# error out on errors
+set -e
+
+usage() {
+cat << EOF
+Usage:
+$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
+ -o <file> Create gzipped initramfs file named <file> using
+ gen_init_cpio and gzip
+ -u <uid> User ID to map to user ID 0 (root).
+ <uid> is only meaningful if <cpio_source>
+ is a directory.
+ -g <gid> Group ID to map to group ID 0 (root).
+ <gid> is only meaningful if <cpio_source>
+ is a directory.
+ <cpio_source> File list or directory for cpio archive.
+ If <cpio_source> is a .cpio file it will be used
+ as direct input to initramfs.
+ -d Output the default cpio list.
+
+All options except -o and -l may be repeated and are interpreted
+sequentially and immediately. -u and -g states are preserved across
+<cpio_source> options so an explicit "-u 0 -g 0" is required
+to reset the root/group mapping.
+EOF
+}
+
+list_default_initramfs() {
+ # echo usr/kinit/kinit
+ :
+}
default_initramfs() {
- cat <<-EOF
+ cat <<-EOF >> ${output}
# This is a very simple, default initramfs
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
+ # file /kinit usr/kinit/kinit 0755 0 0
+ # slink /init kinit 0755 0 0
EOF
}
@@ -42,18 +75,28 @@ filetype() {
return 0
}
+list_print_mtime() {
+ :
+}
+
print_mtime() {
- local argv1="$1"
local my_mtime="0"
- if [ -e "${argv1}" ]; then
- my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1)
+ if [ -e "$1" ]; then
+ my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
fi
-
- echo "# Last modified: ${my_mtime}"
- echo
+
+ echo "# Last modified: ${my_mtime}" >> ${output}
+ echo "" >> ${output}
+}
+
+list_parse() {
+ echo "$1 \\"
}
+# for each file print a line in following format
+# <filetype> <name> <path to file> <octal mode> <uid> <gid>
+# for links, devices etc the format differs. See gen_init_cpio for details
parse() {
local location="$1"
local name="${location/${srcdir}//}"
@@ -99,80 +142,112 @@ parse() {
;;
esac
- echo "${str}"
+ echo "${str}" >> ${output}
return 0
}
-usage() {
- printf "Usage:\n"
- printf "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n"
- printf "\n"
- printf -- "-u <root_uid> User ID to map to user ID 0 (root).\n"
- printf " <root_uid> is only meaningful if <cpio_source>\n"
- printf " is a directory.\n"
- printf -- "-g <root_gid> Group ID to map to group ID 0 (root).\n"
- printf " <root_gid> is only meaningful if <cpio_source>\n"
- printf " is a directory.\n"
- printf "<cpio_source> File list or directory for cpio archive.\n"
- printf " If <cpio_source> is not provided then a\n"
- printf " a default list will be output.\n"
- printf -- "-d Output the default cpio list. If no <cpio_source>\n"
- printf " is given then the default cpio list will be output.\n"
- printf "\n"
- printf "All options may be repeated and are interpreted sequentially\n"
- printf "and immediately. -u and -g states are preserved across\n"
- printf "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n"
- printf "to reset the root/group mapping.\n"
+unknown_option() {
+ printf "ERROR: unknown option \"$arg\"\n" >&2
+ printf "If the filename validly begins with '-', " >&2
+ printf "then it must be prefixed\n" >&2
+ printf "by './' so that it won't be interpreted as an option." >&2
+ printf "\n" >&2
+ usage >&2
+ exit 1
+}
+
+list_header() {
+ echo "deps_initramfs := \\"
+}
+
+header() {
+ printf "\n#####################\n# $1\n" >> ${output}
+}
+
+# process one directory (incl sub-directories)
+dir_filelist() {
+ ${dep_list}header "$1"
+
+ srcdir=$(echo "$1" | sed -e 's://*:/:g')
+ dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
+
+ # If $dirlist is only one line, then the directory is empty
+ if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
+ ${dep_list}print_mtime "$1"
+
+ echo "${dirlist}" | \
+ while read x; do
+ ${dep_list}parse ${x}
+ done
+ fi
}
-build_list() {
- printf "\n#####################\n# $cpio_source\n"
-
- if [ -f "$cpio_source" ]; then
- print_mtime "$cpio_source"
- cat "$cpio_source"
- elif [ -d "$cpio_source" ]; then
- srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g')
- dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
-
- # If $dirlist is only one line, then the directory is empty
- if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
- print_mtime "$cpio_source"
-
- echo "${dirlist}" | \
- while read x; do
- parse ${x}
- done
+# if only one file is specified and it is .cpio file then use it direct as fs
+# if a directory is specified then add all files in given direcotry to fs
+# if a regular file is specified assume it is in gen_initramfs format
+input_file() {
+ source="$1"
+ if [ -f "$1" ]; then
+ ${dep_list}header "$1"
+ is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
+ if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
+ cpio_file=$1
+ [ ! -z ${dep_list} ] && echo "$1"
+ return 0
+ fi
+ if [ -z ${dep_list} ]; then
+ print_mtime "$1" >> ${output}
+ cat "$1" >> ${output}
else
- # Failsafe in case directory is empty
- default_initramfs
+ grep ^file "$1" | cut -d ' ' -f 3
fi
+ elif [ -d "$1" ]; then
+ dir_filelist "$1"
else
- echo " $0: Cannot open '$cpio_source'" >&2
+ echo " ${prog}: Cannot open '$1'" >&2
exit 1
fi
}
-
+prog=$0
root_uid=0
root_gid=0
+dep_list=
+cpio_file=
+cpio_list=
+output="/dev/stdout"
+output_file=""
+arg="$1"
+case "$arg" in
+ "-l") # files included in initramfs - used by kbuild
+ dep_list="list_"
+ shift
+ ;;
+ "-o") # generate gzipped cpio image named $1
+ shift
+ output_file="$1"
+ cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
+ output=${cpio_list}
+ shift
+ ;;
+esac
while [ $# -gt 0 ]; do
arg="$1"
shift
case "$arg" in
- "-u")
+ "-u") # map $1 to uid=0 (root)
root_uid="$1"
shift
;;
- "-g")
+ "-g") # map $1 to gid=0 (root)
root_gid="$1"
shift
;;
- "-d")
+ "-d") # display default initramfs list
default_list="$arg"
- default_initramfs
+ ${dep_list}default_initramfs
;;
"-h")
usage
@@ -181,23 +256,27 @@ while [ $# -gt 0 ]; do
*)
case "$arg" in
"-"*)
- printf "ERROR: unknown option \"$arg\"\n" >&2
- printf "If the filename validly begins with '-', then it must be prefixed\n" >&2
- printf "by './' so that it won't be interpreted as an option." >&2
- printf "\n" >&2
- usage >&2
- exit 1
+ unknown_option
;;
- *)
- cpio_source="$arg"
- build_list
+ *) # input file/dir - process it
+ input_file "$arg" "$#"
;;
esac
;;
esac
done
-# spit out the default cpio list if a source hasn't been specified
-[ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs
-
+# If output_file is set we will generate cpio archive and gzip it
+# we are carefull to delete tmp files
+if [ ! -z ${output_file} ]; then
+ if [ -z ${cpio_file} ]; then
+ cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
+ usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
+ else
+ cpio_tfile=${cpio_file}
+ fi
+ rm ${cpio_list}
+ cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
+ [ -z ${cpio_file} ] && rm ${cpio_tfile}
+fi
exit 0
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 10eeae53d827..8012d1076876 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
@@ -63,20 +64,6 @@ static void check_stdin(void)
}
}
-static char *fgets_check_stream(char *s, int size, FILE *stream)
-{
- char *ret = fgets(s, size, stream);
-
- if (ret == NULL && feof(stream)) {
- printf(_("aborted!\n\n"));
- printf(_("Console input is closed. "));
- printf(_("Run 'make oldconfig' to update configuration.\n\n"));
- exit(1);
- }
-
- return ret;
-}
-
static void conf_askvalue(struct symbol *sym, const char *def)
{
enum symbol_type type = sym_get_type(sym);
@@ -114,7 +101,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
check_stdin();
case ask_all:
fflush(stdout);
- fgets_check_stream(line, 128, stdin);
+ fgets(line, 128, stdin);
return;
case set_default:
printf("%s\n", def);
@@ -328,8 +315,7 @@ static int conf_choice(struct menu *menu)
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym);
cnt = def = 0;
- line[0] = '0';
- line[1] = 0;
+ line[0] = 0;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
@@ -370,7 +356,7 @@ static int conf_choice(struct menu *menu)
check_stdin();
case ask_all:
fflush(stdout);
- fgets_check_stream(line, 128, stdin);
+ fgets(line, 128, stdin);
strip(line);
if (line[0] == '?') {
printf("\n%s\n", menu->sym->help ?
@@ -546,7 +532,7 @@ int main(int ac, char **av)
break;
case 'h':
case '?':
- printf("%s [-o|-s] config\n", av[0]);
+ fprintf(stderr, "See README for usage info\n");
exit(0);
}
}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1b8882ddbc74..1b5df589f3ae 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -325,7 +325,7 @@ int conf_read(const char *name)
sym->flags |= e->right.sym->flags & SYMBOL_NEW;
}
- sym_change_count = conf_warnings && conf_unsaved;
+ sym_change_count = conf_warnings || conf_unsaved;
return 0;
}
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index db07ae73e051..be0200e9cdaf 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -196,8 +196,8 @@ int dialog_checklist(const char *title, const char *prompt, int height,
print_buttons(dialog, height, width, 0);
- wnoutrefresh(list);
wnoutrefresh(dialog);
+ wnoutrefresh(list);
doupdate();
while (key != ESC) {
@@ -225,12 +225,11 @@ int dialog_checklist(const char *title, const char *prompt, int height,
}
scroll--;
print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
- wnoutrefresh(list);
-
print_arrows(dialog, choice, item_no,
scroll, box_y, box_x + check_x + 5, list_height);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
continue; /* wait for another key press */
} else
@@ -252,12 +251,12 @@ int dialog_checklist(const char *title, const char *prompt, int height,
scroll++;
print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
status[scroll + max_choice - 1], max_choice - 1, TRUE);
- wnoutrefresh(list);
print_arrows(dialog, choice, item_no,
scroll, box_y, box_x + check_x + 5, list_height);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
continue; /* wait for another key press */
} else
@@ -271,8 +270,8 @@ int dialog_checklist(const char *title, const char *prompt, int height,
choice = i;
print_item(list, items[(scroll + choice) * 3 + 1],
status[scroll + choice], choice, TRUE);
- wnoutrefresh(list);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
}
continue; /* wait for another key press */
}
@@ -306,8 +305,8 @@ int dialog_checklist(const char *title, const char *prompt, int height,
print_item(list, items[(scroll + i) * 3 + 1],
status[scroll + i], i, i == choice);
}
- wnoutrefresh(list);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
for (i = 0; i < item_no; i++)
if (status[i])
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 09512b544375..bf8052f4fd4a 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -58,8 +58,7 @@
#include "dialog.h"
-#define ITEM_IDENT 1 /* Indent of menu entries. Fixed for all menus */
-static int menu_width;
+static int menu_width, item_x;
/*
* Print menu item
@@ -70,7 +69,7 @@ static void do_print_item(WINDOW * win, const char *item, int choice,
int j;
char *menu_item = malloc(menu_width + 1);
- strncpy(menu_item, item, menu_width - ITEM_IDENT);
+ strncpy(menu_item, item, menu_width - item_x);
menu_item[menu_width] = 0;
j = first_alpha(menu_item, "YyNnMmHh");
@@ -87,13 +86,13 @@ static void do_print_item(WINDOW * win, const char *item, int choice,
wclrtoeol(win);
#endif
wattrset(win, selected ? item_selected_attr : item_attr);
- mvwaddstr(win, choice, ITEM_IDENT, menu_item);
+ mvwaddstr(win, choice, item_x, menu_item);
if (hotkey) {
wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
- mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]);
+ mvwaddch(win, choice, item_x + j, menu_item[j]);
}
if (selected) {
- wmove(win, choice, ITEM_IDENT + 1);
+ wmove(win, choice, item_x + 1);
}
free(menu_item);
wrefresh(win);
@@ -227,6 +226,8 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr);
+ item_x = (menu_width - 70) / 2;
+
/* Set choice to default item */
for (i = 0; i < item_no; i++)
if (strcmp(current, items[i * 2]) == 0)
@@ -263,10 +264,10 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
wnoutrefresh(menu);
print_arrows(dialog, item_no, scroll,
- box_y, box_x + ITEM_IDENT + 1, menu_height);
+ box_y, box_x + item_x + 1, menu_height);
print_buttons(dialog, height, width, 0);
- wmove(menu, choice, ITEM_IDENT + 1);
+ wmove(menu, choice, item_x + 1);
wrefresh(menu);
while (key != ESC) {
@@ -349,7 +350,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
print_item(scroll + choice, choice, TRUE);
print_arrows(dialog, item_no, scroll,
- box_y, box_x + ITEM_IDENT + 1, menu_height);
+ box_y, box_x + item_x + 1, menu_height);
wnoutrefresh(dialog);
wrefresh(menu);
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0b92ddff26fd..cd00e9f07589 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -492,17 +492,19 @@ static int strrcmp(const char *s, const char *sub)
* These functions may often be marked __init and we do not want to
* warn here.
* the pattern is identified by:
- * tosec = .init.text | .exit.text
+ * tosec = .init.text | .exit.text | .init.data
* fromsec = .data
- * atsym = *_driver, *_ops, *_probe, *probe_one
+ * atsym = *_driver, *_template, *_sht, *_ops, *_probe, *probe_one
**/
static int secref_whitelist(const char *tosec, const char *fromsec,
- const char *atsym)
+ const char *atsym)
{
int f1 = 1, f2 = 1;
const char **s;
const char *pat2sym[] = {
"_driver",
+ "_template", /* scsi uses *_template a lot */
+ "_sht", /* scsi also used *_sht to some extent */
"_ops",
"_probe",
"_probe_one",
@@ -522,7 +524,8 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
/* Check for pattern 2 */
if ((strcmp(tosec, ".init.text") != 0) &&
- (strcmp(tosec, ".exit.text") != 0))
+ (strcmp(tosec, ".exit.text") != 0) &&
+ (strcmp(tosec, ".init.data") != 0))
f2 = 0;
if (strcmp(fromsec, ".data") != 0)
f2 = 0;
@@ -658,7 +661,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
warn("%s - Section mismatch: reference to %s:%s from %s "
"before '%s' (at offset -0x%llx)\n",
modname, secname, refsymname, fromsec,
- elf->strtab + before->st_name,
+ elf->strtab + after->st_name,
(long long)r.r_offset);
} else {
warn("%s - Section mismatch: reference to %s:%s from %s "
@@ -820,6 +823,7 @@ static int exit_section(const char *name)
* For our future {in}sanity, add a comment that this is the ppc .opd
* section, not the ia64 .opd section.
* ia64 .opd should not point to discarded sections.
+ * [.rodata] like for .init.text we ignore .rodata references -same reason
**/
static int exit_section_ref_ok(const char *name)
{
@@ -829,6 +833,7 @@ static int exit_section_ref_ok(const char *name)
".exit.text",
".exit.data",
".init.text",
+ ".rodata",
".opd", /* See comment [OPD] */
".toc1", /* used by ppc64 */
".altinstructions",
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index f34373853ef8..f34373853ef8 100644..100755
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
diff --git a/scripts/show_delta b/scripts/show_delta
index 48a706ab3d0c..48a706ab3d0c 100644..100755
--- a/scripts/show_delta
+++ b/scripts/show_delta
diff --git a/scripts/ver_linux b/scripts/ver_linux
index beb43ef7f761..84999f69773d 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -39,10 +39,10 @@ tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' | awk \
fsck.jfs -V 2>&1 | grep version | sed 's/,//' | awk \
'NR==1 {print "jfsutils ", $3}'
-reiserfsck -V 2>&1 | grep reiserfsck | awk \
+reiserfsck -V 2>&1 | grep ^reiserfsck | awk \
'NR==1{print "reiserfsprogs ", $2}'
-fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \
+fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \
'NR==1{print "reiser4progs ", $2}'
xfs_db -V 2>&1 | grep version | awk \
diff --git a/security/keys/key.c b/security/keys/key.c
index a057e3311aad..b6061fa29da7 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -785,6 +785,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
key_check(keyring);
+ key_ref = ERR_PTR(-ENOTDIR);
+ if (keyring->type != &key_type_keyring)
+ goto error_2;
+
down_write(&keyring->sem);
/* if we're going to allocate a new key, we're going to have
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index d65a180f888d..bffa924c1f88 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -437,6 +437,7 @@ EXPORT_SYMBOL(keyring_search);
/*
* search the given keyring only (no recursion)
* - keyring must be locked by caller
+ * - caller must guarantee that the keyring is a keyring
*/
key_ref_t __keyring_search_one(key_ref_t keyring_ref,
const struct key_type *ktype,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index f6940618e345..217a0bef3c82 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -168,11 +168,12 @@ error:
*/
int install_process_keyring(struct task_struct *tsk)
{
- unsigned long flags;
struct key *keyring;
char buf[20];
int ret;
+ might_sleep();
+
if (!tsk->signal->process_keyring) {
sprintf(buf, "_pid.%u", tsk->tgid);
@@ -183,12 +184,12 @@ int install_process_keyring(struct task_struct *tsk)
}
/* attach keyring */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ spin_lock_irq(&tsk->sighand->siglock);
if (!tsk->signal->process_keyring) {
tsk->signal->process_keyring = keyring;
keyring = NULL;
}
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
key_put(keyring);
}
@@ -207,38 +208,37 @@ error:
static int install_session_keyring(struct task_struct *tsk,
struct key *keyring)
{
- unsigned long flags;
struct key *old;
char buf[20];
- int ret;
+
+ might_sleep();
/* create an empty session keyring */
if (!keyring) {
sprintf(buf, "_ses.%u", tsk->tgid);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto error;
- }
+ if (IS_ERR(keyring))
+ return PTR_ERR(keyring);
}
else {
atomic_inc(&keyring->usage);
}
/* install the keyring */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
- old = rcu_dereference(tsk->signal->session_keyring);
+ spin_lock_irq(&tsk->sighand->siglock);
+ old = tsk->signal->session_keyring;
rcu_assign_pointer(tsk->signal->session_keyring, keyring);
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
- ret = 0;
+ /* we're using RCU on the pointer, but there's no point synchronising
+ * on it if it didn't previously point to anything */
+ if (old) {
+ synchronize_rcu();
+ key_put(old);
+ }
- /* we're using RCU on the pointer */
- synchronize_rcu();
- key_put(old);
-error:
- return ret;
+ return 0;
} /* end install_session_keyring() */
@@ -311,7 +311,6 @@ void exit_keys(struct task_struct *tsk)
*/
int exec_keys(struct task_struct *tsk)
{
- unsigned long flags;
struct key *old;
/* newly exec'd tasks don't get a thread keyring */
@@ -323,10 +322,10 @@ int exec_keys(struct task_struct *tsk)
key_put(old);
/* discard the process keyring from a newly exec'd task */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ spin_lock_irq(&tsk->sighand->siglock);
old = tsk->signal->process_keyring;
tsk->signal->process_keyring = NULL;
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
key_put(old);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 640d0bfdbc68..84047f69f9c1 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -264,7 +264,7 @@ int mls_context_to_sid(char oldc,
if (!selinux_mls_enabled) {
if (def_sid != SECSID_NULL && oldc)
- *scontext += strlen(*scontext);
+ *scontext += strlen(*scontext)+1;
return 0;
}
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index dfab6c886698..abe99d881376 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -281,7 +281,7 @@ u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
int i;
for (i = sp->len-1; i >= 0; i--) {
- struct xfrm_state *x = sp->x[i].xvec;
+ struct xfrm_state *x = sp->xvec[i];
if (selinux_authorizable_xfrm(x)) {
struct xfrm_sec_ctx *ctx = x->security;
return ctx->ctx_sid;
@@ -314,7 +314,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
* Only need to verify the existence of an authorizable sp.
*/
for (i = 0; i < sp->len; i++) {
- struct xfrm_state *x = sp->x[i].xvec;
+ struct xfrm_state *x = sp->xvec[i];
if (x && selinux_authorizable_xfrm(x))
goto accept;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 9dd121bb5638..8efc1b12f3a8 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -92,8 +92,9 @@ config SND_SEQUENCER_OSS
Many programs still use the OSS API, so say Y.
- To compile this driver as a module, choose M here: the module
- will be called snd-seq-oss.
+ If you choose M in "Sequencer support" (SND_SEQUENCER),
+ this will be compiled as a module. The module will be called
+ snd-seq-oss.
config SND_RTCTIMER
tristate "RTC Timer support"
diff --git a/sound/core/control.c b/sound/core/control.c
index 574745314e70..22565c9b9603 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -664,7 +664,7 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
snd_power_lock(ctl->card);
- result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+ result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
if (result >= 0)
result = snd_ctl_elem_info(ctl, &info);
snd_power_unlock(ctl->card);
@@ -718,7 +718,7 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
return -EFAULT;
}
snd_power_lock(card);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result >= 0)
result = snd_ctl_elem_read(card, control);
snd_power_unlock(card);
@@ -783,7 +783,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
}
card = file->card;
snd_power_lock(card);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result >= 0)
result = snd_ctl_elem_write(card, file, control);
snd_power_unlock(card);
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 84fef5084e17..3c0161bb5ba4 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -109,7 +109,7 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
goto error;
snd_power_lock(ctl->card);
- err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+ err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
if (err >= 0)
err = snd_ctl_elem_info(ctl, data);
snd_power_unlock(ctl->card);
@@ -294,7 +294,7 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
goto error;
snd_power_lock(card);
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (err >= 0)
err = snd_ctl_elem_read(card, data);
snd_power_unlock(card);
@@ -320,7 +320,7 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
goto error;
snd_power_lock(card);
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (err >= 0)
err = snd_ctl_elem_write(card, file, data);
snd_power_unlock(card);
diff --git a/sound/core/init.c b/sound/core/init.c
index 5bb8a8b23d51..39ed2e5bb0af 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -722,13 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
* snd_power_wait - wait until the power-state is changed.
* @card: soundcard structure
* @power_state: expected power state
- * @file: file structure for the O_NONBLOCK check (optional)
*
* Waits until the power-state is changed.
*
* Note: the power lock must be active before call.
*/
-int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file)
+int snd_power_wait(struct snd_card *card, unsigned int power_state)
{
wait_queue_t wait;
int result = 0;
@@ -745,12 +744,6 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file
}
if (snd_power_get_state(card) == power_state)
break;
-#if 0 /* block all devices */
- if (file && (file->f_flags & O_NONBLOCK)) {
- result = -EAGAIN;
- break;
- }
-#endif
set_current_state(TASK_UNINTERRUPTIBLE);
snd_power_unlock(card);
schedule_timeout(30 * HZ);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f8302b703a30..c5978d6c6080 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -208,9 +208,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
oss_buffer_size = runtime->oss.mmap_bytes;
}
- if (substream->oss.setup &&
- substream->oss.setup->period_size > 16)
- oss_period_size = substream->oss.setup->period_size;
+ if (substream->oss.setup.period_size > 16)
+ oss_period_size = substream->oss.setup.period_size;
else if (runtime->oss.fragshift) {
oss_period_size = 1 << runtime->oss.fragshift;
if (oss_period_size > oss_buffer_size / 2)
@@ -252,10 +251,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
oss_periods = oss_buffer_size / oss_period_size;
- if (substream->oss.setup) {
- if (substream->oss.setup->periods > 1)
- oss_periods = substream->oss.setup->periods;
- }
+ if (substream->oss.setup.periods > 1)
+ oss_periods = substream->oss.setup.periods;
s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
@@ -341,12 +338,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
goto failure;
}
- if (atomic_read(&runtime->mmap_count)) {
+ if (atomic_read(&runtime->mmap_count))
direct = 1;
- } else {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- direct = (setup != NULL && setup->direct);
- }
+ else
+ direct = substream->oss.setup.direct;
_snd_pcm_hw_params_any(sparams);
_snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
@@ -482,7 +477,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
1 : runtime->period_size;
sw_params->xfer_align = 1;
if (atomic_read(&runtime->mmap_count) ||
- (substream->oss.setup && substream->oss.setup->nosilence)) {
+ substream->oss.setup.nosilence) {
sw_params->silence_threshold = 0;
sw_params->silence_size = 0;
} else {
@@ -843,7 +838,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
buf += tmp;
bytes -= tmp;
xfer += tmp;
- if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) ||
+ if (substream->oss.setup.partialfrag ||
runtime->oss.buffer_used == runtime->oss.period_bytes) {
tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
@@ -959,12 +954,12 @@ static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream != NULL) {
- snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
substream->runtime->oss.prepare = 1;
}
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
if (substream != NULL) {
- snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
substream->runtime->oss.prepare = 1;
}
return 0;
@@ -979,7 +974,7 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
if (substream != NULL) {
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
- snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
}
/* note: all errors from the start action are ignored */
/* OSS apps do not know, how to handle them */
@@ -1108,7 +1103,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
__direct:
saved_f_flags = substream->ffile->f_flags;
substream->ffile->f_flags &= ~O_NONBLOCK;
- err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
substream->ffile->f_flags = saved_f_flags;
if (err < 0)
return err;
@@ -1120,7 +1115,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
runtime = substream->runtime;
- err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
if (err < 0)
return err;
runtime->oss.buffer_used = 0;
@@ -1214,12 +1209,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
return err;
- if (atomic_read(&substream->runtime->mmap_count)) {
+ if (atomic_read(&substream->runtime->mmap_count))
direct = 1;
- } else {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- direct = (setup != NULL && setup->direct);
- }
+ else
+ direct = substream->oss.setup.direct;
if (!direct)
return AFMT_MU_LAW | AFMT_U8 |
AFMT_S16_LE | AFMT_S16_BE |
@@ -1437,7 +1430,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
- err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL);
+ err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
if (err < 0)
return err;
}
@@ -1458,7 +1451,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
- err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL);
+ err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
if (err < 0)
return err;
}
@@ -1495,7 +1488,7 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
runtime = substream->runtime;
if (runtime->oss.params || runtime->oss.prepare)
return 0;
- err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
if (err == -EPIPE)
delay = 0; /* hack for broken OSS applications */
else if (err < 0)
@@ -1555,8 +1548,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream
} else {
delay = snd_pcm_oss_bytes(substream, delay);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup && setup->buggyptr)
+ if (substream->oss.setup.buggyptr)
info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
else
info.blocks = (delay + fixup) / runtime->oss.period_bytes;
@@ -1638,37 +1630,46 @@ static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int str
return -EINVAL;
}
-static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name)
+static const char *strip_task_path(const char *path)
{
- const char *ptr, *ptrl;
- struct snd_pcm_oss_setup *setup;
-
- mutex_lock(&pcm->streams[stream].oss.setup_mutex);
- for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, task_name)) {
- mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
- return setup;
- }
- }
- ptr = ptrl = task_name;
- while (*ptr) {
+ const char *ptr, *ptrl = NULL;
+ for (ptr = path; *ptr; ptr++) {
if (*ptr == '/')
ptrl = ptr + 1;
- ptr++;
}
- if (ptrl == task_name) {
- goto __not_found;
- return NULL;
- }
- for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, ptrl)) {
- mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
- return setup;
+ return ptrl;
+}
+
+static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
+ const char *task_name,
+ struct snd_pcm_oss_setup *rsetup)
+{
+ struct snd_pcm_oss_setup *setup;
+
+ mutex_lock(&pcm->streams[stream].oss.setup_mutex);
+ do {
+ for (setup = pcm->streams[stream].oss.setup_list; setup;
+ setup = setup->next) {
+ if (!strcmp(setup->task_name, task_name))
+ goto out;
}
- }
- __not_found:
+ } while ((task_name = strip_task_path(task_name)) != NULL);
+ out:
+ if (setup)
+ *rsetup = *setup;
mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
- return NULL;
+}
+
+static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ runtime = substream->runtime;
+ vfree(runtime->oss.buffer);
+ runtime->oss.buffer = NULL;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+ snd_pcm_oss_plugin_clear(substream);
+#endif
+ substream->oss.oss = 0;
}
static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
@@ -1678,7 +1679,11 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime;
substream->oss.oss = 1;
- substream->oss.setup = setup;
+ substream->oss.setup = *setup;
+ if (setup->nonblock)
+ substream->ffile->f_flags |= O_NONBLOCK;
+ else if (setup->block)
+ substream->ffile->f_flags &= ~O_NONBLOCK;
runtime = substream->runtime;
runtime->oss.params = 1;
runtime->oss.trigger = 1;
@@ -1697,18 +1702,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
runtime->oss.fragshift = 0;
runtime->oss.maxfrags = 0;
runtime->oss.subdivision = 0;
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- runtime = substream->runtime;
- vfree(runtime->oss.buffer);
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- snd_pcm_oss_plugin_clear(substream);
-#endif
- substream->oss.file = NULL;
- substream->oss.oss = 0;
+ substream->pcm_release = snd_pcm_oss_release_substream;
}
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1717,23 +1711,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
snd_assert(pcm_oss_file != NULL, return -ENXIO);
for (cidx = 0; cidx < 2; ++cidx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
- struct snd_pcm_runtime *runtime;
- if (substream == NULL)
- continue;
- runtime = substream->runtime;
-
- snd_pcm_stream_lock_irq(substream);
- if (snd_pcm_running(substream))
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- snd_pcm_stream_unlock_irq(substream);
- if (substream->ffile != NULL) {
- if (substream->ops->hw_free != NULL)
- substream->ops->hw_free(substream);
- substream->ops->close(substream);
- substream->ffile = NULL;
- }
- snd_pcm_oss_release_substream(substream);
- snd_pcm_release_substream(substream);
+ if (substream)
+ snd_pcm_release_substream(substream);
}
kfree(pcm_oss_file);
return 0;
@@ -1743,12 +1722,11 @@ static int snd_pcm_oss_open_file(struct file *file,
struct snd_pcm *pcm,
struct snd_pcm_oss_file **rpcm_oss_file,
int minor,
- struct snd_pcm_oss_setup *psetup,
- struct snd_pcm_oss_setup *csetup)
+ struct snd_pcm_oss_setup *setup)
{
- int err = 0;
+ int idx, err;
struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
+ struct snd_pcm_substream *substream;
unsigned int f_mode = file->f_mode;
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1761,73 +1739,32 @@ static int snd_pcm_oss_open_file(struct file *file,
if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
f_mode = FMODE_WRITE;
- if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
- if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &psubstream)) < 0) {
+
+ for (idx = 0; idx < 2; idx++) {
+ if (setup[idx].disable)
+ continue;
+ if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (! (f_mode & FMODE_WRITE))
+ continue;
+ } else {
+ if (! (f_mode & FMODE_READ))
+ continue;
+ }
+ err = snd_pcm_open_substream(pcm, idx, file, &substream);
+ if (err < 0) {
snd_pcm_oss_release_file(pcm_oss_file);
return err;
}
- pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
- }
- if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
- if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &csubstream)) < 0) {
- if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- } else {
- csubstream = NULL;
- }
- }
- pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
+
+ pcm_oss_file->streams[idx] = substream;
+ substream->file = pcm_oss_file;
+ snd_pcm_oss_init_substream(substream, &setup[idx], minor);
}
- if (psubstream == NULL && csubstream == NULL) {
+ if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
snd_pcm_oss_release_file(pcm_oss_file);
return -EINVAL;
}
- if (psubstream != NULL) {
- psubstream->oss.file = pcm_oss_file;
- err = snd_pcm_hw_constraints_init(psubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_init failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- if ((err = psubstream->ops->open(psubstream)) < 0) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- psubstream->ffile = file;
- err = snd_pcm_hw_constraints_complete(psubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_complete failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- snd_pcm_oss_init_substream(psubstream, psetup, minor);
- }
- if (csubstream != NULL) {
- csubstream->oss.file = pcm_oss_file;
- err = snd_pcm_hw_constraints_init(csubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_init failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- if ((err = csubstream->ops->open(csubstream)) < 0) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- csubstream->ffile = file;
- err = snd_pcm_hw_constraints_complete(csubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_complete failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- snd_pcm_oss_init_substream(csubstream, csetup, minor);
- }
file->private_data = pcm_oss_file;
*rpcm_oss_file = pcm_oss_file;
@@ -1852,7 +1789,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
char task_name[32];
struct snd_pcm *pcm;
struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
+ struct snd_pcm_oss_setup setup[2];
int nonblock;
wait_queue_t wait;
@@ -1873,23 +1810,15 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
err = -EFAULT;
goto __error;
}
+ memset(setup, 0, sizeof(setup));
if (file->f_mode & FMODE_WRITE)
- psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
+ snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ task_name, &setup[0]);
if (file->f_mode & FMODE_READ)
- csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
+ snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ task_name, &setup[1]);
nonblock = !!(file->f_flags & O_NONBLOCK);
- if (psetup && !psetup->disable) {
- if (psetup->nonblock)
- nonblock = 1;
- else if (psetup->block)
- nonblock = 0;
- } else if (csetup && !csetup->disable) {
- if (csetup->nonblock)
- nonblock = 1;
- else if (csetup->block)
- nonblock = 0;
- }
if (!nonblock)
nonblock = nonblock_open;
@@ -1898,7 +1827,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
mutex_lock(&pcm->open_mutex);
while (1) {
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
- iminor(inode), psetup, csetup);
+ iminor(inode), setup);
if (err >= 0)
break;
if (err == -EAGAIN) {
@@ -2312,13 +2241,8 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
{
- unsigned int idx;
- struct snd_pcm_substream *substream;
struct snd_pcm_oss_setup *setup, *setupn;
- for (idx = 0, substream = pstr->substream;
- idx < pstr->substream_count; idx++, substream = substream->next)
- substream->oss.setup = NULL;
for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
setup; setup = setupn) {
setupn = setup->next;
@@ -2379,21 +2303,28 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
}
} while (*str);
if (setup == NULL) {
- setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL);
- if (setup) {
- if (pstr->oss.setup_list == NULL) {
- pstr->oss.setup_list = setup;
- } else {
- for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
- setup1->next = setup;
- }
- template.task_name = kstrdup(task_name, GFP_KERNEL);
- } else {
+ setup = kmalloc(sizeof(*setup), GFP_KERNEL);
+ if (! setup) {
+ buffer->error = -ENOMEM;
+ mutex_lock(&pstr->oss.setup_mutex);
+ return;
+ }
+ if (pstr->oss.setup_list == NULL)
+ pstr->oss.setup_list = setup;
+ else {
+ for (setup1 = pstr->oss.setup_list;
+ setup1->next; setup1 = setup1->next);
+ setup1->next = setup;
+ }
+ template.task_name = kstrdup(task_name, GFP_KERNEL);
+ if (! template.task_name) {
+ kfree(setup);
buffer->error = -ENOMEM;
+ mutex_lock(&pstr->oss.setup_mutex);
+ return;
}
}
- if (setup)
- *setup = template;
+ *setup = template;
mutex_unlock(&pstr->oss.setup_mutex);
}
}
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 3da6a38c2d0f..122e10a61ab9 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -196,7 +196,7 @@ static char *snd_pcm_format_names[] = {
FORMAT(U18_3BE),
};
-const char *snd_pcm_format_name(snd_pcm_format_t format)
+static const char *snd_pcm_format_name(snd_pcm_format_t format)
{
return snd_pcm_format_names[format];
}
@@ -777,8 +777,9 @@ static void snd_pcm_tick_timer_func(unsigned long data)
snd_pcm_tick_elapsed(substream);
}
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
- struct snd_pcm_substream **rsubstream)
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
+ struct file *file,
+ struct snd_pcm_substream **rsubstream)
{
struct snd_pcm_str * pstr;
struct snd_pcm_substream *substream;
@@ -793,7 +794,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
*rsubstream = NULL;
snd_assert(pcm != NULL, return -ENXIO);
pstr = &pcm->streams[stream];
- if (pstr->substream == NULL)
+ if (pstr->substream == NULL || pstr->substream_count == 0)
return -ENODEV;
card = pcm->card;
@@ -807,8 +808,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
}
up_read(&card->controls_rwsem);
- if (pstr->substream_count == 0)
- return -ENODEV;
switch (stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
@@ -874,12 +873,13 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
substream->runtime = runtime;
substream->private_data = pcm->private_data;
+ substream->ffile = file;
pstr->substream_opened++;
*rsubstream = substream;
return 0;
}
-void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
substream->file = NULL;
@@ -1111,8 +1111,6 @@ EXPORT_SYMBOL(snd_pcm_link_rwlock);
EXPORT_SYMBOL(snd_pcm_suspend);
EXPORT_SYMBOL(snd_pcm_suspend_all);
#endif
-EXPORT_SYMBOL(snd_pcm_kernel_playback_ioctl);
-EXPORT_SYMBOL(snd_pcm_kernel_capture_ioctl);
EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
EXPORT_SYMBOL(snd_pcm_mmap_data);
#if SNDRV_PCM_INFO_MMAP_IOMEM
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eeba2f060955..230a940d00bd 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2299,19 +2299,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
runtime->channels > 1)
@@ -2374,19 +2362,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
return -EINVAL;
@@ -2596,19 +2572,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
return -EINVAL;
return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
@@ -2665,20 +2629,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
-
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
return -EINVAL;
return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 01f150f0990e..0860c5a84502 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1170,7 +1170,7 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
int res;
snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
+ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
snd_power_unlock(card);
return res;
@@ -1198,7 +1198,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0)
goto _unlock;
}
@@ -1313,13 +1313,13 @@ static struct action_ops snd_pcm_action_prepare = {
*
* Prepare the PCM substream to be triggerable.
*/
-int snd_pcm_prepare(struct snd_pcm_substream *substream)
+static int snd_pcm_prepare(struct snd_pcm_substream *substream)
{
int res;
struct snd_card *card = substream->pcm->card;
snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
+ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
snd_power_unlock(card);
return res;
@@ -1410,7 +1410,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0) {
snd_power_unlock(card);
return result;
@@ -1533,7 +1533,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0)
goto _unlock;
}
@@ -1995,28 +1995,65 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str,
}
}
-static int snd_pcm_release_file(struct snd_pcm_file * pcm_file)
+static void pcm_release_private(struct snd_pcm_substream *substream)
{
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- struct snd_pcm_str * str;
+ struct snd_pcm_file *pcm_file = substream->file;
- snd_assert(pcm_file != NULL, return -ENXIO);
- substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
- runtime = substream->runtime;
- str = substream->pstr;
snd_pcm_unlink(substream);
- if (substream->ffile != NULL) {
+ snd_pcm_remove_file(substream->pstr, pcm_file);
+ kfree(pcm_file);
+}
+
+void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+{
+ snd_pcm_drop(substream);
+ if (substream->hw_opened) {
if (substream->ops->hw_free != NULL)
substream->ops->hw_free(substream);
substream->ops->close(substream);
- substream->ffile = NULL;
+ substream->hw_opened = 0;
}
- snd_pcm_remove_file(str, pcm_file);
- snd_pcm_release_substream(substream);
- kfree(pcm_file);
+ if (substream->pcm_release) {
+ substream->pcm_release(substream);
+ substream->pcm_release = NULL;
+ }
+ snd_pcm_detach_substream(substream);
+}
+
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+ struct file *file,
+ struct snd_pcm_substream **rsubstream)
+{
+ struct snd_pcm_substream *substream;
+ int err;
+
+ err = snd_pcm_attach_substream(pcm, stream, file, &substream);
+ if (err < 0)
+ return err;
+ substream->no_mmap_ctrl = 0;
+ err = snd_pcm_hw_constraints_init(substream);
+ if (err < 0) {
+ snd_printd("snd_pcm_hw_constraints_init failed\n");
+ goto error;
+ }
+
+ if ((err = substream->ops->open(substream)) < 0)
+ goto error;
+
+ substream->hw_opened = 1;
+
+ err = snd_pcm_hw_constraints_complete(substream);
+ if (err < 0) {
+ snd_printd("snd_pcm_hw_constraints_complete failed\n");
+ goto error;
+ }
+
+ *rsubstream = substream;
return 0;
+
+ error:
+ snd_pcm_release_substream(substream);
+ return err;
}
static int snd_pcm_open_file(struct file *file,
@@ -2024,52 +2061,29 @@ static int snd_pcm_open_file(struct file *file,
int stream,
struct snd_pcm_file **rpcm_file)
{
- int err = 0;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_str *str;
+ int err;
snd_assert(rpcm_file != NULL, return -EINVAL);
*rpcm_file = NULL;
+ err = snd_pcm_open_substream(pcm, stream, file, &substream);
+ if (err < 0)
+ return err;
+
pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
if (pcm_file == NULL) {
+ snd_pcm_release_substream(substream);
return -ENOMEM;
}
-
- if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
- kfree(pcm_file);
- return err;
- }
-
str = substream->pstr;
substream->file = pcm_file;
- substream->no_mmap_ctrl = 0;
-
+ substream->pcm_release = pcm_release_private;
pcm_file->substream = substream;
-
snd_pcm_add_file(str, pcm_file);
- err = snd_pcm_hw_constraints_init(substream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_init failed\n");
- snd_pcm_release_file(pcm_file);
- return err;
- }
-
- if ((err = substream->ops->open(substream)) < 0) {
- snd_pcm_release_file(pcm_file);
- return err;
- }
- substream->ffile = file;
-
- err = snd_pcm_hw_constraints_complete(substream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_complete failed\n");
- snd_pcm_release_file(pcm_file);
- return err;
- }
-
file->private_data = pcm_file;
*rpcm_file = pcm_file;
return 0;
@@ -2158,10 +2172,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO);
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
pcm = substream->pcm;
- snd_pcm_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync);
mutex_lock(&pcm->open_mutex);
- snd_pcm_release_file(pcm_file);
+ snd_pcm_release_substream(substream);
mutex_unlock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
module_put(pcm->card->module);
@@ -2480,11 +2493,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
return 0;
}
-static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg);
-static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg);
-
static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
@@ -2736,41 +2744,28 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
-int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- mm_segment_t fs;
- int result;
-
- fs = snd_enter_user();
- result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
- snd_leave_user(fs);
- return result;
-}
-
-int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
+int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
{
mm_segment_t fs;
int result;
fs = snd_enter_user();
- result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
- snd_leave_user(fs);
- return result;
-}
-
-int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
switch (substream->stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
- return snd_pcm_kernel_playback_ioctl(substream, cmd, arg);
+ result = snd_pcm_playback_ioctl1(substream,
+ cmd, (void __user *)arg);
+ break;
case SNDRV_PCM_STREAM_CAPTURE:
- return snd_pcm_kernel_capture_ioctl(substream, cmd, arg);
+ result = snd_pcm_capture_ioctl1(substream,
+ cmd, (void __user *)arg);
+ break;
default:
- return -EINVAL;
+ result = -EINVAL;
+ break;
}
+ snd_leave_user(fs);
+ return result;
}
static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 8687ae3c66b8..b49a45cbf67a 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -183,7 +183,8 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
*/
-static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
+static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
+ int ack)
{
unsigned long flags;
int timeout, ok;
@@ -218,9 +219,11 @@ static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int
ok = 1;
}
spin_unlock_irqrestore(&mpu->input_lock, flags);
- if (! ok)
+ if (!ok) {
snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
- // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
+ return 1;
+ }
+ return 0;
}
/*
@@ -235,12 +238,19 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
return err;
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
- snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+ if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+ goto error_out;
+ if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+ goto error_out;
}
mpu->substream_input = substream;
set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
return 0;
+
+error_out:
+ if (mpu->open_input && mpu->close_input)
+ mpu->close_input(mpu);
+ return -EIO;
}
static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
@@ -252,39 +262,52 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
return err;
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
- snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+ if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+ goto error_out;
+ if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+ goto error_out;
}
mpu->substream_output = substream;
set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
return 0;
+
+error_out:
+ if (mpu->open_output && mpu->close_output)
+ mpu->close_output(mpu);
+ return -EIO;
}
static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
{
struct snd_mpu401 *mpu;
+ int err = 0;
mpu = substream->rmidi->private_data;
clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
mpu->substream_input = NULL;
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+ err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
if (mpu->close_input)
mpu->close_input(mpu);
+ if (err)
+ return -EIO;
return 0;
}
static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
{
struct snd_mpu401 *mpu;
+ int err = 0;
mpu = substream->rmidi->private_data;
clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
mpu->substream_output = NULL;
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+ err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
if (mpu->close_output)
mpu->close_output(mpu);
+ if (err)
+ return -EIO;
return 0;
}
@@ -316,6 +339,7 @@ static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substrea
snd_mpu401_uart_remove_timer(mpu, 1);
clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
}
+
}
/*
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ff8fef932786..557c4de22960 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -11,6 +11,15 @@ config SND_CS4231_LIB
tristate
select SND_PCM
+config SND_ADLIB
+ tristate "AdLib FM card"
+ select SND_OPL3_LIB
+ help
+ Say Y here to include support for AdLib FM cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-adlib.
+
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
depends on SND && PNP && ISA
@@ -292,6 +301,20 @@ config SND_OPTI93X
To compile this driver as a module, choose M here: the module
will be called snd-opti93x.
+config SND_MIRO
+ tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
+ depends on SND
+ select SND_OPL4_LIB
+ select SND_CS4231_LIB
+ select SND_MPU401_UART
+ select SND_PCM
+ help
+ Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro,
+ miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-miro.
+
config SND_SB8
tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
depends on SND
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index 05724eb7bfe4..bb317ccc170f 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -3,6 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
+snd-adlib-objs := adlib.o
snd-als100-objs := als100.o
snd-azt2320-objs := azt2320.o
snd-cmi8330-objs := cmi8330.o
@@ -13,6 +14,7 @@ snd-sgalaxy-objs := sgalaxy.o
snd-sscape-objs := sscape.o
# Toplevel Module Dependency
+obj-$(CONFIG_SND_ADLIB) += snd-adlib.o
obj-$(CONFIG_SND_ALS100) += snd-als100.o
obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 326a057f752f..99908e44124d 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -193,9 +193,11 @@ static int __init alsa_card_ad1848_init(void)
continue;
device = platform_device_register_simple(SND_AD1848_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -204,14 +206,10 @@ static int __init alsa_card_ad1848_init(void)
#ifdef MODULE
printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_ad1848_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_ad1848_unregister_all();
- return err;
}
static void __exit alsa_card_ad1848_exit(void)
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
new file mode 100644
index 000000000000..1124344ed948
--- /dev/null
+++ b/sound/isa/adlib.c
@@ -0,0 +1,164 @@
+/*
+ * AdLib FM card driver.
+ */
+
+#include <sound/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/opl3.h>
+
+#define CRD_NAME "AdLib FM"
+#define DRV_NAME "snd_adlib"
+
+MODULE_DESCRIPTION(CRD_NAME);
+MODULE_AUTHOR("Rene Herman");
+MODULE_LICENSE("GPL");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
+module_param_array(port, long, NULL, 0444);
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
+
+static struct platform_device *devices[SNDRV_CARDS];
+
+static void snd_adlib_free(struct snd_card *card)
+{
+ release_and_free_resource(card->private_data);
+}
+
+static int __devinit snd_adlib_probe(struct platform_device *device)
+{
+ struct snd_card *card;
+ struct snd_opl3 *opl3;
+
+ int error, i = device->id;
+
+ if (port[i] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
+ error = -EINVAL;
+ goto out0;
+ }
+
+ card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
+ if (!card) {
+ snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
+ error = -EINVAL;
+ goto out0;
+ }
+
+ card->private_data = request_region(port[i], 4, CRD_NAME);
+ if (!card->private_data) {
+ snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
+ error = -EBUSY;
+ goto out1;
+ }
+ card->private_free = snd_adlib_free;
+
+ error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
+ if (error < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
+ goto out1;
+ }
+
+ error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
+ if (error < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
+ goto out1;
+ }
+
+ strcpy(card->driver, DRV_NAME);
+ strcpy(card->shortname, CRD_NAME);
+ sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
+
+ snd_card_set_dev(card, &device->dev);
+
+ error = snd_card_register(card);
+ if (error < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
+ goto out1;
+ }
+
+ platform_set_drvdata(device, card);
+ return 0;
+
+out1: snd_card_free(card);
+out0: return error;
+}
+
+static int __devexit snd_adlib_remove(struct platform_device *device)
+{
+ snd_card_free(platform_get_drvdata(device));
+ platform_set_drvdata(device, NULL);
+ return 0;
+}
+
+static struct platform_driver snd_adlib_driver = {
+ .probe = snd_adlib_probe,
+ .remove = __devexit_p(snd_adlib_remove),
+
+ .driver = {
+ .name = DRV_NAME
+ }
+};
+
+static int __init alsa_card_adlib_init(void)
+{
+ int i, cards;
+
+ if (platform_driver_register(&snd_adlib_driver) < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
+ return -ENODEV;
+ }
+
+ for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
+ struct platform_device *device;
+
+ if (!enable[i])
+ continue;
+
+ device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
+ if (IS_ERR(device))
+ continue;
+
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
+ }
+
+ devices[i] = device;
+ cards++;
+ }
+
+ if (!cards) {
+#ifdef MODULE
+ printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
+#endif
+ platform_driver_unregister(&snd_adlib_driver);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit alsa_card_adlib_exit(void)
+{
+ int i;
+
+ for (i = 0; i < SNDRV_CARDS; i++)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_adlib_driver);
+}
+
+module_init(alsa_card_adlib_init);
+module_exit(alsa_card_adlib_exit);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index fa63048a8b9d..3c1e9fd56fe0 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -693,15 +693,17 @@ static int __init alsa_card_cmi8330_init(void)
if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
return err;
- for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
- if (is_isapnp_selected(i))
+ if (! enable[i] || is_isapnp_selected(i))
continue;
device = platform_device_register_simple(CMI8330_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
@@ -719,14 +721,10 @@ static int __init alsa_card_cmi8330_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_cmi8330_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_cmi8330_unregister_all();
- return err;
}
static void __exit alsa_card_cmi8330_exit(void)
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index a30dcd962525..397310f358b7 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -209,9 +209,11 @@ static int __init alsa_card_cs4231_init(void)
continue;
device = platform_device_register_simple(SND_CS4231_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -220,14 +222,10 @@ static int __init alsa_card_cs4231_init(void)
#ifdef MODULE
printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_cs4231_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_cs4231_unregister_all();
- return err;
}
static void __exit alsa_card_cs4231_exit(void)
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 382bb17ef49f..f7fa779347ff 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -780,9 +780,11 @@ static int __init alsa_card_cs423x_init(void)
continue;
device = platform_device_register_simple(CS423X_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
snd_cs423x_devices++;
@@ -802,14 +804,10 @@ static int __init alsa_card_cs423x_init(void)
#ifdef MODULE
printk(KERN_ERR IDENT " soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_cs423x_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_cs423x_unregister_all();
- return err;
}
static void __exit alsa_card_cs423x_exit(void)
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 2b69fc829265..e90689ee162f 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -213,9 +213,11 @@ static int __init alsa_card_es1688_init(void)
continue;
device = platform_device_register_simple(ES1688_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -224,14 +226,10 @@ static int __init alsa_card_es1688_init(void)
#ifdef MODULE
printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_es1688_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_es1688_unregister_all();
- return err;
}
static void __exit alsa_card_es1688_exit(void)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 9fbc185b4cc2..a36ec1daa5cb 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -2391,9 +2391,11 @@ static int __init alsa_card_es18xx_init(void)
continue;
device = platform_device_register_simple(ES18XX_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
@@ -2411,14 +2413,10 @@ static int __init alsa_card_es18xx_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_es18xx_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_es18xx_unregister_all();
- return err;
}
static void __exit alsa_card_es18xx_exit(void)
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 26dccfea2437..37057a37dc30 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -253,9 +253,11 @@ static int __init alsa_card_gusclassic_init(void)
continue;
device = platform_device_register_simple(GUSCLASSIC_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -264,14 +266,10 @@ static int __init alsa_card_gusclassic_init(void)
#ifdef MODULE
printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_gusclassic_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_gusclassic_unregister_all();
- return err;
}
static void __exit alsa_card_gusclassic_exit(void)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 31dc20501d0c..05852fcc613b 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -363,9 +363,11 @@ static int __init alsa_card_gusextreme_init(void)
continue;
device = platform_device_register_simple(GUSEXTREME_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -374,14 +376,10 @@ static int __init alsa_card_gusextreme_init(void)
#ifdef MODULE
printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_gusextreme_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_gusextreme_unregister_all();
- return err;
}
static void __exit alsa_card_gusextreme_exit(void)
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index cafb9b67fa72..fcf2c8fe6f94 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -390,9 +390,11 @@ static int __init alsa_card_gusmax_init(void)
continue;
device = platform_device_register_simple(GUSMAX_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -401,14 +403,10 @@ static int __init alsa_card_gusmax_init(void)
#ifdef MODULE
printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_gusmax_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_gusmax_unregister_all();
- return err;
}
static void __exit alsa_card_gusmax_exit(void)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index de71b7a99c83..4298d339e786 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -947,9 +947,11 @@ static int __init alsa_card_interwave_init(void)
#endif
device = platform_device_register_simple(INTERWAVE_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
@@ -966,14 +968,10 @@ static int __init alsa_card_interwave_init(void)
#ifdef MODULE
printk(KERN_ERR "InterWave soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_interwave_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_interwave_unregister_all();
- return err;
}
static void __exit alsa_card_interwave_exit(void)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index c906e205d7d5..6d889052c32c 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -962,9 +962,11 @@ static int __init alsa_card_opl3sa2_init(void)
#endif
device = platform_device_register_simple(OPL3SA2_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
snd_opl3sa2_devices++;
@@ -983,14 +985,10 @@ static int __init alsa_card_opl3sa2_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_opl3sa2_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_opl3sa2_unregister_all();
- return err;
}
static void __exit alsa_card_opl3sa2_exit(void)
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile
index 28c64070cd56..0e41bfd5a403 100644
--- a/sound/isa/opti9xx/Makefile
+++ b/sound/isa/opti9xx/Makefile
@@ -6,8 +6,10 @@
snd-opti92x-ad1848-objs := opti92x-ad1848.o
snd-opti92x-cs4231-objs := opti92x-cs4231.o
snd-opti93x-objs := opti93x.o
+snd-miro-objs := miro.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o
obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o
obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o
+obj-$(CONFIG_SND_MIRO) += snd-miro.o
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
new file mode 100644
index 000000000000..83d64bc07ff0
--- /dev/null
+++ b/sound/isa/opti9xx/miro.c
@@ -0,0 +1,1458 @@
+/*
+ * ALSA soundcard driver for Miro miroSOUND PCM1 pro
+ * miroSOUND PCM12
+ * miroSOUND PCM20 Radio
+ *
+ * Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de>
+ *
+ * Based on OSS ACI and ALSA OPTi9xx drivers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/moduleparam.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/cs4231.h>
+#include <sound/mpu401.h>
+#include <sound/opl4.h>
+#include <sound/control.h>
+#include <sound/info.h>
+#define SNDRV_LEGACY_FIND_FREE_IRQ
+#define SNDRV_LEGACY_FIND_FREE_DMA
+#include <sound/initval.h>
+#include "miro.h"
+
+MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio");
+MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, "
+ "{Miro,miroSOUND PCM12}, "
+ "{Miro,miroSOUND PCM20 Radio}}");
+
+static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
+static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */
+static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */
+static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */
+static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */
+static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */
+static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
+static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
+static int wss;
+static int ide;
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for miro soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for miro soundcard.");
+module_param(port, long, 0444);
+MODULE_PARM_DESC(port, "WSS port # for miro driver.");
+module_param(mpu_port, long, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver.");
+module_param(fm_port, long, 0444);
+MODULE_PARM_DESC(fm_port, "FM Port # for miro driver.");
+module_param(irq, int, 0444);
+MODULE_PARM_DESC(irq, "WSS irq # for miro driver.");
+module_param(mpu_irq, int, 0444);
+MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver.");
+module_param(dma1, int, 0444);
+MODULE_PARM_DESC(dma1, "1st dma # for miro driver.");
+module_param(dma2, int, 0444);
+MODULE_PARM_DESC(dma2, "2nd dma # for miro driver.");
+module_param(wss, int, 0444);
+MODULE_PARM_DESC(wss, "wss mode");
+module_param(ide, int, 0444);
+MODULE_PARM_DESC(ide, "enable ide port");
+
+#define OPTi9XX_HW_DETECT 0
+#define OPTi9XX_HW_82C928 1
+#define OPTi9XX_HW_82C929 2
+#define OPTi9XX_HW_82C924 3
+#define OPTi9XX_HW_82C925 4
+#define OPTi9XX_HW_82C930 5
+#define OPTi9XX_HW_82C931 6
+#define OPTi9XX_HW_82C933 7
+#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933
+
+#define OPTi9XX_MC_REG(n) n
+
+
+struct snd_miro {
+ unsigned short hardware;
+ unsigned char password;
+ char name[7];
+
+ struct resource *res_mc_base;
+ struct resource *res_aci_port;
+
+ unsigned long mc_base;
+ unsigned long mc_base_size;
+ unsigned long pwd_reg;
+
+ spinlock_t lock;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+
+ long wss_base;
+ int irq;
+ int dma1;
+ int dma2;
+
+ long fm_port;
+
+ long mpu_port;
+ int mpu_irq;
+
+ unsigned long aci_port;
+ int aci_vendor;
+ int aci_product;
+ int aci_version;
+ int aci_amp;
+ int aci_preamp;
+ int aci_solomode;
+
+ struct mutex aci_mutex;
+};
+
+static void snd_miro_proc_init(struct snd_miro * miro);
+
+#define DRIVER_NAME "snd-miro"
+
+static struct platform_device *device;
+
+static char * snd_opti9xx_names[] = {
+ "unkown",
+ "82C928", "82C929",
+ "82C924", "82C925",
+ "82C930", "82C931", "82C933"
+};
+
+/*
+ * ACI control
+ */
+
+static int aci_busy_wait(struct snd_miro * miro)
+{
+ long timeout;
+ unsigned char byte;
+
+ for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) {
+ if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) {
+ if (timeout >= ACI_MINTIME)
+ snd_printd("aci ready in round %ld.\n",
+ timeout-ACI_MINTIME);
+ return byte;
+ }
+ if (timeout >= ACI_MINTIME) {
+ long out=10*HZ;
+ switch (timeout-ACI_MINTIME) {
+ case 0 ... 9:
+ out /= 10;
+ case 10 ... 19:
+ out /= 10;
+ case 20 ... 30:
+ out /= 10;
+ default:
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(out);
+ break;
+ }
+ }
+ }
+ snd_printk(KERN_ERR "aci_busy_wait() time out\n");
+ return -EBUSY;
+}
+
+static inline int aci_write(struct snd_miro * miro, unsigned char byte)
+{
+ if (aci_busy_wait(miro) >= 0) {
+ outb(byte, miro->aci_port + ACI_REG_COMMAND);
+ return 0;
+ } else {
+ snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte);
+ return -EBUSY;
+ }
+}
+
+static inline int aci_read(struct snd_miro * miro)
+{
+ unsigned char byte;
+
+ if (aci_busy_wait(miro) >= 0) {
+ byte=inb(miro->aci_port + ACI_REG_STATUS);
+ return byte;
+ } else {
+ snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n");
+ return -EBUSY;
+ }
+}
+
+static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3)
+{
+ int write[] = {write1, write2, write3};
+ int value, i;
+
+ if (mutex_lock_interruptible(&miro->aci_mutex))
+ return -EINTR;
+
+ for (i=0; i<3; i++) {
+ if (write[i]< 0 || write[i] > 255)
+ break;
+ else {
+ value = aci_write(miro, write[i]);
+ if (value < 0)
+ goto out;
+ }
+ }
+
+ value = aci_read(miro);
+
+out: mutex_unlock(&miro->aci_mutex);
+ return value;
+}
+
+static int aci_getvalue(struct snd_miro * miro, unsigned char index)
+{
+ return aci_cmd(miro, ACI_STATUS, index, -1);
+}
+
+static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value)
+{
+ return aci_cmd(miro, index, value, -1);
+}
+
+/*
+ * MIXER part
+ */
+
+static int snd_miro_info_capture(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int value;
+
+ if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value);
+ return value;
+ }
+
+ ucontrol->value.integer.value[0] = value & 0x20;
+
+ return 0;
+}
+
+static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int change, value, error;
+
+ value = !(ucontrol->value.integer.value[0]);
+
+ if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error);
+ return error;
+ }
+
+ change = (value != miro->aci_solomode);
+ miro->aci_solomode = value;
+
+ return change;
+}
+
+static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 3;
+
+ return 0;
+}
+
+static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int value;
+
+ if (miro->aci_version <= 176) {
+
+ /*
+ OSS says it's not readable with versions < 176.
+ But it doesn't work on my card,
+ which is a PCM12 with aci_version = 176.
+ */
+
+ ucontrol->value.integer.value[0] = miro->aci_preamp;
+ return 0;
+ }
+
+ if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value);
+ return value;
+ }
+
+ ucontrol->value.integer.value[0] = value;
+
+ return 0;
+}
+
+static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int error, value, change;
+
+ value = ucontrol->value.integer.value[0];
+
+ if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error);
+ return error;
+ }
+
+ change = (value != miro->aci_preamp);
+ miro->aci_preamp = value;
+
+ return change;
+}
+
+static int snd_miro_info_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = miro->aci_amp;
+
+ return 0;
+}
+
+static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int error, value, change;
+
+ value = ucontrol->value.integer.value[0];
+
+ if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error);
+ return error;
+ }
+
+ change = (value != miro->aci_amp);
+ miro->aci_amp = value;
+
+ return change;
+}
+
+#define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = ctl_name, \
+ .index = ctl_index, \
+ .info = snd_miro_info_double, \
+ .get = snd_miro_get_double, \
+ .put = snd_miro_put_double, \
+ .private_value = get_right_reg | (set_right_reg << 8) \
+}
+
+static int snd_miro_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int reg = kcontrol->private_value & 0xff;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+
+ if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) {
+
+ /* equalizer elements */
+
+ uinfo->value.integer.min = - 0x7f;
+ uinfo->value.integer.max = 0x7f;
+ } else {
+
+ /* non-equalizer elements */
+
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0x20;
+ }
+
+ return 0;
+}
+
+static int snd_miro_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uinfo)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int left_val, right_val;
+
+ int right_reg = kcontrol->private_value & 0xff;
+ int left_reg = right_reg + 1;
+
+ if ((right_val = aci_getvalue(miro, right_reg)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val);
+ return right_val;
+ }
+
+ if ((left_val = aci_getvalue(miro, left_reg)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val);
+ return left_val;
+ }
+
+ if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) {
+
+ /* equalizer elements */
+
+ if (left_val < 0x80) {
+ uinfo->value.integer.value[0] = left_val;
+ } else {
+ uinfo->value.integer.value[0] = 0x80 - left_val;
+ }
+
+ if (right_val < 0x80) {
+ uinfo->value.integer.value[1] = right_val;
+ } else {
+ uinfo->value.integer.value[1] = 0x80 - right_val;
+ }
+
+ } else {
+
+ /* non-equalizer elements */
+
+ uinfo->value.integer.value[0] = 0x20 - left_val;
+ uinfo->value.integer.value[1] = 0x20 - right_val;
+ }
+
+ return 0;
+}
+
+static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int left, right, left_old, right_old;
+ int setreg_left, setreg_right, getreg_left, getreg_right;
+ int change, error;
+
+ left = ucontrol->value.integer.value[0];
+ right = ucontrol->value.integer.value[1];
+
+ setreg_right = (kcontrol->private_value >> 8) & 0xff;
+ if (setreg_right == ACI_SET_MASTER) {
+ setreg_left = setreg_right + 1;
+ } else {
+ setreg_left = setreg_right + 8;
+ }
+
+ getreg_right = kcontrol->private_value & 0xff;
+ getreg_left = getreg_right + 1;
+
+ if ((left_old = aci_getvalue(miro, getreg_left)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old);
+ return left_old;
+ }
+
+ if ((right_old = aci_getvalue(miro, getreg_right)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old);
+ return right_old;
+ }
+
+ if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) {
+
+ /* equalizer elements */
+
+ if (left_old > 0x80)
+ left_old = 0x80 - left_old;
+ if (right_old > 0x80)
+ right_old = 0x80 - right_old;
+
+ if (left >= 0) {
+ if ((error = aci_setvalue(miro, setreg_left, left)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ left, error);
+ return error;
+ }
+ } else {
+ if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x80 - left, error);
+ return error;
+ }
+ }
+
+ if (right >= 0) {
+ if ((error = aci_setvalue(miro, setreg_right, right)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ right, error);
+ return error;
+ }
+ } else {
+ if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x80 - right, error);
+ return error;
+ }
+ }
+
+ } else {
+
+ /* non-equalizer elements */
+
+ left_old = 0x20 - left_old;
+ right_old = 0x20 - right_old;
+
+ if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x20 - left, error);
+ return error;
+ }
+ if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x20 - right, error);
+ return error;
+ }
+ }
+
+ change = (left != left_old) || (right != right_old);
+
+ return change;
+}
+
+static struct snd_kcontrol_new snd_miro_controls[] = {
+MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
+MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
+MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
+MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD),
+MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH),
+MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM),
+MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
+};
+
+/* Equalizer with seven bands (only PCM20)
+ from -12dB up to +12dB on each band */
+static struct snd_kcontrol_new snd_miro_eq_controls[] = {
+MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
+MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
+MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
+MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4),
+MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5),
+MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
+MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
+};
+
+static struct snd_kcontrol_new snd_miro_radio_control[] = {
+MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
+};
+
+static struct snd_kcontrol_new snd_miro_line_control[] = {
+MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
+};
+
+static struct snd_kcontrol_new snd_miro_preamp_control[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Boost",
+ .index = 1,
+ .info = snd_miro_info_preamp,
+ .get = snd_miro_get_preamp,
+ .put = snd_miro_put_preamp,
+}};
+
+static struct snd_kcontrol_new snd_miro_amp_control[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line Boost",
+ .index = 0,
+ .info = snd_miro_info_amp,
+ .get = snd_miro_get_amp,
+ .put = snd_miro_put_amp,
+}};
+
+static struct snd_kcontrol_new snd_miro_capture_control[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Capture Switch",
+ .index = 0,
+ .info = snd_miro_info_capture,
+ .get = snd_miro_get_capture,
+ .put = snd_miro_put_capture,
+}};
+
+static unsigned char aci_init_values[][2] __initdata = {
+ { ACI_SET_MUTE, 0x00 },
+ { ACI_SET_POWERAMP, 0x00 },
+ { ACI_SET_PREAMP, 0x00 },
+ { ACI_SET_SOLOMODE, 0x00 },
+ { ACI_SET_MIC + 0, 0x20 },
+ { ACI_SET_MIC + 8, 0x20 },
+ { ACI_SET_LINE + 0, 0x20 },
+ { ACI_SET_LINE + 8, 0x20 },
+ { ACI_SET_CD + 0, 0x20 },
+ { ACI_SET_CD + 8, 0x20 },
+ { ACI_SET_PCM + 0, 0x20 },
+ { ACI_SET_PCM + 8, 0x20 },
+ { ACI_SET_LINE1 + 0, 0x20 },
+ { ACI_SET_LINE1 + 8, 0x20 },
+ { ACI_SET_LINE2 + 0, 0x20 },
+ { ACI_SET_LINE2 + 8, 0x20 },
+ { ACI_SET_SYNTH + 0, 0x20 },
+ { ACI_SET_SYNTH + 8, 0x20 },
+ { ACI_SET_MASTER + 0, 0x20 },
+ { ACI_SET_MASTER + 1, 0x20 },
+};
+
+static int __init snd_set_aci_init_values(struct snd_miro *miro)
+{
+ int idx, error;
+
+ /* enable WSS on PCM1 */
+
+ if ((miro->aci_product == 'A') && wss) {
+ if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) {
+ snd_printk(KERN_ERR "enabling WSS mode failed\n");
+ return error;
+ }
+ }
+
+ /* enable IDE port */
+
+ if (ide) {
+ if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) {
+ snd_printk(KERN_ERR "enabling IDE port failed\n");
+ return error;
+ }
+ }
+
+ /* set common aci values */
+
+ for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++)
+ if ((error = aci_setvalue(miro, aci_init_values[idx][0],
+ aci_init_values[idx][1])) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ aci_init_values[idx][0], error);
+ return error;
+ }
+
+ miro->aci_amp = 0;
+ miro->aci_preamp = 0;
+ miro->aci_solomode = 1;
+
+ return 0;
+}
+
+static int snd_miro_mixer(struct snd_miro *miro)
+{
+ struct snd_card *card;
+ unsigned int idx;
+ int err;
+
+ snd_assert(miro != NULL && miro->card != NULL, return -EINVAL);
+
+ card = miro->card;
+
+ switch (miro->hardware) {
+ case OPTi9XX_HW_82C924:
+ strcpy(card->mixername, "ACI & OPTi924");
+ break;
+ case OPTi9XX_HW_82C929:
+ strcpy(card->mixername, "ACI & OPTi929");
+ break;
+ default:
+ snd_BUG();
+ break;
+ }
+
+ for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) {
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0)
+ return err;
+ }
+
+ if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) {
+ /* PCM1/PCM12 with power-amp and Line 2 */
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0)
+ return err;
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0)
+ return err;
+ }
+
+ if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) {
+ /* PCM12/PCM20 with mic-preamp */
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0)
+ return err;
+ if (miro->aci_version >= 176)
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0)
+ return err;
+ }
+
+ if (miro->aci_product == 'C') {
+ /* PCM20 with radio and 7 band equalizer */
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0)
+ return err;
+ for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) {
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static long snd_legacy_find_free_ioport(long *port_table, long size)
+{
+ while (*port_table != -1) {
+ struct resource *res;
+ if ((res = request_region(*port_table, size,
+ "ALSA test")) != NULL) {
+ release_and_free_resource(res);
+ return *port_table;
+ }
+ port_table++;
+ }
+ return -1;
+}
+
+static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware)
+{
+ static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+
+ chip->hardware = hardware;
+ strcpy(chip->name, snd_opti9xx_names[hardware]);
+
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+
+ spin_lock_init(&chip->lock);
+
+ chip->wss_base = -1;
+ chip->irq = -1;
+ chip->dma1 = -1;
+ chip->dma2 = -1;
+ chip->fm_port = -1;
+ chip->mpu_port = -1;
+ chip->mpu_irq = -1;
+
+ switch (hardware) {
+ case OPTi9XX_HW_82C929:
+ chip->mc_base = 0xf8c;
+ chip->password = 0xe3;
+ chip->pwd_reg = 3;
+ break;
+
+ case OPTi9XX_HW_82C924:
+ chip->mc_base = 0xf8c;
+ chip->password = 0xe5;
+ chip->pwd_reg = 3;
+ break;
+
+ default:
+ snd_printk(KERN_ERR "sorry, no support for %d\n", hardware);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static unsigned char snd_miro_read(struct snd_miro *chip,
+ unsigned char reg)
+{
+ unsigned long flags;
+ unsigned char retval = 0xff;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+
+ switch (chip->hardware) {
+ case OPTi9XX_HW_82C924:
+ if (reg > 7) {
+ outb(reg, chip->mc_base + 8);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+ retval = inb(chip->mc_base + 9);
+ break;
+ }
+
+ case OPTi9XX_HW_82C929:
+ retval = inb(chip->mc_base + reg);
+ break;
+
+ default:
+ snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
+ }
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return retval;
+}
+
+static void snd_miro_write(struct snd_miro *chip, unsigned char reg,
+ unsigned char value)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+
+ switch (chip->hardware) {
+ case OPTi9XX_HW_82C924:
+ if (reg > 7) {
+ outb(reg, chip->mc_base + 8);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+ outb(value, chip->mc_base + 9);
+ break;
+ }
+
+ case OPTi9XX_HW_82C929:
+ outb(value, chip->mc_base + reg);
+ break;
+
+ default:
+ snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
+ }
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+
+#define snd_miro_write_mask(chip, reg, value, mask) \
+ snd_miro_write(chip, reg, \
+ (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask)))
+
+/*
+ * Proc Interface
+ */
+
+static void snd_miro_proc_read(struct snd_info_entry * entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_miro *miro = (struct snd_miro *) entry->private_data;
+ char* model = "unknown";
+
+ /* miroSOUND PCM1 pro, early PCM12 */
+
+ if ((miro->hardware == OPTi9XX_HW_82C929) &&
+ (miro->aci_vendor == 'm') &&
+ (miro->aci_product == 'A')) {
+ switch(miro->aci_version) {
+ case 3:
+ model = "miroSOUND PCM1 pro";
+ break;
+ default:
+ model = "miroSOUND PCM1 pro / (early) PCM12";
+ break;
+ }
+ }
+
+ /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
+
+ if ((miro->hardware == OPTi9XX_HW_82C924) &&
+ (miro->aci_vendor == 'm') &&
+ (miro->aci_product == 'B')) {
+ switch(miro->aci_version) {
+ case 4:
+ model = "miroSOUND PCM12";
+ break;
+ case 176:
+ model = "miroSOUND PCM12 (Rev. E)";
+ break;
+ default:
+ model = "miroSOUND PCM12 / PCM12 pnp";
+ break;
+ }
+ }
+
+ /* miroSOUND PCM20 radio */
+
+ if ((miro->hardware == OPTi9XX_HW_82C924) &&
+ (miro->aci_vendor == 'm') &&
+ (miro->aci_product == 'C')) {
+ switch(miro->aci_version) {
+ case 7:
+ model = "miroSOUND PCM20 radio (Rev. E)";
+ break;
+ default:
+ model = "miroSOUND PCM20 radio";
+ break;
+ }
+ }
+
+ snd_iprintf(buffer, "\nGeneral information:\n");
+ snd_iprintf(buffer, " model : %s\n", model);
+ snd_iprintf(buffer, " opti : %s\n", miro->name);
+ snd_iprintf(buffer, " codec : %s\n", miro->pcm->name);
+ snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base);
+ snd_iprintf(buffer, " irq : %d\n", miro->irq);
+ snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2);
+
+ snd_iprintf(buffer, "MPU-401:\n");
+ snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port);
+ snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq);
+
+ snd_iprintf(buffer, "ACI information:\n");
+ snd_iprintf(buffer, " vendor : ");
+ switch(miro->aci_vendor) {
+ case 'm':
+ snd_iprintf(buffer, "Miro\n");
+ break;
+ default:
+ snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor);
+ break;
+ }
+
+ snd_iprintf(buffer, " product : ");
+ switch(miro->aci_product) {
+ case 'A':
+ snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
+ break;
+ case 'B':
+ snd_iprintf(buffer, "miroSOUND PCM12\n");
+ break;
+ case 'C':
+ snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
+ break;
+ default:
+ snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product);
+ break;
+ }
+
+ snd_iprintf(buffer, " firmware: %d (0x%x)\n",
+ miro->aci_version, miro->aci_version);
+ snd_iprintf(buffer, " port : 0x%lx-0x%lx\n",
+ miro->aci_port, miro->aci_port+2);
+ snd_iprintf(buffer, " wss : 0x%x\n", wss);
+ snd_iprintf(buffer, " ide : 0x%x\n", ide);
+ snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode);
+ snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp);
+ snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp);
+}
+
+static void __init snd_miro_proc_init(struct snd_miro * miro)
+{
+ struct snd_info_entry *entry;
+
+ if (! snd_card_proc_new(miro->card, "miro", &entry))
+ snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read);
+}
+
+/*
+ * Init
+ */
+
+static int __init snd_miro_configure(struct snd_miro *chip)
+{
+ unsigned char wss_base_bits;
+ unsigned char irq_bits;
+ unsigned char dma_bits;
+ unsigned char mpu_port_bits = 0;
+ unsigned char mpu_irq_bits;
+ unsigned long flags;
+
+ switch (chip->hardware) {
+ case OPTi9XX_HW_82C924:
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
+ break;
+ case OPTi9XX_HW_82C929:
+ /* untested init commands for OPTi929 */
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
+ break;
+ default:
+ snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
+ return -EINVAL;
+ }
+
+ switch (chip->wss_base) {
+ case 0x530:
+ wss_base_bits = 0x00;
+ break;
+ case 0x604:
+ wss_base_bits = 0x03;
+ break;
+ case 0xe80:
+ wss_base_bits = 0x01;
+ break;
+ case 0xf40:
+ wss_base_bits = 0x02;
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base);
+ goto __skip_base;
+ }
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
+
+__skip_base:
+ switch (chip->irq) {
+ case 5:
+ irq_bits = 0x05;
+ break;
+ case 7:
+ irq_bits = 0x01;
+ break;
+ case 9:
+ irq_bits = 0x02;
+ break;
+ case 10:
+ irq_bits = 0x03;
+ break;
+ case 11:
+ irq_bits = 0x04;
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq);
+ goto __skip_resources;
+ }
+
+ switch (chip->dma1) {
+ case 0:
+ dma_bits = 0x01;
+ break;
+ case 1:
+ dma_bits = 0x02;
+ break;
+ case 3:
+ dma_bits = 0x03;
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1);
+ goto __skip_resources;
+ }
+
+ if (chip->dma1 == chip->dma2) {
+ snd_printk(KERN_ERR "don't want to share dmas\n");
+ return -EBUSY;
+ }
+
+ switch (chip->dma2) {
+ case 0:
+ case 1:
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2);
+ goto __skip_resources;
+ }
+ dma_bits |= 0x04;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ outb(irq_bits << 3 | dma_bits, chip->wss_base);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+__skip_resources:
+ if (chip->hardware > OPTi9XX_HW_82C928) {
+ switch (chip->mpu_port) {
+ case 0:
+ case -1:
+ break;
+ case 0x300:
+ mpu_port_bits = 0x03;
+ break;
+ case 0x310:
+ mpu_port_bits = 0x02;
+ break;
+ case 0x320:
+ mpu_port_bits = 0x01;
+ break;
+ case 0x330:
+ mpu_port_bits = 0x00;
+ break;
+ default:
+ snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n",
+ chip->mpu_port);
+ goto __skip_mpu;
+ }
+
+ switch (chip->mpu_irq) {
+ case 5:
+ mpu_irq_bits = 0x02;
+ break;
+ case 7:
+ mpu_irq_bits = 0x03;
+ break;
+ case 9:
+ mpu_irq_bits = 0x00;
+ break;
+ case 10:
+ mpu_irq_bits = 0x01;
+ break;
+ default:
+ snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n",
+ chip->mpu_irq);
+ goto __skip_mpu;
+ }
+
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(6),
+ (chip->mpu_port <= 0) ? 0x00 :
+ 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
+ 0xf8);
+ }
+__skip_mpu:
+
+ return 0;
+}
+
+static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip)
+{
+ int i, err;
+ unsigned char value;
+
+ for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) {
+
+ if ((err = snd_miro_init(chip, i)) < 0)
+ return err;
+
+ if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
+ continue;
+
+ value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
+ if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
+ if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
+ return 1;
+
+ release_and_free_resource(chip->res_mc_base);
+ chip->res_mc_base = NULL;
+
+ }
+
+ return -ENODEV;
+}
+
+static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro)
+{
+ unsigned char regval;
+ int i;
+
+ mutex_init(&miro->aci_mutex);
+
+ /* get ACI port from OPTi9xx MC 4 */
+
+ miro->mc_base = 0xf8c;
+ regval=inb(miro->mc_base + 4);
+ miro->aci_port = (regval & 0x10) ? 0x344: 0x354;
+
+ if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) {
+ snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
+ miro->aci_port, miro->aci_port+2);
+ return -ENOMEM;
+ }
+
+ /* force ACI into a known state */
+ for (i = 0; i < 3; i++)
+ if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "can't force aci into known state.\n");
+ return -ENXIO;
+ }
+
+ if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 ||
+ (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port);
+ return -ENXIO;
+ }
+
+ if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
+ miro->aci_port);
+ return -ENXIO;
+ }
+
+ if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 ||
+ aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
+ aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
+ snd_printk(KERN_ERR "can't initialize aci.\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void snd_card_miro_free(struct snd_card *card)
+{
+ struct snd_miro *miro = card->private_data;
+
+ release_and_free_resource(miro->res_aci_port);
+ release_and_free_resource(miro->res_mc_base);
+}
+
+static int __init snd_miro_probe(struct platform_device *devptr)
+{
+ static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+ static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
+ static int possible_irqs[] = {11, 9, 10, 7, -1};
+ static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
+ static int possible_dma1s[] = {3, 1, 0, -1};
+ static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
+
+ int error;
+ struct snd_miro *miro;
+ struct snd_cs4231 *codec;
+ struct snd_timer *timer;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_rawmidi *rmidi;
+
+ if (!(card = snd_card_new(index, id, THIS_MODULE,
+ sizeof(struct snd_miro))))
+ return -ENOMEM;
+
+ card->private_free = snd_card_miro_free;
+ miro = card->private_data;
+ miro->card = card;
+
+ if ((error = snd_card_miro_aci_detect(card, miro)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to detect aci chip\n");
+ return -ENODEV;
+ }
+
+ /* init proc interface */
+ snd_miro_proc_init(miro);
+
+ if ((error = snd_card_miro_detect(card, miro)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
+ return -ENODEV;
+ }
+
+ if (! miro->res_mc_base &&
+ (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size,
+ "miro (OPTi9xx MC)")) == NULL) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
+ return -ENOMEM;
+ }
+
+ miro->wss_base = port;
+ miro->fm_port = fm_port;
+ miro->mpu_port = mpu_port;
+ miro->irq = irq;
+ miro->mpu_irq = mpu_irq;
+ miro->dma1 = dma1;
+ miro->dma2 = dma2;
+
+ if (miro->wss_base == SNDRV_AUTO_PORT) {
+ if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free WSS port\n");
+ return -EBUSY;
+ }
+ }
+
+ if (miro->mpu_port == SNDRV_AUTO_PORT) {
+ if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->irq == SNDRV_AUTO_IRQ) {
+ if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->mpu_irq == SNDRV_AUTO_IRQ) {
+ if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->dma1 == SNDRV_AUTO_DMA) {
+ if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free DMA1\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->dma2 == SNDRV_AUTO_DMA) {
+ if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free DMA2\n");
+ return -EBUSY;
+ }
+ }
+
+ if ((error = snd_miro_configure(miro))) {
+ snd_card_free(card);
+ return error;
+ }
+
+ if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1,
+ miro->irq, miro->dma1, miro->dma2,
+ CS4231_HW_AD1845,
+ 0,
+ &codec)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+ if ((error = snd_cs4231_mixer(codec)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+ if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ miro->pcm = pcm;
+
+ if ((error = snd_miro_mixer(miro)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ if (miro->aci_vendor == 'm') {
+ /* It looks like a miro sound card. */
+ switch (miro->aci_product) {
+ case 'A':
+ sprintf(card->shortname,
+ "miroSOUND PCM1 pro / PCM12");
+ break;
+ case 'B':
+ sprintf(card->shortname,
+ "miroSOUND PCM12");
+ break;
+ case 'C':
+ sprintf(card->shortname,
+ "miroSOUND PCM20 radio");
+ break;
+ default:
+ sprintf(card->shortname,
+ "unknown miro");
+ snd_printk(KERN_INFO "unknown miro aci id\n");
+ break;
+ }
+ } else {
+ snd_printk(KERN_INFO "found unsupported aci card\n");
+ sprintf(card->shortname, "unknown Cardinal Technologies");
+ }
+
+ strcpy(card->driver, "miro");
+ sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
+ card->shortname, miro->name, pcm->name, miro->wss_base + 4,
+ miro->irq, miro->dma1, miro->dma2);
+
+ if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT)
+ rmidi = NULL;
+ else
+ if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+ miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT,
+ &rmidi)))
+ snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port);
+
+ if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) {
+ struct snd_opl3 *opl3 = NULL;
+ struct snd_opl4 *opl4;
+ if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8,
+ 2, &opl3, &opl4) < 0)
+ snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port);
+ }
+
+ if ((error = snd_set_aci_init_values(miro)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ snd_card_set_dev(card, &devptr->dev);
+
+ if ((error = snd_card_register(card))) {
+ snd_card_free(card);
+ return error;
+ }
+
+ platform_set_drvdata(devptr, card);
+ return 0;
+}
+
+static int __devexit snd_miro_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+static struct platform_driver snd_miro_driver = {
+ .probe = snd_miro_probe,
+ .remove = __devexit_p(snd_miro_remove),
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = DRIVER_NAME
+ },
+};
+
+static int __init alsa_card_miro_init(void)
+{
+ int error;
+
+ if ((error = platform_driver_register(&snd_miro_driver)) < 0)
+ return error;
+ device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+ if (! IS_ERR(device)) {
+ if (platform_get_drvdata(device))
+ return 0;
+ platform_device_unregister(device);
+ }
+#ifdef MODULE
+ printk(KERN_ERR "no miro soundcard found\n");
+#endif
+ platform_driver_unregister(&snd_miro_driver);
+ return PTR_ERR(device);
+}
+
+static void __exit alsa_card_miro_exit(void)
+{
+ platform_device_unregister(device);
+ platform_driver_unregister(&snd_miro_driver);
+}
+
+module_init(alsa_card_miro_init)
+module_exit(alsa_card_miro_exit)
diff --git a/sound/isa/opti9xx/miro.h b/sound/isa/opti9xx/miro.h
new file mode 100644
index 000000000000..6e1385b8e07e
--- /dev/null
+++ b/sound/isa/opti9xx/miro.h
@@ -0,0 +1,73 @@
+#ifndef _MIRO_H_
+#define _MIRO_H_
+
+#define ACI_REG_COMMAND 0 /* write register offset */
+#define ACI_REG_STATUS 1 /* read register offset */
+#define ACI_REG_BUSY 2 /* busy register offset */
+#define ACI_REG_RDS 2 /* PCM20: RDS register offset */
+#define ACI_MINTIME 500 /* ACI time out limit */
+
+#define ACI_SET_MUTE 0x0d
+#define ACI_SET_POWERAMP 0x0f
+#define ACI_SET_TUNERMUTE 0xa3
+#define ACI_SET_TUNERMONO 0xa4
+#define ACI_SET_IDE 0xd0
+#define ACI_SET_WSS 0xd1
+#define ACI_SET_SOLOMODE 0xd2
+#define ACI_SET_PREAMP 0x03
+#define ACI_GET_PREAMP 0x21
+#define ACI_WRITE_TUNE 0xa7
+#define ACI_READ_TUNERSTEREO 0xa8
+#define ACI_READ_TUNERSTATION 0xa9
+#define ACI_READ_VERSION 0xf1
+#define ACI_READ_IDCODE 0xf2
+#define ACI_INIT 0xff
+#define ACI_STATUS 0xf0
+#define ACI_S_GENERAL 0x00
+#define ACI_ERROR_OP 0xdf
+
+/* ACI Mixer */
+
+/* These are the values for the right channel GET registers.
+ Add an offset of 0x01 for the left channel register.
+ (left=right+0x01) */
+
+#define ACI_GET_MASTER 0x03
+#define ACI_GET_MIC 0x05
+#define ACI_GET_LINE 0x07
+#define ACI_GET_CD 0x09
+#define ACI_GET_SYNTH 0x0b
+#define ACI_GET_PCM 0x0d
+#define ACI_GET_LINE1 0x10 /* Radio on PCM20 */
+#define ACI_GET_LINE2 0x12
+
+#define ACI_GET_EQ1 0x22 /* from Bass ... */
+#define ACI_GET_EQ2 0x24
+#define ACI_GET_EQ3 0x26
+#define ACI_GET_EQ4 0x28
+#define ACI_GET_EQ5 0x2a
+#define ACI_GET_EQ6 0x2c
+#define ACI_GET_EQ7 0x2e /* ... to Treble */
+
+/* And these are the values for the right channel SET registers.
+ For left channel access you have to add an offset of 0x08.
+ MASTER is an exception, which needs an offset of 0x01 */
+
+#define ACI_SET_MASTER 0x00
+#define ACI_SET_MIC 0x30
+#define ACI_SET_LINE 0x31
+#define ACI_SET_CD 0x34
+#define ACI_SET_SYNTH 0x33
+#define ACI_SET_PCM 0x32
+#define ACI_SET_LINE1 0x35 /* Radio on PCM20 */
+#define ACI_SET_LINE2 0x36
+
+#define ACI_SET_EQ1 0x40 /* from Bass ... */
+#define ACI_SET_EQ2 0x41
+#define ACI_SET_EQ3 0x42
+#define ACI_SET_EQ4 0x43
+#define ACI_SET_EQ5 0x44
+#define ACI_SET_EQ6 0x45
+#define ACI_SET_EQ7 0x46 /* ... to Treble */
+
+#endif /* _MIRO_H_ */
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 65b28cbc0ebd..8ee0d70536f9 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -2099,8 +2099,11 @@ static int __init alsa_card_opti9xx_init(void)
return error;
device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
if (!IS_ERR(device)) {
- snd_opti9xx_platform_device = device;
- return 0;
+ if (platform_get_drvdata(device)) {
+ snd_opti9xx_platform_device = device;
+ return 0;
+ }
+ platform_device_unregister(device);
}
platform_driver_unregister(&snd_opti9xx_driver);
}
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 21ea65925a9e..6333f900eaee 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -720,9 +720,11 @@ static int __init alsa_card_sb16_init(void)
continue;
device = platform_device_register_simple(SND_SB16_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
@@ -745,14 +747,10 @@ static int __init alsa_card_sb16_init(void)
snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
#endif
#endif
- err = -ENODEV;
- goto errout;
+ snd_sb16_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_sb16_unregister_all();
- return err;
}
static void __exit alsa_card_sb16_exit(void)
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 3efa23d303c3..141400c01426 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -264,9 +264,11 @@ static int __init alsa_card_sb8_init(void)
continue;
device = platform_device_register_simple(SND_SB8_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -275,14 +277,10 @@ static int __init alsa_card_sb8_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_sb8_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_sb8_unregister_all();
- return err;
}
static void __exit alsa_card_sb8_exit(void)
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index a60e66afbf90..09c8e8c6b5e3 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -366,9 +366,11 @@ static int __init alsa_card_sgalaxy_init(void)
continue;
device = platform_device_register_simple(SND_SGALAXY_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -377,14 +379,10 @@ static int __init alsa_card_sgalaxy_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_sgalaxy_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_sgalaxy_unregister_all();
- return err;
}
static void __exit alsa_card_sgalaxy_exit(void)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 48e5552d3444..d2a856f0fde2 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1427,8 +1427,8 @@ static int __init sscape_manual_probe(void)
dma[i] == SNDRV_AUTO_DMA) {
printk(KERN_INFO
"sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
- ret = -ENXIO;
- goto errout;
+ sscape_unregister_all();
+ return -ENXIO;
}
/*
@@ -1436,17 +1436,15 @@ static int __init sscape_manual_probe(void)
*/
device = platform_device_register_simple(SSCAPE_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- ret = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
}
return 0;
-
- errout:
- sscape_unregister_all();
- return ret;
}
static void sscape_exit(void)
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 2f13cd5d4dcb..7ae86f82c3fa 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -722,9 +722,11 @@ static int __init alsa_card_wavefront_init(void)
#endif
device = platform_device_register_simple(WAVEFRONT_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
@@ -742,14 +744,10 @@ static int __init alsa_card_wavefront_init(void)
#ifdef MODULE
printk (KERN_ERR "No WaveFront cards found or devices busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_wavefront_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_wavefront_unregister_all();
- return err;
}
static void __exit alsa_card_wavefront_exit(void)
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 88e52dc84c09..558c6ed443be 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,23 +5,9 @@
#
# Prompt user for primary drivers.
-config OBSOLETE_OSS_DRIVER
- bool "Obsolete OSS drivers"
- depends on SOUND_PRIME
- help
- This option enables support for obsolete OSS drivers that
- are scheduled for removal in the near future since there
- are ALSA drivers for the same hardware.
-
- Please contact Adrian Bunk <bunk@stusta.de> if you had to
- say Y here because your soundcard is not properly supported
- by ALSA.
-
- If unsure, say N.
-
config SOUND_BT878
tristate "BT878 audio dma"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
---help---
Audio DMA support for bt878 based grabber boards. As you might have
already noticed, bt878 is listed with two functions in /proc/pci.
@@ -35,48 +21,9 @@ config SOUND_BT878
To compile this driver as a module, choose M here: the module will
be called btaudio.
-config SOUND_CMPCI
- tristate "C-Media PCI (CMI8338/8738)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card using the CMI8338
- or the CMI8738 chipset. Data on these chips are available at
- <http://www.cmedia.com.tw/>.
-
- A userspace utility to control some internal registers of these
- chips is available at
- <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
-
-config SOUND_CMPCI_FM
- bool "Enable legacy FM"
- depends on SOUND_CMPCI && X86
- help
- Say Y here to enable the legacy FM (frequency-modulation) synthesizer
- support on a card using the CMI8338 or CMI8378 chipset. Even it is
- enabled, you need to set fmio as proper value to enable it.
- Say N here if you don't need this.
-
-config SOUND_CMPCI_MIDI
- bool "Enable legacy MPU-401"
- depends on SOUND_CMPCI && X86
- help
- Say Y here to enable the legacy MPU401 MIDI synthesizer support on a
- card using the CMI8338 or CMI8378 chipset. Even it is enabled,
- you need to set mpuio as proper value to enable it.
- Say N here if you don't need this.
-
-config SOUND_CMPCI_JOYSTICK
- bool "Enable joystick"
- depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
- help
- Say Y here in order to enable the joystick port on a sound card using
- the CMI8338 or the CMI8738 chipset. You need to config the
- gameport support and set joystick parameter as 1 to use it.
- Say N here if you don't need this.
-
config SOUND_EMU10K1
tristate "Creative SBLive! (EMU10K1)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
---help---
Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -108,13 +55,6 @@ config SOUND_FUSION
series) when wired as native sound drivers with AC97 codecs. If
this driver does not work try the CS4232 driver.
-config SOUND_CS4281
- tristate "Crystal Sound CS4281"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Picture and feature list at
- <http://www.pcbroker.com/crystal4281.html>.
-
config SOUND_BCM_CS4297A
tristate "Crystal Sound CS4297a (for Swarm)"
depends on SOUND_PRIME && SIBYTE_SWARM
@@ -125,22 +65,9 @@ config SOUND_BCM_CS4297A
note that CONFIG_KGDB should not be enabled at the same
time, since it also attempts to use this UART port.
-config SOUND_ES1370
- tristate "Ensoniq AudioPCI (ES1370)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card utilizing the Ensoniq
- ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
- out if your sound card uses an ES1370 without removing your
- computer's cover, use lspci -n and look for the PCI ID
- 1274:5000. Since Ensoniq was bought by Creative Labs,
- Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
- This driver differs slightly from OSS/Free, so PLEASE READ
- <file:Documentation/sound/oss/es1370>.
-
config SOUND_ES1371
tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a PCI sound card utilizing the Ensoniq
ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -151,33 +78,6 @@ config SOUND_ES1371
slightly from OSS/Free, so PLEASE READ
<file:Documentation/sound/oss/es1371>.
-config SOUND_ESSSOLO1
- tristate "ESS Technology Solo1"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card utilizing the ESS Technology
- Solo1 chip. To find out if your sound card uses a
- Solo1 chip without removing your computer's cover, use
- lspci -n and look for the PCI ID 125D:1969. This driver
- differs slightly from OSS/Free, so PLEASE READ
- <file:Documentation/sound/oss/solo1>.
-
-config SOUND_MAESTRO
- tristate "ESS Maestro, Maestro2, Maestro2E driver"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a sound system driven by ESS's Maestro line
- of PCI sound chips. These include the Maestro 1, Maestro 2, and
- Maestro 2E. See <file:Documentation/sound/oss/Maestro> for more
- details.
-
-config SOUND_MAESTRO3
- tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
- depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a sound system driven by ESS's Maestro 3
- PCI sound chip.
-
config SOUND_ICH
tristate "Intel ICH (i8xx) audio support"
depends on SOUND_PRIME && PCI
@@ -185,24 +85,6 @@ config SOUND_ICH
Support for integral audio in Intel's I/O Controller Hub (ICH)
chipset, as used on the 810/820/840 motherboards.
-config SOUND_HARMONY
- tristate "PA Harmony audio driver"
- depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER
- help
- Say 'Y' or 'M' to include support for Harmony soundchip
- on HP 712, 715/new and many other GSC based machines.
-
-config SOUND_SONICVIBES
- tristate "S3 SonicVibes"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card utilizing the S3
- SonicVibes chipset. To find out if your sound card uses a
- SonicVibes chip without removing your computer's cover, use
- lspci -n and look for the PCI ID 5333:CA00. This driver
- differs slightly from OSS/Free, so PLEASE READ
- <file:Documentation/sound/oss/sonicvibes>.
-
config SOUND_VWSND
tristate "SGI Visual Workstation Sound"
depends on SOUND_PRIME && X86_VISWS
@@ -231,10 +113,6 @@ config SOUND_VRC5477
integrated, multi-function controller chip for MIPS CPUs. Works
with the AC97 codec.
-config SOUND_AU1000
- tristate "Au1000 Sound"
- depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER
-
config SOUND_AU1550_AC97
tristate "Au1550 AC97 Sound"
depends on SOUND_PRIME && SOC_AU1550
@@ -507,7 +385,7 @@ config MSND_FIFOSIZE
config SOUND_VIA82CXXX
tristate "VIA 82C686 Audio Codec"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
help
Say Y here to include support for the audio codec found on VIA
82Cxxx-based chips. Typically these are built into a motherboard.
@@ -576,18 +454,6 @@ config SOUND_AD1889
Say M here if you have a sound card based on the Analog Devices
AD1889 chip.
-config SOUND_SGALAXY
- tristate "Aztech Sound Galaxy (non-PnP) cards"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- This module initializes the older non Plug and Play sound galaxy
- cards from Aztech. It supports the Waverider Pro 32 - 3D and the
- Galaxy Washington 16.
-
- If you compile the driver into the kernel, you have to add
- "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command
- line.
-
config SOUND_ADLIB
tristate "Adlib Cards"
depends on SOUND_OSS
@@ -614,7 +480,7 @@ config SOUND_ACI_MIXER
config SOUND_CS4232
tristate "Crystal CS4232 based (PnP) cards"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+ depends on SOUND_OSS
help
Say Y here if you have a card based on the Crystal CS4232 chip set,
which uses its own Plug and Play protocol.
@@ -626,42 +492,6 @@ config SOUND_CS4232
See <file:Documentation/sound/oss/CS4232> for more information on
configuring this card.
-config SOUND_SSCAPE
- tristate "Ensoniq SoundScape support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Answer Y if you have a sound card based on the Ensoniq SoundScape
- chipset. Such cards are being manufactured at least by Ensoniq, Spea
- and Reveal (Reveal makes also other cards).
-
- If you compile the driver into the kernel, you have to add
- "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
- line.
-
-config SOUND_GUS
- tristate "Gravis Ultrasound support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y here for any type of Gravis Ultrasound card, including the GUS
- or GUS MAX. See also <file:Documentation/sound/oss/ultrasound> for more
- information on configuring this card with modules.
-
- If you compile the driver into the kernel, you have to add
- "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-config SOUND_GUS16
- bool "16 bit sampling option of GUS (_NOT_ GUS MAX)"
- depends on SOUND_GUS
- help
- Support for Gravis Ulstrasound (GUS) cards (other than the GUS),
- sampling at 16-bit width.
-
-config SOUND_GUSMAX
- bool "GUS MAX support"
- depends on SOUND_GUS
- help
- Support for Gravis Ulstrasound MAX.
-
config SOUND_VMIDI
tristate "Loopback MIDI device support"
depends on SOUND_OSS
@@ -742,7 +572,7 @@ config SOUND_MPU401
config SOUND_NM256
tristate "NM256AV/NM256ZX audio support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+ depends on SOUND_OSS
help
Say M here to include audio support for the NeoMagic 256AV/256ZX
chipsets. These are the audio chipsets found in the Sony
@@ -752,35 +582,6 @@ config SOUND_NM256
See <file:Documentation/sound/oss/NM256> for further information.
-config SOUND_MAD16
- tristate "OPTi MAD16 and/or Mozart based cards"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- ---help---
- Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
- 82C928 or 82C929 or 82C931) audio interface chip. These chips are
- quite common so it's possible that many no-name cards have one of
- them. In addition the MAD16 chip is used in some cards made by known
- manufacturers such as Turtle Beach (Tropez), Reveal (some models)
- and Diamond (latest ones). Note however that the Tropez sound cards
- have their own driver; if you have one of those, say N here and Y or
- M to "Full support for Turtle Beach WaveFront", below.
-
- If you compile the driver into the kernel, you have to add
- "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
- kernel command line.
-
- See also <file:Documentation/sound/oss/Opti> and
- <file:Documentation/sound/oss/MAD16> for more information on setting
- these cards up as modules.
-
-config MAD16_OLDCARD
- bool "Support MIDI in older MAD16 based cards (requires SB)"
- depends on SOUND_MAD16
- help
- Answer Y (or M) if you have an older card based on the C928 or
- Mozart chipset and you want to have MIDI support. If you enable this
- option you also need to enable support for Sound Blaster.
-
config SOUND_PAS
tristate "ProAudioSpectrum 16 support"
depends on SOUND_OSS
@@ -873,53 +674,9 @@ config SOUND_SB
You can say M here to compile this driver as a module; the module is
called sb.
-config SOUND_AWE32_SYNTH
- tristate "AWE32 synth"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
- similar sound card. See <file:Documentation/sound/oss/README.awe>,
- <file:Documentation/sound/oss/AWE32> and the Soundblaster-AWE
- mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
- for more info.
-
-config SOUND_WAVEFRONT
- tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards"
- depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER
- help
- Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
- and read the files <file:Documentation/sound/oss/Wavefront> and
- <file:Documentation/sound/oss/Tropez+>.
-
-config SOUND_MAUI
- tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
- sound card.
-
- If you compile the driver into the kernel, you have to add
- "maui=<io>,<irq>" to the kernel command line.
-
-config MAUI_HAVE_BOOT
- bool "Have OSWF.MOT firmware file"
- depends on SOUND_MAUI=y && !STANDALONE
- help
- Turtle Beach Maui and Tropez sound cards have a microcontroller
- which needs to be initialized prior to use. OSWF.MOT is a file
- distributed with the card's DOS/Windows drivers. Answer Y if you
- have this file.
-
-config MAUI_BOOT_FILE
- string "Full pathname of OSWF.MOT firmware file"
- depends on MAUI_HAVE_BOOT
- default "/etc/sound/oswf.mot"
- help
- Enter the full pathname of your OSWF.MOT file, starting from /.
-
config SOUND_YM3812
tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+ depends on SOUND_OSS
---help---
Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
Answering Y is usually a safe and recommended choice, however some
@@ -933,18 +690,6 @@ config SOUND_YM3812
If unsure, say Y.
-config SOUND_OPL3SA1
- tristate "Yamaha OPL3-SA1 audio controller"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
- usually built into motherboards. Read
- <file:Documentation/sound/oss/OPL3-SA> for details.
-
- If you compile the driver into the kernel, you have to add
- "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
- command line.
-
config SOUND_OPL3SA2
tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
depends on SOUND_OSS
@@ -959,19 +704,6 @@ config SOUND_OPL3SA2
"opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
command line.
-config SOUND_YMFPCI
- tristate "Yamaha YMF7xx PCI audio (native mode)"
- depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER
- help
- Support for Yamaha cards including the YMF711, YMF715, YMF718,
- YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
-
-config SOUND_YMFPCI_LEGACY
- bool "Yamaha PCI legacy ports support"
- depends on SOUND_YMFPCI
- help
- Support for YMF7xx PCI cards emulating an MP401.
-
config SOUND_UART6850
tristate "6850 UART support"
depends on SOUND_OSS
@@ -1101,30 +833,6 @@ config SOUND_KAHLUA
tristate "XpressAudio Sound Blaster emulation"
depends on SOUND_SB
-config SOUND_ALI5455
- tristate "ALi5455 audio support"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-
-config SOUND_FORTE
- tristate "ForteMedia FM801 driver"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you want driver support for the ForteMedia FM801 PCI
- audio controller (Abit AU10, Genius Sound Maker, HP Workstation
- zx2000, and others).
-
-config SOUND_RME96XX
- tristate "RME Hammerfall (RME96XX) support"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a Hammerfall or Hammerfall light
- multichannel card from RME. If you want to access advanced
- features of the card, read <file:Documentation/sound/oss/rme96xx>.
-
-config SOUND_AD1980
- tristate "AD1980 front/back switch plugin"
- depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER
-
config SOUND_SH_DAC_AUDIO
tristate "SuperH DAC audio support"
depends on SOUND_PRIME && CPU_SH3
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 54dabf862802..a4ca7569e700 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -75,7 +75,7 @@ static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
DBG("Setting WAV rate to %d\n", rate);
dev->state[AD_WAV_STATE].dmabuf.rate = rate;
- AD1889_WRITEW(dev, AD_DSWAS, rate);
+ AD1889_WRITEW(dev, AD_DS_WAS, rate);
/* Cycle the DAC to enable the new rate */
ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
@@ -89,14 +89,14 @@ static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
DBG("Setting WAV format to 0x%x\n", fmt);
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
if (fmt & AFMT_S16_LE) {
//tmp |= 0x0100; /* set WA16 */
tmp |= 0x0300; /* set WA16 stereo */
} else if (fmt & AFMT_U8) {
tmp &= ~0x0100; /* clear WA16 */
}
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
}
static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
@@ -105,13 +105,13 @@ static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
DBG("Setting ADC format to 0x%x\n", fmt);
- tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (fmt & AFMT_S16_LE) {
tmp |= 0x0100; /* set WA16 */
} else if (fmt & AFMT_U8) {
tmp &= ~0x0100; /* clear WA16 */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
}
static void ad1889_start_wav(ad1889_state_t *state)
@@ -145,21 +145,21 @@ static void ad1889_start_wav(ad1889_state_t *state)
dmabuf->rd_ptr, dmabuf->dma_len);
/* load up the current register set */
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVCA, dmabuf->dma_handle);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
/* TODO: for now we load the base registers with the same thing */
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVIBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVBA, dmabuf->dma_handle);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
/* and we're off to the races... */
- AD1889_WRITEL(ad1889_dev, AD_DMACHSS, 0x8);
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
tmp |= 0x0400; /* set WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+ (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
dmabuf->enable |= DAC_RUNNING;
@@ -179,10 +179,10 @@ static void ad1889_stop_wav(ad1889_state_t *state)
u16 tmp;
unsigned long cnt = dmabuf->dma_len;
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
tmp &= ~0x0400; /* clear WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+ (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle,
cnt, PCI_DMA_TODEVICE);
@@ -211,7 +211,7 @@ static void ad1889_startstop_adc(ad1889_state_t *state, int start)
spin_lock_irqsave(&state->card->lock, flags);
- tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (start) {
state->dmabuf.enable |= ADC_RUNNING;
tmp |= 0x0004; /* set ADEN */
@@ -219,7 +219,7 @@ static void ad1889_startstop_adc(ad1889_state_t *state, int start)
state->dmabuf.enable &= ~ADC_RUNNING;
tmp &= ~0x0004; /* clear ADEN */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
spin_unlock_irqrestore(&state->card->lock, flags);
}
@@ -301,53 +301,53 @@ static int ad1889_read_proc (char *page, char **start, off_t off,
int len, i;
ad1889_dev_t *dev = data;
ad1889_reg_t regs[] = {
- { "WSMC", AD_DSWSMC, 16 },
- { "RAMC", AD_DSRAMC, 16 },
- { "WADA", AD_DSWADA, 16 },
- { "SYDA", AD_DSSYDA, 16 },
- { "WAS", AD_DSWAS, 16 },
- { "RES", AD_DSRES, 16 },
- { "CCS", AD_DSCCS, 16 },
- { "ADCBA", AD_DMAADCBA, 32 },
- { "ADCCA", AD_DMAADCCA, 32 },
- { "ADCBC", AD_DMAADCBC, 32 },
- { "ADCCC", AD_DMAADCCC, 32 },
- { "ADCIBC", AD_DMAADCIBC, 32 },
- { "ADCICC", AD_DMAADCICC, 32 },
- { "ADCCTRL", AD_DMAADCCTRL, 16 },
- { "WAVBA", AD_DMAWAVBA, 32 },
- { "WAVCA", AD_DMAWAVCA, 32 },
- { "WAVBC", AD_DMAWAVBC, 32 },
- { "WAVCC", AD_DMAWAVCC, 32 },
- { "WAVIBC", AD_DMAWAVIBC, 32 },
- { "WAVICC", AD_DMAWAVICC, 32 },
- { "WAVCTRL", AD_DMAWAVCTRL, 16 },
- { "DISR", AD_DMADISR, 32 },
- { "CHSS", AD_DMACHSS, 32 },
- { "IPC", AD_GPIOIPC, 16 },
- { "OP", AD_GPIOOP, 16 },
- { "IP", AD_GPIOIP, 16 },
- { "ACIC", AD_ACIC, 16 },
- { "AC97_RESET", 0x100 + AC97_RESET, 16 },
- { "AC97_MASTER_VOL_STEREO", 0x100 + AC97_MASTER_VOL_STEREO, 16 },
- { "AC97_HEADPHONE_VOL", 0x100 + AC97_HEADPHONE_VOL, 16 },
- { "AC97_MASTER_VOL_MONO", 0x100 + AC97_MASTER_VOL_MONO, 16 },
- { "AC97_MASTER_TONE", 0x100 + AC97_MASTER_TONE, 16 },
- { "AC97_PCBEEP_VOL", 0x100 + AC97_PCBEEP_VOL, 16 },
- { "AC97_PHONE_VOL", 0x100 + AC97_PHONE_VOL, 16 },
- { "AC97_MIC_VOL", 0x100 + AC97_MIC_VOL, 16 },
- { "AC97_LINEIN_VOL", 0x100 + AC97_LINEIN_VOL, 16 },
- { "AC97_CD_VOL", 0x100 + AC97_CD_VOL, 16 },
- { "AC97_VIDEO_VOL", 0x100 + AC97_VIDEO_VOL, 16 },
- { "AC97_AUX_VOL", 0x100 + AC97_AUX_VOL, 16 },
- { "AC97_PCMOUT_VOL", 0x100 + AC97_PCMOUT_VOL, 16 },
- { "AC97_RECORD_SELECT", 0x100 + AC97_RECORD_SELECT, 16 },
- { "AC97_RECORD_GAIN", 0x100 + AC97_RECORD_GAIN, 16 },
- { "AC97_RECORD_GAIN_MIC", 0x100 + AC97_RECORD_GAIN_MIC, 16 },
- { "AC97_GENERAL_PURPOSE", 0x100 + AC97_GENERAL_PURPOSE, 16 },
- { "AC97_3D_CONTROL", 0x100 + AC97_3D_CONTROL, 16 },
- { "AC97_MODEM_RATE", 0x100 + AC97_MODEM_RATE, 16 },
- { "AC97_POWER_CONTROL", 0x100 + AC97_POWER_CONTROL, 16 },
+ { "WSMC", AD_DS_WSMC, 16 },
+ { "RAMC", AD_DS_RAMC, 16 },
+ { "WADA", AD_DS_WADA, 16 },
+ { "SYDA", AD_DS_SYDA, 16 },
+ { "WAS", AD_DS_WAS, 16 },
+ { "RES", AD_DS_RES, 16 },
+ { "CCS", AD_DS_CCS, 16 },
+ { "ADCBA", AD_DMA_ADCBA, 32 },
+ { "ADCCA", AD_DMA_ADCCA, 32 },
+ { "ADCBC", AD_DMA_ADCBC, 32 },
+ { "ADCCC", AD_DMA_ADCCC, 32 },
+ { "ADCIBC", AD_DMA_ADCIBC, 32 },
+ { "ADCICC", AD_DMA_ADCICC, 32 },
+ { "ADCCTRL", AD_DMA_ADCCTRL, 16 },
+ { "WAVBA", AD_DMA_WAVBA, 32 },
+ { "WAVCA", AD_DMA_WAVCA, 32 },
+ { "WAVBC", AD_DMA_WAVBC, 32 },
+ { "WAVCC", AD_DMA_WAVCC, 32 },
+ { "WAVIBC", AD_DMA_WAVIBC, 32 },
+ { "WAVICC", AD_DMA_WAVICC, 32 },
+ { "WAVCTRL", AD_DMA_WAVCTRL, 16 },
+ { "DISR", AD_DMA_DISR, 32 },
+ { "CHSS", AD_DMA_CHSS, 32 },
+ { "IPC", AD_GPIO_IPC, 16 },
+ { "OP", AD_GPIO_OP, 16 },
+ { "IP", AD_GPIO_IP, 16 },
+ { "ACIC", AD_AC97_ACIC, 16 },
+ { "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
+ { "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
+ { "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
+ { "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
+ { "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
+ { "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
+ { "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
+ { "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
+ { "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
+ { "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
+ { "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
+ { "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
+ { "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
+ { "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
+ { "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
+ { "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
+ { "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
+ { "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
+ { "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
+ { "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
{ NULL }
};
@@ -400,9 +400,9 @@ static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
}
if (dmabuf->enable & DAC_RUNNING)
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAWAVBA));
+ offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
else
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAADCBA));
+ offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
}
@@ -639,9 +639,9 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (val > 5400 && val < 48000)
{
if (file->f_mode & FMODE_WRITE)
- AD1889_WRITEW(ad1889_dev, AD_DSWAS, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
if (file->f_mode & FMODE_READ)
- AD1889_WRITEW(ad1889_dev, AD_DSRES, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
}
return 0;
@@ -649,22 +649,22 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (get_user(val, p))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
- val = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
if (val) {
val |= 0x0200; /* set WAST */
} else {
val &= ~0x0200; /* clear WAST */
}
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
}
if (file->f_mode & FMODE_WRITE) {
- val = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (val) {
val |= 0x0002; /* set ADST */
} else {
val &= ~0x0002; /* clear ADST */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
}
return 0;
@@ -739,7 +739,7 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
break;
case SOUND_PCM_READ_RATE:
- return put_user(AD1889_READW(ad1889_dev, AD_DSWAS), p);
+ return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
case SOUND_PCM_READ_CHANNELS:
case SOUND_PCM_READ_BITS:
@@ -769,7 +769,7 @@ static int ad1889_open(struct inode *inode, struct file *file)
ad1889_set_wav_rate(ad1889_dev, 48000);
ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
- AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
return nonseekable_open(inode, file);
}
@@ -826,15 +826,15 @@ static void ad1889_codec_write(struct ac97_codec *ac97, u8 reg, u16 val)
{
ad1889_dev_t *dev = ac97->private_data;
- //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + 0x100 + reg);
- AD1889_WRITEW(dev, 0x100 + reg, val);
+ //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
+ AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
}
static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
{
ad1889_dev_t *dev = ac97->private_data;
- //DBG("Reading from 0x%lx\n", dev->regbase + 0x100 + reg);
- return AD1889_READW(dev, 0x100 + reg);
+ //DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
+ return AD1889_READW(dev, AD_AC97_BASE + reg);
}
static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
@@ -883,24 +883,24 @@ static int ad1889_aclink_reset(struct pci_dev * pcidev)
int retry = 200;
ad1889_dev_t *dev = pci_get_drvdata(pcidev);
- AD1889_WRITEW(dev, AD_DSCCS, 0x8000); /* turn on clock */
- AD1889_READW(dev, AD_DSCCS);
+ AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
+ AD1889_READW(dev, AD_DS_CCS);
WAIT_10MS();
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0002; /* Reset Disable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
- (void) AD1889_READW(dev, AD_ACIC); /* flush posted write */
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
+ (void) AD1889_READW(dev, AD_AC97_ACIC); /* flush posted write */
udelay(10);
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0001; /* Interface Enable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
do {
- if (AD1889_READW(dev, AD_ACIC) & 0x8000) /* Ready */
+ if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000) /* Ready */
break;
WAIT_10MS();
retry--;
@@ -908,16 +908,16 @@ static int ad1889_aclink_reset(struct pci_dev * pcidev)
if (!retry) {
printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
- AD1889_READW(dev, AD_ACIC));
+ AD1889_READW(dev, AD_AC97_ACIC));
return -EBUSY;
}
/* TODO reset AC97 codec */
/* TODO set wave/adc pci ctrl status */
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0004; /* Audio Stream Output Enable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
return 0;
}
@@ -935,10 +935,10 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u32 stat;
ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
- stat = AD1889_READL(dev, AD_DMADISR);
+ stat = AD1889_READL(dev, AD_DMA_DISR);
/* clear ISR */
- AD1889_WRITEL(dev, AD_DMADISR, stat);
+ AD1889_WRITEL(dev, AD_DMA_DISR, stat);
if (stat & 0x8) { /* WAVI */
DBG("WAV interrupt\n");
@@ -964,15 +964,15 @@ static void ad1889_initcfg(ad1889_dev_t *dev)
u32 tmp32;
/* make sure the interrupt bits are setup the way we want */
- tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL);
+ tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
tmp32 |= 0x6; /* intr on count, loop */
- AD1889_WRITEL(dev, AD_DMAWAVCTRL, tmp32);
+ AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
/* unmute... */
- tmp16 = AD1889_READW(dev, AD_DSWADA);
+ tmp16 = AD1889_READW(dev, AD_DS_WADA);
tmp16 &= ~0x8080;
- AD1889_WRITEW(dev, AD_DSWADA, tmp16);
+ AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
}
static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
@@ -1005,7 +1005,7 @@ static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_devic
goto out1;
}
- dev->regbase = ioremap_nocache(bar, AD_DSIOMEMSIZE);
+ dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
if (!dev->regbase) {
printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
goto out2;
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
index 861b3213f30b..09913765967a 100644
--- a/sound/oss/ad1889.h
+++ b/sound/oss/ad1889.h
@@ -1,57 +1,58 @@
#ifndef _AD1889_H_
#define _AD1889_H_
-#define AD_DSWSMC 0x00 /* DMA input wave/syn mixer control */
-#define AD_DSRAMC 0x02 /* DMA output resamp/ADC mixer control */
-#define AD_DSWADA 0x04 /* DMA input wave attenuation */
-#define AD_DSSYDA 0x06 /* DMA input syn attentuation */
-#define AD_DSWAS 0x08 /* wave input sample rate */
-#define AD_DSRES 0x0a /* resampler output sample rate */
-#define AD_DSCCS 0x0c /* chip control/status */
-
-#define AD_DMARESBA 0x40 /* RES base addr */
-#define AD_DMARESCA 0x44 /* RES current addr */
-#define AD_DMARESBC 0x48 /* RES base cnt */
-#define AD_DMARESCC 0x4c /* RES current count */
-#define AD_DMAADCBA 0x50 /* ADC */
-#define AD_DMAADCCA 0x54
-#define AD_DMAADCBC 0x58
-#define AD_DMAADCCC 0x5c
-#define AD_DMASYNBA 0x60 /* SYN */
-#define AD_DMASYNCA 0x64
-#define AD_DMASYNBC 0x68
-#define AD_DMASYNCC 0x6c
-#define AD_DMAWAVBA 0x70 /* WAV */
-#define AD_DMAWAVCA 0x74
-#define AD_DMAWAVBC 0x78
-#define AD_DMAWAVCC 0x7c
-#define AD_DMARESICC 0x80 /* RES interrupt current count */
-#define AD_DMARESIBC 0x84 /* RES interrupt base count */
-#define AD_DMAADCICC 0x88 /* ADC interrupt current count */
-#define AD_DMAADCIBC 0x8c /* ADC interrupt base count */
-#define AD_DMASYNICC 0x90 /* SYN interrupt current count */
-#define AD_DMASYNIBC 0x94 /* SYN interrupt base count */
-#define AD_DMAWAVICC 0x98 /* WAV interrupt current count */
-#define AD_DMAWAVIBC 0x9c /* WAV interrupt base count */
-#define AD_DMARESCTRL 0xa0 /* RES PCI control/status */
-#define AD_DMAADCCTRL 0xa8 /* ADC PCI control/status */
-#define AD_DMASYNCTRL 0xb0 /* SYN PCI control/status */
-#define AD_DMAWAVCTRL 0xb8 /* WAV PCI control/status */
-#define AD_DMADISR 0xc0 /* PCI DMA intr status */
-#define AD_DMACHSS 0xc4 /* PCI DMA channel stop status */
-
-#define AD_GPIOIPC 0xc8 /* IO port ctrl */
-#define AD_GPIOOP 0xca /* IO output status */
-#define AD_GPIOIP 0xcc /* IO input status */
+#define AD_DS_WSMC 0x00 /* DMA input wave/syn mixer control */
+#define AD_DS_RAMC 0x02 /* DMA output resamp/ADC mixer control */
+#define AD_DS_WADA 0x04 /* DMA input wave attenuation */
+#define AD_DS_SYDA 0x06 /* DMA input syn attentuation */
+#define AD_DS_WAS 0x08 /* wave input sample rate */
+#define AD_DS_RES 0x0a /* resampler output sample rate */
+#define AD_DS_CCS 0x0c /* chip control/status */
+
+#define AD_DMA_RESBA 0x40 /* RES base addr */
+#define AD_DMA_RESCA 0x44 /* RES current addr */
+#define AD_DMA_RESBC 0x48 /* RES base cnt */
+#define AD_DMA_RESCC 0x4c /* RES current count */
+#define AD_DMA_ADCBA 0x50 /* ADC */
+#define AD_DMA_ADCCA 0x54
+#define AD_DMA_ADCBC 0x58
+#define AD_DMA_ADCCC 0x5c
+#define AD_DMA_SYNBA 0x60 /* SYN */
+#define AD_DMA_SYNCA 0x64
+#define AD_DMA_SYNBC 0x68
+#define AD_DMA_SYNCC 0x6c
+#define AD_DMA_WAVBA 0x70 /* WAV */
+#define AD_DMA_WAVCA 0x74
+#define AD_DMA_WAVBC 0x78
+#define AD_DMA_WAVCC 0x7c
+#define AD_DMA_RESICC 0x80 /* RES interrupt current count */
+#define AD_DMA_RESIBC 0x84 /* RES interrupt base count */
+#define AD_DMA_ADCICC 0x88 /* ADC interrupt current count */
+#define AD_DMA_ADCIBC 0x8c /* ADC interrupt base count */
+#define AD_DMA_SYNICC 0x90 /* SYN interrupt current count */
+#define AD_DMA_SYNIBC 0x94 /* SYN interrupt base count */
+#define AD_DMA_WAVICC 0x98 /* WAV interrupt current count */
+#define AD_DMA_WAVIBC 0x9c /* WAV interrupt base count */
+#define AD_DMA_RESCTRL 0xa0 /* RES PCI control/status */
+#define AD_DMA_ADCCTRL 0xa8 /* ADC PCI control/status */
+#define AD_DMA_SYNCTRL 0xb0 /* SYN PCI control/status */
+#define AD_DMA_WAVCTRL 0xb8 /* WAV PCI control/status */
+#define AD_DMA_DISR 0xc0 /* PCI DMA intr status */
+#define AD_DMA_CHSS 0xc4 /* PCI DMA channel stop status */
+
+#define AD_GPIO_IPC 0xc8 /* IO port ctrl */
+#define AD_GPIO_OP 0xca /* IO output status */
+#define AD_GPIO_IP 0xcc /* IO input status */
/* AC97 registers, 0x100 - 0x17f; see ac97.h */
-#define AD_ACIC 0x180 /* AC Link interface ctrl */
+#define AD_AC97_BASE 0x100 /* ac97 base register */
+#define AD_AC97_ACIC 0x180 /* AC Link interface ctrl */
/* OPL3; BAR1 */
-#define AD_OPLM0AS 0x00 /* Music0 address/status */
-#define AD_OPLM0DATA 0x01 /* Music0 data */
-#define AD_OPLM1A 0x02 /* Music1 address */
-#define AD_OPLM1DATA 0x03 /* Music1 data */
+#define AD_OPL_M0AS 0x00 /* Music0 address/status */
+#define AD_OPL_M0DATA 0x01 /* Music0 data */
+#define AD_OPL_M1A 0x02 /* Music1 address */
+#define AD_OPL_M1DATA 0x03 /* Music1 data */
/* 0x04-0x0f reserved */
/* MIDI; BAR2 */
@@ -59,9 +60,9 @@
#define AD_MISC 0x01 /* MIDI status/cmd */
/* 0x02-0xff reserved */
-#define AD_DSIOMEMSIZE 512
-#define AD_OPLMEMSIZE 16
-#define AD_MIDIMEMSIZE 16
+#define AD_DS_IOMEMSIZE 512
+#define AD_OPL_MEMSIZE 16
+#define AD_MIDI_MEMSIZE 16
#define AD_WAV_STATE 0
#define AD_ADC_STATE 1
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index 81315996c0f1..882ae98a41b1 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -195,8 +195,8 @@ tas_init(int driver_id, const char *driver_name)
printk(KERN_INFO "tas driver [%s])\n", driver_name);
-#ifndef CONFIG_I2C_KEYWEST
- request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+ request_module("i2c-powermac");
#endif
tas_node = find_devices("deq");
if (tas_node == NULL)
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index 0cd44a6f7ac0..3721c5857b90 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -94,6 +94,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
+#include <linux/dma-mapping.h>
#include "hwaccess.h"
#include "8010.h"
@@ -119,7 +120,7 @@
/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
-#define EMU10K1_DMA_MASK 0x1fffffff /* DMA buffer mask for pci_alloc_consist */
+#define EMU10K1_DMA_MASK DMA_29BIT_MASK /* DMA buffer mask for pci_alloc_consist */
#ifndef PCI_VENDOR_ID_CREATIVE
#define PCI_VENDOR_ID_CREATIVE 0x1102
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1e2e19305e38..a2081803a827 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -15,6 +15,18 @@ config SND_AD1889
To compile this as a module, choose M here: the module
will be called snd-ad1889.
+config SND_ALS300
+ tristate "Avance Logic ALS300/ALS300+"
+ depends on SND
+ select SND_PCM
+ select SND_AC97_CODEC
+ select SND_OPL3_LIB
+ help
+ Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-als300
+
config SND_ALS4000
tristate "Avance Logic ALS4000"
depends on SND && ISA_DMA_API
@@ -195,8 +207,9 @@ config SND_CS46XX
will be called snd-cs46xx.
config SND_CS46XX_NEW_DSP
- bool "Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)"
- depends on SND_CS46XX && EXPERIMENTAL
+ bool "Cirrus Logic (Sound Fusion) New DSP support"
+ depends on SND_CS46XX
+ default y
help
Say Y here to use a new DSP image for SPDIF and dual codecs.
@@ -466,6 +479,19 @@ config SND_PCXHR
To compile this driver as a module, choose M here: the module
will be called snd-pcxhr.
+config SND_RIPTIDE
+ tristate "Conexant Riptide"
+ depends on SND
+ depends on FW_LOADER
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
+ help
+ Say 'Y' or 'M' to include support for Conexant Riptide chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-riptide
+
config SND_RME32
tristate "RME Digi32, 32/8, 32 PRO"
depends on SND
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index a6c3cd58fe94..cba5105aafea 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -4,6 +4,7 @@
#
snd-ad1889-objs := ad1889.o
+snd-als300-objs := als300.o
snd-als4000-objs := als4000.o
snd-atiixp-objs := atiixp.o
snd-atiixp-modem-objs := atiixp_modem.o
@@ -27,6 +28,7 @@ snd-via82xx-modem-objs := via82xx_modem.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_AD1889) += snd-ad1889.o
+obj-$(CONFIG_SND_ALS300) += snd-als300.o
obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
@@ -62,6 +64,7 @@ obj-$(CONFIG_SND) += \
mixart/ \
nm256/ \
pcxhr/ \
+ riptide/ \
rme9652/ \
trident/ \
ymfpci/ \
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 278319bbdea1..d05200741ac3 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -160,6 +160,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL },
{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
{ 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF
+{ 0x56494182, 0xffffffff, "VIA1618", NULL, NULL },
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL },
{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
new file mode 100644
index 000000000000..91899f87f037
--- /dev/null
+++ b/sound/pci/als300.c
@@ -0,0 +1,867 @@
+/*
+ * als300.c - driver for Avance Logic ALS300/ALS300+ soundcards.
+ * Copyright (C) 2005 by Ash Willis <ashwillis@programmer.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ *
+ * TODO
+ * 4 channel playback for ALS300+
+ * gameport
+ * mpu401
+ * opl3
+ *
+ * NOTES
+ * The BLOCK_COUNTER registers for the ALS300(+) return a figure related to
+ * the position in the current period, NOT the whole buffer. It is important
+ * to know which period we are in so we can calculate the correct pointer.
+ * This is why we always use 2 periods. We can then use a flip-flop variable
+ * to keep track of what period we are in.
+ */
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/opl3.h>
+
+/* snd_als300_set_irq_flag */
+#define IRQ_DISABLE 0
+#define IRQ_ENABLE 1
+
+/* I/O port layout */
+#define AC97_ACCESS 0x00
+#define AC97_READ 0x04
+#define AC97_STATUS 0x06
+#define AC97_DATA_AVAIL (1<<6)
+#define AC97_BUSY (1<<7)
+#define ALS300_IRQ_STATUS 0x07 /* ALS300 Only */
+#define IRQ_PLAYBACK (1<<3)
+#define IRQ_CAPTURE (1<<2)
+#define GCR_DATA 0x08
+#define GCR_INDEX 0x0C
+#define ALS300P_DRAM_IRQ_STATUS 0x0D /* ALS300+ Only */
+#define MPU_IRQ_STATUS 0x0E /* ALS300 Rev. E+, ALS300+ */
+#define ALS300P_IRQ_STATUS 0x0F /* ALS300+ Only */
+
+/* General Control Registers */
+#define PLAYBACK_START 0x80
+#define PLAYBACK_END 0x81
+#define PLAYBACK_CONTROL 0x82
+#define TRANSFER_START (1<<16)
+#define FIFO_PAUSE (1<<17)
+#define RECORD_START 0x83
+#define RECORD_END 0x84
+#define RECORD_CONTROL 0x85
+#define DRAM_WRITE_CONTROL 0x8B
+#define WRITE_TRANS_START (1<<16)
+#define DRAM_MODE_2 (1<<17)
+#define MISC_CONTROL 0x8C
+#define IRQ_SET_BIT (1<<15)
+#define VMUTE_NORMAL (1<<20)
+#define MMUTE_NORMAL (1<<21)
+#define MUS_VOC_VOL 0x8E
+#define PLAYBACK_BLOCK_COUNTER 0x9A
+#define RECORD_BLOCK_COUNTER 0x9B
+
+#define DEBUG_CALLS 1
+#define DEBUG_PLAY_REC 1
+
+#if DEBUG_CALLS
+#define snd_als300_dbgcalls(format, args...) printk(format, ##args)
+#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#else
+#define snd_als300_dbgcalls(format, args...)
+#define snd_als300_dbgcallenter()
+#define snd_als300_dbgcallleave()
+#endif
+
+#if DEBUG_PLAY_REC
+#define snd_als300_dbgplay(format, args...) printk(KERN_ERR format, ##args)
+#else
+#define snd_als300_dbgplay(format, args...)
+#endif
+
+enum {DEVICE_ALS300, DEVICE_ALS300_PLUS};
+
+MODULE_AUTHOR("Ash Willis <ashwillis@programmer.net>");
+MODULE_DESCRIPTION("Avance Logic ALS300");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS300},{Avance Logic,ALS300+}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+struct snd_als300 {
+ unsigned long port;
+ spinlock_t reg_lock;
+ struct snd_card *card;
+ struct pci_dev *pci;
+
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+
+ struct snd_ac97 *ac97;
+ struct snd_opl3 *opl3;
+
+ struct resource *res_port;
+
+ int irq;
+
+ int chip_type; /* ALS300 or ALS300+ */
+
+ char revision;
+};
+
+struct snd_als300_substream_data {
+ int period_flipflop;
+ int control_register;
+ int block_counter_register;
+};
+
+static struct pci_device_id snd_als300_ids[] = {
+ { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 },
+ { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, snd_als300_ids);
+
+static inline u32 snd_als300_gcr_read(unsigned long port, unsigned short reg)
+{
+ outb(reg, port+GCR_INDEX);
+ return inl(port+GCR_DATA);
+}
+
+static inline void snd_als300_gcr_write(unsigned long port,
+ unsigned short reg, u32 val)
+{
+ outb(reg, port+GCR_INDEX);
+ outl(val, port+GCR_DATA);
+}
+
+/* Enable/Disable Interrupts */
+static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd)
+{
+ u32 tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL);
+ snd_als300_dbgcallenter();
+
+ /* boolean XOR check, since old vs. new hardware have
+ directly reversed bit setting for ENABLE and DISABLE.
+ ALS300+ acts like newer versions of ALS300 */
+ if (((chip->revision > 5 || chip->chip_type == DEVICE_ALS300_PLUS) ^
+ (cmd == IRQ_ENABLE)) == 0)
+ tmp |= IRQ_SET_BIT;
+ else
+ tmp &= ~IRQ_SET_BIT;
+ snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp);
+ snd_als300_dbgcallleave();
+}
+
+static int snd_als300_free(struct snd_als300 *chip)
+{
+ snd_als300_dbgcallenter();
+ snd_als300_set_irq_flag(chip, IRQ_DISABLE);
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void *)chip);
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_dev_free(struct snd_device *device)
+{
+ struct snd_als300 *chip = device->device_data;
+ return snd_als300_free(chip);
+}
+
+static irqreturn_t snd_als300_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u8 status;
+ struct snd_als300 *chip = dev_id;
+ struct snd_als300_substream_data *data;
+
+ status = inb(chip->port+ALS300_IRQ_STATUS);
+ if (!status) /* shared IRQ, for different device?? Exit ASAP! */
+ return IRQ_NONE;
+
+ /* ACK everything ASAP */
+ outb(status, chip->port+ALS300_IRQ_STATUS);
+ if (status & IRQ_PLAYBACK) {
+ if (chip->pcm && chip->playback_substream) {
+ data = chip->playback_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->playback_substream);
+ snd_als300_dbgplay("IRQ_PLAYBACK\n");
+ }
+ }
+ if (status & IRQ_CAPTURE) {
+ if (chip->pcm && chip->capture_substream) {
+ data = chip->capture_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->capture_substream);
+ snd_als300_dbgplay("IRQ_CAPTURE\n");
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u8 general, mpu, dram;
+ struct snd_als300 *chip = dev_id;
+ struct snd_als300_substream_data *data;
+
+ general = inb(chip->port+ALS300P_IRQ_STATUS);
+ mpu = inb(chip->port+MPU_IRQ_STATUS);
+ dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS);
+
+ /* shared IRQ, for different device?? Exit ASAP! */
+ if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0))
+ return IRQ_NONE;
+
+ if (general & IRQ_PLAYBACK) {
+ if (chip->pcm && chip->playback_substream) {
+ outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS);
+ data = chip->playback_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->playback_substream);
+ snd_als300_dbgplay("IRQ_PLAYBACK\n");
+ }
+ }
+ if (general & IRQ_CAPTURE) {
+ if (chip->pcm && chip->capture_substream) {
+ outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS);
+ data = chip->capture_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->capture_substream);
+ snd_als300_dbgplay("IRQ_CAPTURE\n");
+ }
+ }
+ /* FIXME: Ack other interrupt types. Not important right now as
+ * those other devices aren't enabled. */
+ return IRQ_HANDLED;
+}
+
+static void __devexit snd_als300_remove(struct pci_dev *pci)
+{
+ snd_als300_dbgcallenter();
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+ snd_als300_dbgcallleave();
+}
+
+static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+{
+ int i;
+ struct snd_als300 *chip = ac97->private_data;
+
+ for (i = 0; i < 1000; i++) {
+ if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0)
+ break;
+ udelay(10);
+ }
+ outl((reg << 24) | (1 << 31), chip->port+AC97_ACCESS);
+
+ for (i = 0; i < 1000; i++) {
+ if ((inb(chip->port+AC97_STATUS) & (AC97_DATA_AVAIL)) != 0)
+ break;
+ udelay(10);
+ }
+ return inw(chip->port+AC97_READ);
+}
+
+static void snd_als300_ac97_write(struct snd_ac97 *ac97,
+ unsigned short reg, unsigned short val)
+{
+ int i;
+ struct snd_als300 *chip = ac97->private_data;
+
+ for (i = 0; i < 1000; i++) {
+ if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0)
+ break;
+ udelay(10);
+ }
+ outl((reg << 24) | val, chip->port+AC97_ACCESS);
+}
+
+static int snd_als300_ac97(struct snd_als300 *chip)
+{
+ struct snd_ac97_bus *bus;
+ struct snd_ac97_template ac97;
+ int err;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_als300_ac97_write,
+ .read = snd_als300_ac97_read,
+ };
+
+ snd_als300_dbgcallenter();
+ if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
+ return err;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+
+ snd_als300_dbgcallleave();
+ return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+}
+
+/* hardware definition
+ *
+ * In AC97 mode, we always use 48k/16bit/stereo.
+ * Any request to change data type is ignored by
+ * the card when it is running outside of legacy
+ * mode.
+ */
+static struct snd_pcm_hardware snd_als300_playback_hw =
+{
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 64 * 1024,
+ .period_bytes_min = 64,
+ .period_bytes_max = 32 * 1024,
+ .periods_min = 2,
+ .periods_max = 2,
+};
+
+static struct snd_pcm_hardware snd_als300_capture_hw =
+{
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 64 * 1024,
+ .period_bytes_min = 64,
+ .period_bytes_max = 32 * 1024,
+ .periods_min = 2,
+ .periods_max = 2,
+};
+
+static int snd_als300_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
+ GFP_KERNEL);
+
+ snd_als300_dbgcallenter();
+ chip->playback_substream = substream;
+ runtime->hw = snd_als300_playback_hw;
+ runtime->private_data = data;
+ data->control_register = PLAYBACK_CONTROL;
+ data->block_counter_register = PLAYBACK_BLOCK_COUNTER;
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_als300_substream_data *data;
+
+ data = substream->runtime->private_data;
+ snd_als300_dbgcallenter();
+ kfree(data);
+ chip->playback_substream = NULL;
+ snd_pcm_lib_free_pages(substream);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_capture_open(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
+ GFP_KERNEL);
+
+ snd_als300_dbgcallenter();
+ chip->capture_substream = substream;
+ runtime->hw = snd_als300_capture_hw;
+ runtime->private_data = data;
+ data->control_register = RECORD_CONTROL;
+ data->block_counter_register = RECORD_BLOCK_COUNTER;
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_als300_substream_data *data;
+
+ data = substream->runtime->private_data;
+ snd_als300_dbgcallenter();
+ kfree(data);
+ chip->capture_substream = NULL;
+ snd_pcm_lib_free_pages(substream);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int snd_als300_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_als300_playback_prepare(struct snd_pcm_substream *substream)
+{
+ u32 tmp;
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
+ unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+
+ snd_als300_dbgcallenter();
+ spin_lock_irq(&chip->reg_lock);
+ tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL);
+ tmp &= ~TRANSFER_START;
+
+ snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n",
+ period_bytes, buffer_bytes);
+
+ /* set block size */
+ tmp &= 0xffff0000;
+ tmp |= period_bytes - 1;
+ snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp);
+
+ /* set dma area */
+ snd_als300_gcr_write(chip->port, PLAYBACK_START,
+ runtime->dma_addr);
+ snd_als300_gcr_write(chip->port, PLAYBACK_END,
+ runtime->dma_addr + buffer_bytes - 1);
+ spin_unlock_irq(&chip->reg_lock);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_capture_prepare(struct snd_pcm_substream *substream)
+{
+ u32 tmp;
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
+ unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+
+ snd_als300_dbgcallenter();
+ spin_lock_irq(&chip->reg_lock);
+ tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL);
+ tmp &= ~TRANSFER_START;
+
+ snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", period_bytes,
+ buffer_bytes);
+
+ /* set block size */
+ tmp &= 0xffff0000;
+ tmp |= period_bytes - 1;
+
+ /* set dma area */
+ snd_als300_gcr_write(chip->port, RECORD_CONTROL, tmp);
+ snd_als300_gcr_write(chip->port, RECORD_START,
+ runtime->dma_addr);
+ snd_als300_gcr_write(chip->port, RECORD_END,
+ runtime->dma_addr + buffer_bytes - 1);
+ spin_unlock_irq(&chip->reg_lock);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ u32 tmp;
+ struct snd_als300_substream_data *data;
+ unsigned short reg;
+ int ret = 0;
+
+ data = substream->runtime->private_data;
+ reg = data->control_register;
+
+ snd_als300_dbgcallenter();
+ spin_lock(&chip->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ data->period_flipflop = 1;
+ snd_als300_gcr_write(chip->port, reg, tmp | TRANSFER_START);
+ snd_als300_dbgplay("TRIGGER START\n");
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ snd_als300_gcr_write(chip->port, reg, tmp & ~TRANSFER_START);
+ snd_als300_dbgplay("TRIGGER STOP\n");
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ snd_als300_gcr_write(chip->port, reg, tmp | FIFO_PAUSE);
+ snd_als300_dbgplay("TRIGGER PAUSE\n");
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ snd_als300_gcr_write(chip->port, reg, tmp & ~FIFO_PAUSE);
+ snd_als300_dbgplay("TRIGGER RELEASE\n");
+ break;
+ default:
+ snd_als300_dbgplay("TRIGGER INVALID\n");
+ ret = -EINVAL;
+ }
+ spin_unlock(&chip->reg_lock);
+ snd_als300_dbgcallleave();
+ return ret;
+}
+
+static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
+{
+ u16 current_ptr;
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_als300_substream_data *data;
+ unsigned short period_bytes;
+
+ data = substream->runtime->private_data;
+ period_bytes = snd_pcm_lib_period_bytes(substream);
+
+ snd_als300_dbgcallenter();
+ spin_lock(&chip->reg_lock);
+ current_ptr = (u16) snd_als300_gcr_read(chip->port,
+ data->block_counter_register) + 4;
+ spin_unlock(&chip->reg_lock);
+ if (current_ptr > period_bytes)
+ current_ptr = 0;
+ else
+ current_ptr = period_bytes - current_ptr;
+
+ if (data->period_flipflop == 0)
+ current_ptr += period_bytes;
+ snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr);
+ snd_als300_dbgcallleave();
+ return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+static struct snd_pcm_ops snd_als300_playback_ops = {
+ .open = snd_als300_playback_open,
+ .close = snd_als300_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_als300_pcm_hw_params,
+ .hw_free = snd_als300_pcm_hw_free,
+ .prepare = snd_als300_playback_prepare,
+ .trigger = snd_als300_trigger,
+ .pointer = snd_als300_pointer,
+};
+
+static struct snd_pcm_ops snd_als300_capture_ops = {
+ .open = snd_als300_capture_open,
+ .close = snd_als300_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_als300_pcm_hw_params,
+ .hw_free = snd_als300_pcm_hw_free,
+ .prepare = snd_als300_capture_prepare,
+ .trigger = snd_als300_trigger,
+ .pointer = snd_als300_pointer,
+};
+
+static int __devinit snd_als300_new_pcm(struct snd_als300 *chip)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ snd_als300_dbgcallenter();
+ err = snd_pcm_new(chip->card, "ALS300", 0, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, "ALS300");
+ chip->pcm = pcm;
+
+ /* set operators */
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_als300_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_als300_capture_ops);
+
+ /* pre-allocation of buffers */
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static void snd_als300_init(struct snd_als300 *chip)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ snd_als300_dbgcallenter();
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16)
+ & 0x0000000F;
+ /* Setup DRAM */
+ tmp = snd_als300_gcr_read(chip->port, DRAM_WRITE_CONTROL);
+ snd_als300_gcr_write(chip->port, DRAM_WRITE_CONTROL,
+ (tmp | DRAM_MODE_2)
+ & ~WRITE_TRANS_START);
+
+ /* Enable IRQ output */
+ snd_als300_set_irq_flag(chip, IRQ_ENABLE);
+
+ /* Unmute hardware devices so their outputs get routed to
+ * the onboard mixer */
+ tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL);
+ snd_als300_gcr_write(chip->port, MISC_CONTROL,
+ tmp | VMUTE_NORMAL | MMUTE_NORMAL);
+
+ /* Reset volumes */
+ snd_als300_gcr_write(chip->port, MUS_VOC_VOL, 0);
+
+ /* Make sure playback transfer is stopped */
+ tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL);
+ snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL,
+ tmp & ~TRANSFER_START);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_als300_dbgcallleave();
+}
+
+static int __devinit snd_als300_create(snd_card_t *card,
+ struct pci_dev *pci, int chip_type,
+ struct snd_als300 **rchip)
+{
+ struct snd_als300 *chip;
+ void *irq_handler;
+ int err;
+
+ static snd_device_ops_t ops = {
+ .dev_free = snd_als300_dev_free,
+ };
+ *rchip = NULL;
+
+ snd_als300_dbgcallenter();
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
+ printk(KERN_ERR "error setting 28bit DMA mask\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+ pci_set_master(pci);
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ chip->chip_type = chip_type;
+ spin_lock_init(&chip->reg_lock);
+
+ if ((err = pci_request_regions(pci, "ALS300")) < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+ chip->port = pci_resource_start(pci, 0);
+
+ if (chip->chip_type == DEVICE_ALS300_PLUS)
+ irq_handler = snd_als300plus_interrupt;
+ else
+ irq_handler = snd_als300_interrupt;
+
+ if (request_irq(pci->irq, irq_handler, SA_INTERRUPT|SA_SHIRQ,
+ card->shortname, (void *)chip)) {
+ snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+ snd_als300_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+
+ snd_als300_init(chip);
+
+ if (snd_als300_ac97(chip) < 0) {
+ snd_printk(KERN_WARNING "Could not create ac97\n");
+ snd_als300_free(chip);
+ return err;
+ }
+
+ if ((err = snd_als300_new_pcm(chip)) < 0) {
+ snd_printk(KERN_WARNING "Could not create PCM\n");
+ snd_als300_free(chip);
+ return err;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+ chip, &ops)) < 0) {
+ snd_als300_free(chip);
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_als300 *chip = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
+
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int snd_als300_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_als300 *chip = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ snd_als300_init(chip);
+ snd_ac97_resume(chip->ac97);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+static int __devinit snd_als300_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct snd_als300 *chip;
+ int err, chip_type;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+
+ if (card == NULL)
+ return -ENOMEM;
+
+ chip_type = pci_id->driver_data;
+
+ if ((err = snd_als300_create(card, pci, chip_type, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ card->private_data = chip;
+
+ strcpy(card->driver, "ALS300");
+ if (chip->chip_type == DEVICE_ALS300_PLUS)
+ /* don't know much about ALS300+ yet
+ * print revision number for now */
+ sprintf(card->shortname, "ALS300+ (Rev. %d)", chip->revision);
+ else
+ sprintf(card->shortname, "ALS300 (Rev. %c)", 'A' +
+ chip->revision - 1);
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->port, chip->irq);
+
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+}
+
+static struct pci_driver driver = {
+ .name = "ALS300",
+ .id_table = snd_als300_ids,
+ .probe = snd_als300_probe,
+ .remove = __devexit_p(snd_als300_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_als300_suspend,
+ .resume = snd_als300_resume,
+#endif
+};
+
+static int __init alsa_card_als300_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_als300_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_als300_init)
+module_exit(alsa_card_als300_exit)
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index d65ccb1866a0..f078b716d2b0 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -19,7 +19,6 @@
#ifdef __KERNEL__
#include <sound/driver.h>
-#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <sound/core.h>
@@ -277,14 +276,14 @@ static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en);
#endif
/* Driver stuff. */
-static int __devinit vortex_gameport_register(vortex_t * card);
+static int vortex_gameport_register(vortex_t * card);
static void vortex_gameport_unregister(vortex_t * card);
#ifndef CHIP_AU8820
-static int __devinit vortex_eq_init(vortex_t * vortex);
-static int __devexit vortex_eq_free(vortex_t * vortex);
+static int vortex_eq_init(vortex_t * vortex);
+static int vortex_eq_free(vortex_t * vortex);
#endif
/* ALSA stuff. */
-static int __devinit snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr);
-static int __devinit snd_vortex_mixer(vortex_t * vortex);
-static int __devinit snd_vortex_midi(vortex_t * vortex);
+static int snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr);
+static int snd_vortex_mixer(vortex_t * vortex);
+static int snd_vortex_midi(vortex_t * vortex);
#endif
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 9cac02e93b25..4347e6abc1d5 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2658,7 +2658,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
/* Initialization */
-static int vortex_core_init(vortex_t * vortex)
+static int __devinit vortex_core_init(vortex_t * vortex)
{
printk(KERN_INFO "Vortex: init.... ");
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 64fbfbbaf816..0c86a31c4336 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -885,7 +885,7 @@ static char *EqBandLabels[10] __devinitdata = {
};
/* ALSA driver entry points. Init and exit. */
-static int vortex_eq_init(vortex_t * vortex)
+static int __devinit vortex_eq_init(vortex_t * vortex)
{
struct snd_kcontrol *kcontrol;
int err, i;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 6a13ca1d545e..7b5baa173859 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -506,7 +506,7 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
int i;
int err, nr_capt;
- if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
+ if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
return -ENODEV;
/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 4f65ec56bf35..ac4e73f69c1d 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1046,7 +1046,7 @@ static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol,
snd_cs4281_pokeBA0(chip, regL, volL);
change = 1;
}
- if (ucontrol->value.integer.value[0] != volL) {
+ if (ucontrol->value.integer.value[1] != volR) {
volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK);
snd_cs4281_pokeBA0(chip, regR, volR);
change = 1;
@@ -1416,7 +1416,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card,
static int snd_cs4281_chip_init(struct cs4281 *chip)
{
unsigned int tmp;
- int timeout;
+ unsigned long end_time;
int retry_count = 2;
/* Having EPPMC.FPDN=1 prevent proper chip initialisation */
@@ -1496,7 +1496,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
/*
* Wait for the DLL ready signal from the clock logic.
*/
- timeout = 100;
+ end_time = jiffies + HZ;
do {
/*
* Read the AC97 status register to see if we've seen a CODEC
@@ -1504,8 +1504,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
*/
if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
goto __ok0;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "DLLRDY not seen\n");
return -EIO;
@@ -1522,7 +1522,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
/*
* Wait for the codec ready signal from the AC97 codec.
*/
- timeout = 100;
+ end_time = jiffies + HZ;
do {
/*
* Read the AC97 status register to see if we've seen a CODEC
@@ -1530,20 +1530,20 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
*/
if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
goto __ok1;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
return -EIO;
__ok1:
if (chip->dual_codec) {
- timeout = 100;
+ end_time = jiffies + HZ;
do {
if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
goto __codec2_ok;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
chip->dual_codec = 0;
__codec2_ok: ;
@@ -1561,7 +1561,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
* the codec is pumping ADC data across the AC-link.
*/
- timeout = 100;
+ end_time = jiffies + HZ;
do {
/*
* Read the input slot valid register and see if input slots 3
@@ -1569,8 +1569,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
*/
if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
goto __ok2;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
if (--retry_count > 0)
goto __retry;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 31cb9b48bb59..6bfa08436efa 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -843,8 +843,11 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.ac97_chip = 1} ,
/* Tested by shane-alsa@cm.nu 5th Nov 2005 */
+ /* The 0x20061102 does have SB0350 written on it
+ * Just like 0x20021102
+ */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
- .driver = "Audigy2", .name = "Audigy 2 [2006]",
+ .driver = "Audigy2", .name = "Audigy 2 [SB0350b]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b42dff7ceed0..5bee3b536478 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -295,7 +295,7 @@ static int init_unsol_queue(struct hda_bus *bus)
snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
return -ENOMEM;
}
- unsol->workq = create_workqueue("hda_codec");
+ unsol->workq = create_singlethread_workqueue("hda_codec");
if (! unsol->workq) {
snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
kfree(unsol);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c096606970ff..0ad60ae29011 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -81,6 +81,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ESB2},"
"{Intel, ICH8},"
"{ATI, SB450},"
+ "{ATI, SB600},"
"{VIA, VT8251},"
"{VIA, VT8237A},"
"{SiS, SIS966},"
@@ -1619,6 +1620,7 @@ static struct pci_device_id azx_ids[] = {
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
+ { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 32401bd8c229..bcfca159c6a2 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -44,6 +44,7 @@ struct ad198x_spec {
* dig_out_nid and hp_nid are optional
*/
unsigned int cur_eapd;
+ unsigned int need_dac_fix;
/* capture */
unsigned int num_adc_nids;
@@ -800,6 +801,10 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
.config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1213,
.config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
+ .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
{}
};
@@ -836,10 +841,14 @@ static int patch_ad1986a(struct hda_codec *codec)
case AD1986A_3STACK:
spec->num_mixers = 2;
spec->mixers[1] = ad1986a_3st_mixers;
- spec->num_init_verbs = 2;
+ spec->num_init_verbs = 3;
spec->init_verbs[1] = ad1986a_3st_init_verbs;
+ spec->init_verbs[2] = ad1986a_ch2_init;
spec->channel_mode = ad1986a_modes;
spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
+ spec->need_dac_fix = 1;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
break;
case AD1986A_LAPTOP:
spec->mixers[0] = ad1986a_laptop_mixers;
@@ -1325,6 +1334,8 @@ static struct hda_board_config ad1981_cfg_tbl[] = {
.config = AD1981_HP }, /* HP nx6320 */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x309f,
.config = AD1981_HP }, /* HP nx9420 AngelFire */
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x30a2,
+ .config = AD1981_HP }, /* HP nx9420 AngelFire */
{ .modelname = "basic", .config = AD1981_BASIC },
{}
};
@@ -1555,6 +1566,8 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
+ if (spec->need_dac_fix)
+ spec->multiout.num_dacs = spec->multiout.max_channels / 2;
return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
spec->num_channel_mode, &spec->multiout.max_channels);
}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4c6c9ec8ea5b..66bbdb60f50b 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -52,6 +52,7 @@ enum {
ALC880_CLEVO,
ALC880_TCL_S700,
ALC880_LG,
+ ALC880_LG_LW,
#ifdef CONFIG_SND_DEBUG
ALC880_TEST,
#endif
@@ -131,6 +132,7 @@ struct alc_spec {
hda_nid_t dig_in_nid; /* digital-in NID; optional */
/* capture source */
+ unsigned int num_mux_defs;
const struct hda_input_mux *input_mux;
unsigned int cur_mux[3];
@@ -172,6 +174,7 @@ struct alc_config_preset {
hda_nid_t dig_in_nid;
unsigned int num_channel_mode;
const struct hda_channel_mode *channel_mode;
+ unsigned int num_mux_defs;
const struct hda_input_mux *input_mux;
void (*unsol_event)(struct hda_codec *, unsigned int);
void (*init_hook)(struct hda_codec *);
@@ -185,7 +188,10 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- return snd_hda_input_mux_info(spec->input_mux, uinfo);
+ unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
+ if (mux_idx >= spec->num_mux_defs)
+ mux_idx = 0;
+ return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
}
static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -203,7 +209,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+ unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+ return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
}
@@ -245,7 +252,8 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
* states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
* are requested. Therefore order this list so that this behaviour will not
* cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour.
+ * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
+ * March 2006.
*/
static char *alc_pin_mode_names[] = {
"Mic 50pc bias", "Mic 80pc bias",
@@ -255,19 +263,27 @@ static unsigned char alc_pin_mode_values[] = {
PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
};
/* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin.
+ * in the pin being assumed to be exclusively an input or an output pin. In
+ * addition, "input" pins may or may not process the mic bias option
+ * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
+ * accept requests for bias as of chip versions up to March 2006) and/or
+ * wiring in the computer.
*/
-#define ALC_PIN_DIR_IN 0x00
-#define ALC_PIN_DIR_OUT 0x01
-#define ALC_PIN_DIR_INOUT 0x02
+#define ALC_PIN_DIR_IN 0x00
+#define ALC_PIN_DIR_OUT 0x01
+#define ALC_PIN_DIR_INOUT 0x02
+#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
+#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
-/* Info about the pin modes supported by the three different pin directions.
+/* Info about the pin modes supported by the different pin direction modes.
* For each direction the minimum and maximum values are given.
*/
-static signed char alc_pin_mode_dir_info[3][2] = {
+static signed char alc_pin_mode_dir_info[5][2] = {
{ 0, 2 }, /* ALC_PIN_DIR_IN */
{ 3, 4 }, /* ALC_PIN_DIR_OUT */
{ 0, 4 }, /* ALC_PIN_DIR_INOUT */
+ { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
+ { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
};
#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
@@ -329,9 +345,10 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
* input modes.
*
* Dynamically switching the input/output buffers probably
- * reduces noise slightly, particularly on input. However,
- * havingboth input and output buffers enabled
- * simultaneously doesn't seem to be problematic.
+ * reduces noise slightly (particularly on input) so we'll
+ * do it. However, having both input and output buffers
+ * enabled simultaneously doesn't seem to be problematic if
+ * this turns out to be necessary in the future.
*/
if (val <= 2) {
snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
@@ -483,6 +500,9 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *
spec->multiout.dig_out_nid = preset->dig_out_nid;
spec->multiout.hp_nid = preset->hp_nid;
+ spec->num_mux_defs = preset->num_mux_defs;
+ if (! spec->num_mux_defs)
+ spec->num_mux_defs = 1;
spec->input_mux = preset->input_mux;
spec->num_adc_nids = preset->num_adc_nids;
@@ -1427,6 +1447,82 @@ static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
}
/*
+ * LG LW20
+ *
+ * Pin assignment:
+ * Speaker-out: 0x14
+ * Mic-In: 0x18
+ * Built-in Mic-In: 0x19 (?)
+ * HP-Out: 0x1b
+ * SPDIF-Out: 0x1e
+ */
+
+/* seems analog CD is not working */
+static struct hda_input_mux alc880_lg_lw_capture_source = {
+ .num_items = 2,
+ .items = {
+ { "Mic", 0x0 },
+ { "Internal Mic", 0x1 },
+ },
+};
+
+static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ { } /* end */
+};
+
+static struct hda_verb alc880_lg_lw_init_verbs[] = {
+ /* set capture source to mic-in */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ /* speaker-out */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* HP-out */
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* mic-in to input */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* built-in mic */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* jack sense */
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
+ { }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_lg_lw_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+}
+
+static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ /* Looks like the unsol event is incompatible with the standard
+ * definition. 4bit tag is placed at 28 bit!
+ */
+ if ((res >> 28) == 0x01)
+ alc880_lg_lw_automute(codec);
+}
+
+/*
* Common callbacks
*/
@@ -2078,6 +2174,9 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .modelname = "lg", .config = ALC880_LG },
{ .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
+ { .modelname = "lg-lw", .config = ALC880_LG_LW },
+ { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
+
#ifdef CONFIG_SND_DEBUG
{ .modelname = "test", .config = ALC880_TEST },
#endif
@@ -2268,6 +2367,19 @@ static struct alc_config_preset alc880_presets[] = {
.unsol_event = alc880_lg_unsol_event,
.init_hook = alc880_lg_automute,
},
+ [ALC880_LG_LW] = {
+ .mixers = { alc880_lg_lw_mixer },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_lg_lw_init_verbs },
+ .num_dacs = 1,
+ .dac_nids = alc880_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ .channel_mode = alc880_2_jack_modes,
+ .input_mux = &alc880_lg_lw_capture_source,
+ .unsol_event = alc880_lg_lw_unsol_event,
+ .init_hook = alc880_lg_lw_automute,
+ },
#ifdef CONFIG_SND_DEBUG
[ALC880_TEST] = {
.mixers = { alc880_test_mixer },
@@ -2593,6 +2705,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
return 1;
@@ -2722,30 +2835,56 @@ static struct hda_input_mux alc260_capture_source = {
};
/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines.
+ * headphone jack and the internal CD lines since these are the only pins at
+ * which audio can appear. For flexibility, also allow the option of
+ * recording the mixer output on the second ADC (ADC0 doesn't have a
+ * connection to the mixer output).
*/
-static struct hda_input_mux alc260_fujitsu_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic/Line", 0x0 },
- { "CD", 0x4 },
- { "Headphone", 0x2 },
+static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
+ {
+ .num_items = 3,
+ .items = {
+ { "Mic/Line", 0x0 },
+ { "CD", 0x4 },
+ { "Headphone", 0x2 },
+ },
},
+ {
+ .num_items = 4,
+ .items = {
+ { "Mic/Line", 0x0 },
+ { "CD", 0x4 },
+ { "Headphone", 0x2 },
+ { "Mixer", 0x5 },
+ },
+ },
+
};
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to
- * the Fujitsu S702x, but jacks are marked differently. We won't allow
- * retasking the Headphone jack, so it won't be available here.
+/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
+ * the Fujitsu S702x, but jacks are marked differently.
*/
-static struct hda_input_mux alc260_acer_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
+static struct hda_input_mux alc260_acer_capture_sources[2] = {
+ {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ { "Headphone", 0x5 },
+ },
+ },
+ {
+ .num_items = 5,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ { "Headphone", 0x6 },
+ { "Mixer", 0x5 },
+ },
},
};
-
/*
* This is just place-holder, so there's something for alc_build_pcms to look
* at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -2806,6 +2945,9 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
{ } /* end */
};
+/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
+ * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
+ */
static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
@@ -2822,9 +2964,28 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
{ } /* end */
};
+/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
+ * versions of the ALC260 don't act on requests to enable mic bias from NID
+ * 0x0f (used to drive the headphone jack in these laptops). The ALC260
+ * datasheet doesn't mention this restriction. At this stage it's not clear
+ * whether this behaviour is intentional or is a hardware bug in chip
+ * revisions available in early 2006. Therefore for now allow the
+ * "Headphone Jack Mode" control to span all choices, but if it turns out
+ * that the lack of mic bias for this NID is intentional we could change the
+ * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ *
+ * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
+ * don't appear to make the mic bias available from the "line" jack, even
+ * though the NID used for this jack (0x14) can supply it. The theory is
+ * that perhaps Acer have included blocking capacitors between the ALC260
+ * and the output jack. If this turns out to be the case for all such
+ * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
+ * to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ */
static struct snd_kcontrol_new alc260_acer_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+ ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
@@ -3038,7 +3199,8 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = {
};
/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops.
+ * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
+ * audio = 0x16, internal speaker = 0x10.
*/
static struct hda_verb alc260_fujitsu_init_verbs[] = {
/* Disable all GPIOs */
@@ -3185,10 +3347,10 @@ static struct hda_verb alc260_acer_init_verbs[] = {
{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Do similar with the second ADC: mute capture input amp and
- * set ADC connection to line (on line1 pin)
+ * set ADC connection to mic to match ALSA's default state.
*/
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+ {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Mute all inputs to mixer widget (even unconnected ones) */
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
@@ -3213,26 +3375,35 @@ static hda_nid_t alc260_test_dac_nids[1] = {
static hda_nid_t alc260_test_adc_nids[2] = {
0x04, 0x05,
};
-/* This is a bit messy since the two input muxes in the ALC260 have slight
- * variations in their signal assignments. The ideal way to deal with this
- * is to extend alc_spec.input_mux to allow a different input MUX for each
- * ADC. For the purposes of the test model it's sufficient to just list
- * both options for affected signal indices. The separate input mux
- * functionality only needs to be considered if a model comes along which
- * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
- * record.
+/* For testing the ALC260, each input MUX needs its own definition since
+ * the signal assignments are different. This assumes that the first ADC
+ * is NID 0x04.
*/
-static struct hda_input_mux alc260_test_capture_source = {
- .num_items = 8,
- .items = {
- { "MIC1 pin", 0x0 },
- { "MIC2 pin", 0x1 },
- { "LINE1 pin", 0x2 },
- { "LINE2 pin", 0x3 },
- { "CD pin", 0x4 },
- { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
- { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
- { "HP-OUT pin (cap2 only)", 0x7 },
+static struct hda_input_mux alc260_test_capture_sources[2] = {
+ {
+ .num_items = 7,
+ .items = {
+ { "MIC1 pin", 0x0 },
+ { "MIC2 pin", 0x1 },
+ { "LINE1 pin", 0x2 },
+ { "LINE2 pin", 0x3 },
+ { "CD pin", 0x4 },
+ { "LINE-OUT pin", 0x5 },
+ { "HP-OUT pin", 0x6 },
+ },
+ },
+ {
+ .num_items = 8,
+ .items = {
+ { "MIC1 pin", 0x0 },
+ { "MIC2 pin", 0x1 },
+ { "LINE1 pin", 0x2 },
+ { "LINE2 pin", 0x3 },
+ { "CD pin", 0x4 },
+ { "Mixer", 0x5 },
+ { "LINE-OUT pin", 0x6 },
+ { "HP-OUT pin", 0x7 },
+ },
},
};
static struct snd_kcontrol_new alc260_test_mixer[] = {
@@ -3244,7 +3415,17 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
- /* Modes for retasking pin widgets */
+ /* Modes for retasking pin widgets
+ * Note: the ALC260 doesn't seem to act on requests to enable mic
+ * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
+ * mention this restriction. At this stage it's not clear whether
+ * this behaviour is intentional or is a hardware bug in chip
+ * revisions available at least up until early 2006. Therefore for
+ * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
+ * choices, but if it turns out that the lack of mic bias for these
+ * NIDs is intentional we could change their modes from
+ * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ */
ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
@@ -3606,6 +3787,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
/* check whether NID 0x04 is valid */
@@ -3711,7 +3893,8 @@ static struct alc_config_preset alc260_presets[] = {
.adc_nids = alc260_dual_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
- .input_mux = &alc260_fujitsu_capture_source,
+ .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
+ .input_mux = alc260_fujitsu_capture_sources,
},
[ALC260_ACER] = {
.mixers = { alc260_acer_mixer,
@@ -3723,7 +3906,8 @@ static struct alc_config_preset alc260_presets[] = {
.adc_nids = alc260_dual_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
- .input_mux = &alc260_acer_capture_source,
+ .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
+ .input_mux = alc260_acer_capture_sources,
},
#ifdef CONFIG_SND_DEBUG
[ALC260_TEST] = {
@@ -3736,7 +3920,8 @@ static struct alc_config_preset alc260_presets[] = {
.adc_nids = alc260_test_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
- .input_mux = &alc260_test_capture_source,
+ .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
+ .input_mux = alc260_test_capture_sources,
},
#endif
};
@@ -3828,7 +4013,6 @@ static struct hda_input_mux alc882_capture_source = {
{ "CD", 0x4 },
},
};
-
#define alc882_mux_enum_info alc_mux_enum_info
#define alc882_mux_enum_get alc_mux_enum_get
@@ -4730,6 +4914,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
return 1;
@@ -5406,6 +5591,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
spec->adc_nids = alc861_adc_nids;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index b56ca4019392..715260787953 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -310,6 +310,9 @@ static struct hda_board_config stac922x_cfg_tbl[] = {
.pci_subdevice = 0x0b0b,
.config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack, 9221 A1 */
{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x0707,
+ .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */
+ { .pci_subvendor = PCI_VENDOR_ID_INTEL,
.pci_subdevice = 0x0404,
.config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */
{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
@@ -534,6 +537,22 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
return 0;
}
+static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int pincap = snd_hda_param_read(codec, nid,
+ AC_PAR_PIN_CAP);
+ pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
+ if (pincap & AC_PINCAP_VREF_100)
+ return AC_PINCTL_VREF_100;
+ if (pincap & AC_PINCAP_VREF_80)
+ return AC_PINCTL_VREF_80;
+ if (pincap & AC_PINCAP_VREF_50)
+ return AC_PINCTL_VREF_50;
+ if (pincap & AC_PINCAP_VREF_GRD)
+ return AC_PINCTL_VREF_GRD;
+ return 0;
+}
+
static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
{
@@ -571,9 +590,12 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
if (val)
stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
- else
- stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
-
+ else {
+ unsigned int pinctl = AC_PINCTL_IN_EN;
+ if (io_idx) /* set VREF for mic */
+ pinctl |= stac92xx_get_vref(codec, nid);
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
+ }
return 1;
}
@@ -767,13 +789,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin
return 0;
wid_caps = get_wcaps(codec, pin);
- if (wid_caps & AC_WCAP_UNSOL_CAP) {
- /* Enable unsolicited responses on the HP widget */
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- STAC_UNSOL_ENABLE);
+ if (wid_caps & AC_WCAP_UNSOL_CAP)
spec->hp_detect = 1;
- }
nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
for (i = 0; i < cfg->line_outs; i++) {
@@ -896,13 +913,8 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec,
return 0;
wid_caps = get_wcaps(codec, pin);
- if (wid_caps & AC_WCAP_UNSOL_CAP) {
- /* Enable unsolicited responses on the HP widget */
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- STAC_UNSOL_ENABLE);
+ if (wid_caps & AC_WCAP_UNSOL_CAP)
spec->hp_detect = 1;
- }
return 0;
}
@@ -944,6 +956,10 @@ static int stac92xx_init(struct hda_codec *codec)
/* set up pins */
if (spec->hp_detect) {
+ /* Enable unsolicited responses on the HP widget */
+ snd_hda_codec_write(codec, cfg->hp_pin, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ STAC_UNSOL_ENABLE);
/* fake event to set up pins */
codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
} else {
@@ -951,9 +967,13 @@ static int stac92xx_init(struct hda_codec *codec)
stac92xx_auto_init_hp_out(codec);
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
- if (cfg->input_pins[i])
- stac92xx_auto_set_pinctl(codec, cfg->input_pins[i],
- AC_PINCTL_IN_EN);
+ hda_nid_t nid = cfg->input_pins[i];
+ if (nid) {
+ unsigned int pinctl = AC_PINCTL_IN_EN;
+ if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC)
+ pinctl |= stac92xx_get_vref(codec, nid);
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
+ }
}
if (cfg->dig_out_pin)
stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 7e6608b14abc..336dc489aee1 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -87,7 +87,151 @@
#define CS8415_C_BUFFER 0x20
#define CS8415_ID 0x7F
-static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
+/* PCA9554 registers */
+#define PCA9554_DEV 0x40 /* I2C device address */
+#define PCA9554_IN 0x00 /* input port */
+#define PCA9554_OUT 0x01 /* output port */
+#define PCA9554_INVERT 0x02 /* input invert */
+#define PCA9554_DIR 0x03 /* port directions */
+
+/*
+ * Aureon Universe additional controls using PCA9554
+ */
+
+/*
+ * Send data to pca9554
+ */
+static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
+ unsigned char data)
+{
+ unsigned int tmp;
+ int i, j;
+ unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
+ unsigned char val = 0;
+
+ tmp = snd_ice1712_gpio_read(ice);
+
+ snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
+ AUREON_WM_RW|AUREON_WM_CS|
+ AUREON_CS8415_CS));
+ tmp |= AUREON_WM_RW;
+ tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
+
+ tmp &= ~AUREON_SPI_MOSI;
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+
+ /*
+ * send i2c stop condition and start condition
+ * to obtain sane state
+ */
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+ tmp |= AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(100);
+ tmp &= ~AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(100);
+ /*
+ * send device address, command and value,
+ * skipping ack cycles inbetween
+ */
+ for (j = 0; j < 3; j++) {
+ switch(j) {
+ case 0: val = dev; break;
+ case 1: val = reg; break;
+ case 2: val = data; break;
+ }
+ for (i = 7; i >= 0; i--) {
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ if (val & (1 << i))
+ tmp |= AUREON_SPI_MOSI;
+ else
+ tmp &= ~AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ }
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ }
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp &= ~AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+ tmp |= AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(100);
+}
+
+static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out;
+ return 0;
+}
+
+static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ unsigned char oval, nval;
+ int change;
+
+ snd_ice1712_save_gpio_status(ice);
+
+ oval = ice->spec.aureon.pca9554_out;
+ nval = ucontrol->value.integer.value[0];
+ if ((change = (oval != nval))) {
+ aureon_pca9554_write(ice, PCA9554_OUT, nval);
+ ice->spec.aureon.pca9554_out = nval;
+ }
+ snd_ice1712_restore_gpio_status(ice);
+
+ return change;
+}
+
+
+static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
+ unsigned short val)
+{
unsigned int tmp;
/* Send address to XILINX chip */
@@ -146,7 +290,8 @@ static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short r
/*
* Initialize STAC9744 chip
*/
-static int aureon_ac97_init (struct snd_ice1712 *ice) {
+static int aureon_ac97_init (struct snd_ice1712 *ice)
+{
int i;
static unsigned short ac97_defaults[] = {
0x00, 0x9640,
@@ -1598,7 +1743,15 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
.get = aureon_ac97_vol_get,
.put = aureon_ac97_vol_put,
.private_value = AC97_VIDEO|AUREON_AC97_STEREO
- }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Aux Source",
+ .info = aureon_universe_inmux_info,
+ .get = aureon_universe_inmux_get,
+ .put = aureon_universe_inmux_put
+ }
+
};
@@ -1856,6 +2009,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
}
snd_ice1712_restore_gpio_status(ice);
+
+ /* initialize PCA9554 pin directions & set default input*/
+ aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
+ aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
ice->spec.aureon.master[0] = WM_VOL_MUTE;
ice->spec.aureon.master[1] = WM_VOL_MUTE;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index b88eeba2f5d1..32f8415558a5 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2402,7 +2402,7 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) {
/* Limit active ADCs and DACs to 6; */
/* Note: DXR extension not supported */
- pci_write_config_byte(ice->pci, 0x60, 0x0a);
+ pci_write_config_byte(ice->pci, 0x60, 0x2a);
} else {
pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]);
}
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index f9b22d4a3932..053f8e56fd68 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -373,6 +373,7 @@ struct snd_ice1712 {
unsigned int cs8415_mux;
unsigned short master[2];
unsigned short vol[8];
+ unsigned char pca9554_out;
} aureon;
/* AC97 register cache for Phase28 */
struct phase28_spec {
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 44393e190929..9c90d901e6b9 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -831,8 +831,8 @@ struct snd_m3 {
struct snd_pcm *pcm;
struct pci_dev *pci;
- struct m3_quirk *quirk;
- struct m3_hv_quirk *hv_quirk;
+ const struct m3_quirk *quirk;
+ const struct m3_hv_quirk *hv_quirk;
int dacs_active;
int timer_users;
@@ -892,7 +892,7 @@ static struct pci_device_id snd_m3_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_m3_ids);
-static struct m3_quirk m3_quirk_list[] = {
+static const struct m3_quirk m3_quirk_list[] = {
/* panasonic CF-28 "toughbook" */
{
.name = "Panasonic CF-28",
@@ -950,7 +950,7 @@ static struct m3_quirk m3_quirk_list[] = {
};
/* These values came from the Windows driver. */
-static struct m3_hv_quirk m3_hv_quirk_list[] = {
+static const struct m3_hv_quirk m3_hv_quirk_list[] = {
/* Allegro chips */
{ 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
{ 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
@@ -1361,7 +1361,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s,
}
-static struct play_vals {
+static const struct play_vals {
u16 addr, val;
} pv[] = {
{CDATA_LEFT_VOLUME, ARB_VOLUME},
@@ -1428,7 +1428,7 @@ snd_m3_playback_setup(struct snd_m3 *chip, struct m3_dma *s,
/*
* Native record driver
*/
-static struct rec_vals {
+static const struct rec_vals {
u16 addr, val;
} rv[] = {
{CDATA_LEFT_VOLUME, ARB_VOLUME},
@@ -1598,12 +1598,26 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
if (! s->running)
return;
- hwptr = snd_m3_get_pointer(chip, s, subs) % s->dma_size;
- diff = (s->dma_size + hwptr - s->hwptr) % s->dma_size;
+ hwptr = snd_m3_get_pointer(chip, s, subs);
+
+ /* try to avoid expensive modulo divisions */
+ if (hwptr >= s->dma_size)
+ hwptr %= s->dma_size;
+
+ diff = s->dma_size + hwptr - s->hwptr;
+ if (diff >= s->dma_size)
+ diff %= s->dma_size;
+
s->hwptr = hwptr;
s->count += diff;
+
if (s->count >= (signed)s->period_size) {
- s->count %= s->period_size;
+
+ if (s->count < 2 * (signed)s->period_size)
+ s->count -= (signed)s->period_size;
+ else
+ s->count %= s->period_size;
+
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(subs);
spin_lock(&chip->reg_lock);
@@ -1942,6 +1956,7 @@ static int snd_m3_ac97_wait(struct snd_m3 *chip)
do {
if (! (snd_m3_inb(chip, 0x30) & 1))
return 0;
+ cpu_relax();
} while (i-- > 0);
snd_printk(KERN_ERR "ac97 serial bus busy\n");
@@ -1953,16 +1968,18 @@ snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
struct snd_m3 *chip = ac97->private_data;
unsigned long flags;
- unsigned short data;
+ unsigned short data = 0xffff;
if (snd_m3_ac97_wait(chip))
- return 0xffff;
+ goto fail;
spin_lock_irqsave(&chip->ac97_lock, flags);
snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
if (snd_m3_ac97_wait(chip))
- return 0xffff;
+ goto fail_unlock;
data = snd_m3_inw(chip, CODEC_DATA);
+fail_unlock:
spin_unlock_irqrestore(&chip->ac97_lock, flags);
+fail:
return data;
}
@@ -2121,7 +2138,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
* DSP Code images
*/
-static u16 assp_kernel_image[] __devinitdata = {
+static const u16 assp_kernel_image[] __devinitdata = {
0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4,
0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4,
0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4,
@@ -2208,7 +2225,7 @@ static u16 assp_kernel_image[] __devinitdata = {
* Mini sample rate converter code image
* that is to be loaded at 0x400 on the DSP.
*/
-static u16 assp_minisrc_image[] __devinitdata = {
+static const u16 assp_minisrc_image[] __devinitdata = {
0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412,
0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41,
@@ -2251,7 +2268,7 @@ static u16 assp_minisrc_image[] __devinitdata = {
*/
#define MINISRC_LPF_LEN 10
-static u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
+static const u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C,
0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F
};
@@ -2358,7 +2375,7 @@ static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma
*/
/*
- * align instance address to 256 bytes so that it's
+ * align instance address to 256 bytes so that its
* shifted list address is aligned.
* list address = (mem address >> 1) >> 7;
*/
@@ -2647,8 +2664,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
{
struct snd_m3 *chip;
int i, err;
- struct m3_quirk *quirk;
- struct m3_hv_quirk *hv_quirk;
+ const struct m3_quirk *quirk;
+ const struct m3_hv_quirk *hv_quirk;
static struct snd_device_ops ops = {
.dev_free = snd_m3_dev_free,
};
@@ -2843,12 +2860,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
}
#if 0 /* TODO: not supported yet */
- /* TODO enable midi irq and i/o */
+ /* TODO enable MIDI IRQ and I/O */
err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
chip->iobase + MPU401_DATA_PORT, 1,
chip->irq, 0, &chip->rmidi);
if (err < 0)
- printk(KERN_WARNING "maestro3: no midi support.\n");
+ printk(KERN_WARNING "maestro3: no MIDI support.\n");
#endif
pci_set_drvdata(pci, card);
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index fdc652c6992d..c40f59062684 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -274,12 +274,9 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilin
/* test first xilinx */
chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
- if (!second) {
- if (chipsc & PCXHR_CHIPSC_GPI_USERI) {
- snd_printdd("no need to load first xilinx\n");
- return 0; /* first xilinx is already present and cannot be reset */
- }
- } else {
+ /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */
+ /* this bit will always be 1; no possibility to test presence of first xilinx */
+ if(second) {
if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
snd_printk(KERN_ERR "error loading first xilinx\n");
return -EINVAL;
diff --git a/sound/pci/riptide/Makefile b/sound/pci/riptide/Makefile
new file mode 100644
index 000000000000..dcd2e64e4818
--- /dev/null
+++ b/sound/pci/riptide/Makefile
@@ -0,0 +1,3 @@
+snd-riptide-objs := riptide.o
+
+obj-$(CONFIG_SND_RIPTIDE) += snd-riptide.o
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
new file mode 100644
index 000000000000..f148ee434a6b
--- /dev/null
+++ b/sound/pci/riptide/riptide.c
@@ -0,0 +1,2223 @@
+/*
+ * Driver for the Conexant Riptide Soundchip
+ *
+ * Copyright (c) 2004 Peter Gruber <nokos@gmx.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ *
+ */
+/*
+ History:
+ - 02/15/2004 first release
+
+ This Driver is based on the OSS Driver version from Linuxant (riptide-0.6lnxtbeta03111100)
+ credits from the original files:
+
+ MODULE NAME: cnxt_rt.h
+ AUTHOR: K. Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 02/1/2000 KNL
+
+ MODULE NAME: int_mdl.c
+ AUTHOR: Konstantin Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 10/01/99 KNL
+
+ MODULE NAME: riptide.h
+ AUTHOR: O. Druzhinin (Transcribed by OLD)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 10/16/97 OLD
+
+ MODULE NAME: Rp_Cmdif.cpp
+ AUTHOR: O. Druzhinin (Transcribed by OLD)
+ K. Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Adopted from NT4 driver 6/22/99 OLD
+ Ported to Linux 9/01/99 KNL
+
+ MODULE NAME: rt_hw.c
+ AUTHOR: O. Druzhinin (Transcribed by OLD)
+ C. Lazarev (Transcribed by CNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 11/18/97 OLD
+ Hardware functions for RipTide 11/24/97 CNL
+ (ES1) are coded
+ Hardware functions for RipTide 12/24/97 CNL
+ (A0) are coded
+ Hardware functions for RipTide 03/20/98 CNL
+ (A1) are coded
+ Boot loader is included 05/07/98 CNL
+ Redesigned for WDM 07/27/98 CNL
+ Redesigned for Linux 09/01/99 CNL
+
+ MODULE NAME: rt_hw.h
+ AUTHOR: C. Lazarev (Transcribed by CNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 11/18/97 CNL
+
+ MODULE NAME: rt_mdl.c
+ AUTHOR: Konstantin Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 10/01/99 KNL
+
+ MODULE NAME: mixer.h
+ AUTHOR: K. Kenney
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created from MS W95 Sample 11/28/95 KRS
+ RipTide 10/15/97 KRS
+ Adopted for Windows NT driver 01/20/98 CNL
+*/
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/gameport.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/mpu401.h>
+#include <sound/opl3.h>
+#include <sound/initval.h>
+
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
+MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>");
+MODULE_DESCRIPTION("riptide");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+
+#ifdef SUPPORT_JOYSTICK
+static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 };
+#endif
+static int mpu_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x330 };
+static int opl3_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x388 };
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Riptide soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Riptide soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Riptide soundcard.");
+#ifdef SUPPORT_JOYSTICK
+module_param_array(joystick_port, int, NULL, 0444);
+MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard.");
+#endif
+module_param_array(mpu_port, int, NULL, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver.");
+module_param_array(opl3_port, int, NULL, 0444);
+MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
+
+/*
+ */
+
+#define MPU401_HW_RIPTIDE MPU401_HW_MPU401
+#define OPL3_HW_RIPTIDE OPL3_HW_OPL3
+
+#define PCI_EXT_CapId 0x40
+#define PCI_EXT_NextCapPrt 0x41
+#define PCI_EXT_PWMC 0x42
+#define PCI_EXT_PWSCR 0x44
+#define PCI_EXT_Data00 0x46
+#define PCI_EXT_PMSCR_BSE 0x47
+#define PCI_EXT_SB_Base 0x48
+#define PCI_EXT_FM_Base 0x4a
+#define PCI_EXT_MPU_Base 0x4C
+#define PCI_EXT_Game_Base 0x4E
+#define PCI_EXT_Legacy_Mask 0x50
+#define PCI_EXT_AsicRev 0x52
+#define PCI_EXT_Reserved3 0x53
+
+#define LEGACY_ENABLE_ALL 0x8000 /* legacy device options */
+#define LEGACY_ENABLE_SB 0x4000
+#define LEGACY_ENABLE_FM 0x2000
+#define LEGACY_ENABLE_MPU_INT 0x1000
+#define LEGACY_ENABLE_MPU 0x0800
+#define LEGACY_ENABLE_GAMEPORT 0x0400
+
+#define MAX_WRITE_RETRY 10 /* cmd interface limits */
+#define MAX_ERROR_COUNT 10
+#define CMDIF_TIMEOUT 500000
+#define RESET_TRIES 5
+
+#define READ_PORT_ULONG(p) inl((unsigned long)&(p))
+#define WRITE_PORT_ULONG(p,x) outl(x,(unsigned long)&(p))
+
+#define READ_AUDIO_CONTROL(p) READ_PORT_ULONG(p->audio_control)
+#define WRITE_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,x)
+#define UMASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)|x)
+#define MASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)&x)
+#define READ_AUDIO_STATUS(p) READ_PORT_ULONG(p->audio_status)
+
+#define SET_GRESET(p) UMASK_AUDIO_CONTROL(p,0x0001) /* global reset switch */
+#define UNSET_GRESET(p) MASK_AUDIO_CONTROL(p,~0x0001)
+#define SET_AIE(p) UMASK_AUDIO_CONTROL(p,0x0004) /* interrupt enable */
+#define UNSET_AIE(p) MASK_AUDIO_CONTROL(p,~0x0004)
+#define SET_AIACK(p) UMASK_AUDIO_CONTROL(p,0x0008) /* interrupt acknowledge */
+#define UNSET_AIACKT(p) MASKAUDIO_CONTROL(p,~0x0008)
+#define SET_ECMDAE(p) UMASK_AUDIO_CONTROL(p,0x0010)
+#define UNSET_ECMDAE(p) MASK_AUDIO_CONTROL(p,~0x0010)
+#define SET_ECMDBE(p) UMASK_AUDIO_CONTROL(p,0x0020)
+#define UNSET_ECMDBE(p) MASK_AUDIO_CONTROL(p,~0x0020)
+#define SET_EDATAF(p) UMASK_AUDIO_CONTROL(p,0x0040)
+#define UNSET_EDATAF(p) MASK_AUDIO_CONTROL(p,~0x0040)
+#define SET_EDATBF(p) UMASK_AUDIO_CONTROL(p,0x0080)
+#define UNSET_EDATBF(p) MASK_AUDIO_CONTROL(p,~0x0080)
+#define SET_ESBIRQON(p) UMASK_AUDIO_CONTROL(p,0x0100)
+#define UNSET_ESBIRQON(p) MASK_AUDIO_CONTROL(p,~0x0100)
+#define SET_EMPUIRQ(p) UMASK_AUDIO_CONTROL(p,0x0200)
+#define UNSET_EMPUIRQ(p) MASK_AUDIO_CONTROL(p,~0x0200)
+#define IS_CMDE(a) (READ_PORT_ULONG(a->stat)&0x1) /* cmd empty */
+#define IS_DATF(a) (READ_PORT_ULONG(a->stat)&0x2) /* data filled */
+#define IS_READY(p) (READ_AUDIO_STATUS(p)&0x0001)
+#define IS_DLREADY(p) (READ_AUDIO_STATUS(p)&0x0002)
+#define IS_DLERR(p) (READ_AUDIO_STATUS(p)&0x0004)
+#define IS_GERR(p) (READ_AUDIO_STATUS(p)&0x0008) /* error ! */
+#define IS_CMDAEIRQ(p) (READ_AUDIO_STATUS(p)&0x0010)
+#define IS_CMDBEIRQ(p) (READ_AUDIO_STATUS(p)&0x0020)
+#define IS_DATAFIRQ(p) (READ_AUDIO_STATUS(p)&0x0040)
+#define IS_DATBFIRQ(p) (READ_AUDIO_STATUS(p)&0x0080)
+#define IS_EOBIRQ(p) (READ_AUDIO_STATUS(p)&0x0100) /* interrupt status */
+#define IS_EOSIRQ(p) (READ_AUDIO_STATUS(p)&0x0200)
+#define IS_EOCIRQ(p) (READ_AUDIO_STATUS(p)&0x0400)
+#define IS_UNSLIRQ(p) (READ_AUDIO_STATUS(p)&0x0800)
+#define IS_SBIRQ(p) (READ_AUDIO_STATUS(p)&0x1000)
+#define IS_MPUIRQ(p) (READ_AUDIO_STATUS(p)&0x2000)
+
+#define RESP 0x00000001 /* command flags */
+#define PARM 0x00000002
+#define CMDA 0x00000004
+#define CMDB 0x00000008
+#define NILL 0x00000000
+
+#define LONG0(a) ((u32)a) /* shifts and masks */
+#define BYTE0(a) (LONG0(a)&0xff)
+#define BYTE1(a) (BYTE0(a)<<8)
+#define BYTE2(a) (BYTE0(a)<<16)
+#define BYTE3(a) (BYTE0(a)<<24)
+#define WORD0(a) (LONG0(a)&0xffff)
+#define WORD1(a) (WORD0(a)<<8)
+#define WORD2(a) (WORD0(a)<<16)
+#define TRINIB0(a) (LONG0(a)&0xffffff)
+#define TRINIB1(a) (TRINIB0(a)<<8)
+
+#define RET(a) ((union cmdret *)(a))
+
+#define SEND_GETV(p,b) sendcmd(p,RESP,GETV,0,RET(b)) /* get version */
+#define SEND_GETC(p,b,c) sendcmd(p,PARM|RESP,GETC,c,RET(b))
+#define SEND_GUNS(p,b) sendcmd(p,RESP,GUNS,0,RET(b))
+#define SEND_SCID(p,b) sendcmd(p,RESP,SCID,0,RET(b))
+#define SEND_RMEM(p,b,c,d) sendcmd(p,PARM|RESP,RMEM|BYTE1(b),LONG0(c),RET(d)) /* memory access for firmware write */
+#define SEND_SMEM(p,b,c) sendcmd(p,PARM,SMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */
+#define SEND_WMEM(p,b,c) sendcmd(p,PARM,WMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */
+#define SEND_SDTM(p,b,c) sendcmd(p,PARM|RESP,SDTM|TRINIB1(b),0,RET(c)) /* memory access for firmware write */
+#define SEND_GOTO(p,b) sendcmd(p,PARM,GOTO,LONG0(b),RET(0)) /* memory access for firmware write */
+#define SEND_SETDPLL(p) sendcmd(p,0,ARM_SETDPLL,0,RET(0))
+#define SEND_SSTR(p,b,c) sendcmd(p,PARM,SSTR|BYTE3(b),LONG0(c),RET(0)) /* start stream */
+#define SEND_PSTR(p,b) sendcmd(p,PARM,PSTR,BYTE3(b),RET(0)) /* pause stream */
+#define SEND_KSTR(p,b) sendcmd(p,PARM,KSTR,BYTE3(b),RET(0)) /* stop stream */
+#define SEND_KDMA(p) sendcmd(p,0,KDMA,0,RET(0)) /* stop all dma */
+#define SEND_GPOS(p,b,c,d) sendcmd(p,PARM|RESP,GPOS,BYTE3(c)|BYTE2(b),RET(d)) /* get position in dma */
+#define SEND_SETF(p,b,c,d,e,f,g) sendcmd(p,PARM,SETF|WORD1(b)|BYTE3(c),d|BYTE1(e)|BYTE2(f)|BYTE3(g),RET(0)) /* set sample format at mixer */
+#define SEND_GSTS(p,b,c,d) sendcmd(p,PARM|RESP,GSTS,BYTE3(c)|BYTE2(b),RET(d))
+#define SEND_NGPOS(p,b,c,d) sendcmd(p,PARM|RESP,NGPOS,BYTE3(c)|BYTE2(b),RET(d))
+#define SEND_PSEL(p,b,c) sendcmd(p,PARM,PSEL,BYTE2(b)|BYTE3(c),RET(0)) /* activate lbus path */
+#define SEND_PCLR(p,b,c) sendcmd(p,PARM,PCLR,BYTE2(b)|BYTE3(c),RET(0)) /* deactivate lbus path */
+#define SEND_PLST(p,b) sendcmd(p,PARM,PLST,BYTE3(b),RET(0))
+#define SEND_RSSV(p,b,c,d) sendcmd(p,PARM|RESP,RSSV,BYTE2(b)|BYTE3(c),RET(d))
+#define SEND_LSEL(p,b,c,d,e,f,g,h) sendcmd(p,PARM,LSEL|BYTE1(b)|BYTE2(c)|BYTE3(d),BYTE0(e)|BYTE1(f)|BYTE2(g)|BYTE3(h),RET(0)) /* select paths for internal connections */
+#define SEND_SSRC(p,b,c,d,e) sendcmd(p,PARM,SSRC|BYTE1(b)|WORD2(c),WORD0(d)|WORD2(e),RET(0)) /* configure source */
+#define SEND_SLST(p,b) sendcmd(p,PARM,SLST,BYTE3(b),RET(0))
+#define SEND_RSRC(p,b,c) sendcmd(p,RESP,RSRC|BYTE1(b),0,RET(c)) /* read source config */
+#define SEND_SSRB(p,b,c) sendcmd(p,PARM,SSRB|BYTE1(b),WORD2(c),RET(0))
+#define SEND_SDGV(p,b,c,d,e) sendcmd(p,PARM,SDGV|BYTE2(b)|BYTE3(c),WORD0(d)|WORD2(e),RET(0)) /* set digital mixer */
+#define SEND_RDGV(p,b,c,d) sendcmd(p,PARM|RESP,RDGV|BYTE2(b)|BYTE3(c),0,RET(d)) /* read digital mixer */
+#define SEND_DLST(p,b) sendcmd(p,PARM,DLST,BYTE3(b),RET(0))
+#define SEND_SACR(p,b,c) sendcmd(p,PARM,SACR,WORD0(b)|WORD2(c),RET(0)) /* set AC97 register */
+#define SEND_RACR(p,b,c) sendcmd(p,PARM|RESP,RACR,WORD2(b),RET(c)) /* get AC97 register */
+#define SEND_ALST(p,b) sendcmd(p,PARM,ALST,BYTE3(b),RET(0))
+#define SEND_TXAC(p,b,c,d,e,f) sendcmd(p,PARM,TXAC|BYTE1(b)|WORD2(c),WORD0(d)|BYTE2(e)|BYTE3(f),RET(0))
+#define SEND_RXAC(p,b,c,d) sendcmd(p,PARM|RESP,RXAC,BYTE2(b)|BYTE3(c),RET(d))
+#define SEND_SI2S(p,b) sendcmd(p,PARM,SI2S,WORD2(b),RET(0))
+
+#define EOB_STATUS 0x80000000 /* status flags : block boundary */
+#define EOS_STATUS 0x40000000 /* : stoppped */
+#define EOC_STATUS 0x20000000 /* : stream end */
+#define ERR_STATUS 0x10000000
+#define EMPTY_STATUS 0x08000000
+
+#define IEOB_ENABLE 0x1 /* enable interrupts for status notification above */
+#define IEOS_ENABLE 0x2
+#define IEOC_ENABLE 0x4
+#define RDONCE 0x8
+#define DESC_MAX_MASK 0xff
+
+#define ST_PLAY 0x1 /* stream states */
+#define ST_STOP 0x2
+#define ST_PAUSE 0x4
+
+#define I2S_INTDEC 3 /* config for I2S link */
+#define I2S_MERGER 0
+#define I2S_SPLITTER 0
+#define I2S_MIXER 7
+#define I2S_RATE 44100
+
+#define MODEM_INTDEC 4 /* config for modem link */
+#define MODEM_MERGER 3
+#define MODEM_SPLITTER 0
+#define MODEM_MIXER 11
+
+#define FM_INTDEC 3 /* config for FM/OPL3 link */
+#define FM_MERGER 0
+#define FM_SPLITTER 0
+#define FM_MIXER 9
+
+#define SPLIT_PATH 0x80 /* path splitting flag */
+
+enum FIRMWARE {
+ DATA_REC = 0, EXT_END_OF_FILE, EXT_SEG_ADDR_REC, EXT_GOTO_CMD_REC,
+ EXT_LIN_ADDR_REC,
+};
+
+enum CMDS {
+ GETV = 0x00, GETC, GUNS, SCID, RMEM =
+ 0x10, SMEM, WMEM, SDTM, GOTO, SSTR =
+ 0x20, PSTR, KSTR, KDMA, GPOS, SETF, GSTS, NGPOS, PSEL =
+ 0x30, PCLR, PLST, RSSV, LSEL, SSRC = 0x40, SLST, RSRC, SSRB, SDGV =
+ 0x50, RDGV, DLST, SACR = 0x60, RACR, ALST, TXAC, RXAC, SI2S =
+ 0x70, ARM_SETDPLL = 0x72,
+};
+
+enum E1SOURCE {
+ ARM2LBUS_FIFO0 = 0, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, ARM2LBUS_FIFO3,
+ ARM2LBUS_FIFO4, ARM2LBUS_FIFO5, ARM2LBUS_FIFO6, ARM2LBUS_FIFO7,
+ ARM2LBUS_FIFO8, ARM2LBUS_FIFO9, ARM2LBUS_FIFO10, ARM2LBUS_FIFO11,
+ ARM2LBUS_FIFO12, ARM2LBUS_FIFO13, ARM2LBUS_FIFO14, ARM2LBUS_FIFO15,
+ INTER0_OUT, INTER1_OUT, INTER2_OUT, INTER3_OUT, INTER4_OUT,
+ INTERM0_OUT, INTERM1_OUT, INTERM2_OUT, INTERM3_OUT, INTERM4_OUT,
+ INTERM5_OUT, INTERM6_OUT, DECIMM0_OUT, DECIMM1_OUT, DECIMM2_OUT,
+ DECIMM3_OUT, DECIM0_OUT, SR3_4_OUT, OPL3_SAMPLE, ASRC0, ASRC1,
+ ACLNK2PADC, ACLNK2MODEM0RX, ACLNK2MIC, ACLNK2MODEM1RX, ACLNK2HNDMIC,
+ DIGITAL_MIXER_OUT0, GAINFUNC0_OUT, GAINFUNC1_OUT, GAINFUNC2_OUT,
+ GAINFUNC3_OUT, GAINFUNC4_OUT, SOFTMODEMTX, SPLITTER0_OUTL,
+ SPLITTER0_OUTR, SPLITTER1_OUTL, SPLITTER1_OUTR, SPLITTER2_OUTL,
+ SPLITTER2_OUTR, SPLITTER3_OUTL, SPLITTER3_OUTR, MERGER0_OUT,
+ MERGER1_OUT, MERGER2_OUT, MERGER3_OUT, ARM2LBUS_FIFO_DIRECT, NO_OUT
+};
+
+enum E2SINK {
+ LBUS2ARM_FIFO0 = 0, LBUS2ARM_FIFO1, LBUS2ARM_FIFO2, LBUS2ARM_FIFO3,
+ LBUS2ARM_FIFO4, LBUS2ARM_FIFO5, LBUS2ARM_FIFO6, LBUS2ARM_FIFO7,
+ INTER0_IN, INTER1_IN, INTER2_IN, INTER3_IN, INTER4_IN, INTERM0_IN,
+ INTERM1_IN, INTERM2_IN, INTERM3_IN, INTERM4_IN, INTERM5_IN, INTERM6_IN,
+ DECIMM0_IN, DECIMM1_IN, DECIMM2_IN, DECIMM3_IN, DECIM0_IN, SR3_4_IN,
+ PDAC2ACLNK, MODEM0TX2ACLNK, MODEM1TX2ACLNK, HNDSPK2ACLNK,
+ DIGITAL_MIXER_IN0, DIGITAL_MIXER_IN1, DIGITAL_MIXER_IN2,
+ DIGITAL_MIXER_IN3, DIGITAL_MIXER_IN4, DIGITAL_MIXER_IN5,
+ DIGITAL_MIXER_IN6, DIGITAL_MIXER_IN7, DIGITAL_MIXER_IN8,
+ DIGITAL_MIXER_IN9, DIGITAL_MIXER_IN10, DIGITAL_MIXER_IN11,
+ GAINFUNC0_IN, GAINFUNC1_IN, GAINFUNC2_IN, GAINFUNC3_IN, GAINFUNC4_IN,
+ SOFTMODEMRX, SPLITTER0_IN, SPLITTER1_IN, SPLITTER2_IN, SPLITTER3_IN,
+ MERGER0_INL, MERGER0_INR, MERGER1_INL, MERGER1_INR, MERGER2_INL,
+ MERGER2_INR, MERGER3_INL, MERGER3_INR, E2SINK_MAX
+};
+
+enum LBUS_SINK {
+ LS_SRC_INTERPOLATOR = 0, LS_SRC_INTERPOLATORM, LS_SRC_DECIMATOR,
+ LS_SRC_DECIMATORM, LS_MIXER_IN, LS_MIXER_GAIN_FUNCTION,
+ LS_SRC_SPLITTER, LS_SRC_MERGER, LS_NONE1, LS_NONE2,
+};
+
+enum RT_CHANNEL_IDS {
+ M0TX = 0, M1TX, TAMTX, HSSPKR, PDAC, DSNDTX0, DSNDTX1, DSNDTX2,
+ DSNDTX3, DSNDTX4, DSNDTX5, DSNDTX6, DSNDTX7, WVSTRTX, COP3DTX, SPARE,
+ M0RX, HSMIC, M1RX, CLEANRX, MICADC, PADC, COPRX1, COPRX2,
+ CHANNEL_ID_COUNTER
+};
+
+enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD };
+
+struct lbuspath {
+ unsigned char *noconv;
+ unsigned char *stereo;
+ unsigned char *mono;
+};
+
+struct cmdport {
+ u32 data1; /* cmd,param */
+ u32 data2; /* param */
+ u32 stat; /* status */
+ u32 pad[5];
+};
+
+struct riptideport {
+ u32 audio_control; /* status registers */
+ u32 audio_status;
+ u32 pad[2];
+ struct cmdport port[2]; /* command ports */
+};
+
+struct cmdif {
+ struct riptideport *hwport;
+ spinlock_t lock;
+ unsigned int cmdcnt; /* cmd statistics */
+ unsigned int cmdtime;
+ unsigned int cmdtimemax;
+ unsigned int cmdtimemin;
+ unsigned int errcnt;
+ int is_reset;
+};
+
+struct riptide_firmware {
+ u16 ASIC;
+ u16 CODEC;
+ u16 AUXDSP;
+ u16 PROG;
+};
+
+union cmdret {
+ u8 retbytes[8];
+ u16 retwords[4];
+ u32 retlongs[2];
+};
+
+union firmware_version {
+ union cmdret ret;
+ struct riptide_firmware firmware;
+};
+
+#define get_pcmhwdev(substream) (struct pcmhw *)(substream->runtime->private_data)
+
+#define PLAYBACK_SUBSTREAMS 3
+struct snd_riptide {
+ struct snd_card *card;
+ struct pci_dev *pci;
+ const struct firmware *fw_entry;
+
+ struct cmdif *cif;
+
+ struct snd_pcm *pcm;
+ struct snd_pcm *pcm_i2s;
+ struct snd_rawmidi *rmidi;
+ struct snd_opl3 *opl3;
+ struct snd_ac97 *ac97;
+ struct snd_ac97_bus *ac97_bus;
+
+ struct snd_pcm_substream *playback_substream[PLAYBACK_SUBSTREAMS];
+ struct snd_pcm_substream *capture_substream;
+
+ int openstreams;
+
+ int irq;
+ unsigned long port;
+ unsigned short mpuaddr;
+ unsigned short opladdr;
+#ifdef SUPPORT_JOYSTICK
+ unsigned short gameaddr;
+#endif
+ struct resource *res_port;
+
+ unsigned short device_id;
+
+ union firmware_version firmware;
+
+ spinlock_t lock;
+ struct tasklet_struct riptide_tq;
+ struct snd_info_entry *proc_entry;
+
+ unsigned long received_irqs;
+ unsigned long handled_irqs;
+#ifdef CONFIG_PM
+ int in_suspend;
+#endif
+};
+
+struct sgd { /* scatter gather desriptor */
+ u32 dwNextLink;
+ u32 dwSegPtrPhys;
+ u32 dwSegLen;
+ u32 dwStat_Ctl;
+};
+
+struct pcmhw { /* pcm descriptor */
+ struct lbuspath paths;
+ unsigned char *lbuspath;
+ unsigned char source;
+ unsigned char intdec[2];
+ unsigned char mixer;
+ unsigned char id;
+ unsigned char state;
+ unsigned int rate;
+ unsigned int channels;
+ snd_pcm_format_t format;
+ struct snd_dma_buffer sgdlist;
+ struct sgd *sgdbuf;
+ unsigned int size;
+ unsigned int pages;
+ unsigned int oldpos;
+ unsigned int pointer;
+};
+
+#define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}}
+
+static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
+ union cmdret *ret);
+static int getsourcesink(struct cmdif *cif, unsigned char source,
+ unsigned char sink, unsigned char *a,
+ unsigned char *b);
+static int snd_riptide_initialize(struct snd_riptide *chip);
+static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);
+
+/*
+ */
+
+static struct pci_device_id snd_riptide_ids[] = {
+ {
+ .vendor = 0x127a,.device = 0x4310,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4320,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4330,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4340,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {0,},
+};
+
+#ifdef SUPPORT_JOYSTICK
+static struct pci_device_id snd_riptide_joystick_ids[] = {
+ {
+ .vendor = 0x127a,.device = 0x4312,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4322,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {.vendor = 0x127a,.device = 0x4332,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {.vendor = 0x127a,.device = 0x4342,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {0,},
+};
+#endif
+
+MODULE_DEVICE_TABLE(pci, snd_riptide_ids);
+
+/*
+ */
+
+static unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
+ {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
+ LS_NONE2},
+ {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
+ LS_NONE2},
+ {INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR},
+ {INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR},
+ {INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM},
+ {INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT,
+ LS_SRC_INTERPOLATORM},
+ {INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT,
+ LS_SRC_INTERPOLATORM},
+ {INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT,
+ LS_SRC_INTERPOLATORM},
+ {DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM},
+ {DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM},
+ {DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT,
+ LS_NONE2},
+ {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT,
+ LS_MIXER_GAIN_FUNCTION},
+ {GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT,
+ LS_MIXER_GAIN_FUNCTION},
+ {GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1},
+ {SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER},
+ {SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER},
+ {MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER},
+ {MERGER1_OUT, LS_SRC_MERGER},
+ {MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER},
+ {MERGER2_OUT, LS_SRC_MERGER},
+ {MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT,
+ LS_NONE2},
+};
+
+static unsigned char lbus_play_opl3[] = {
+ DIGITAL_MIXER_IN0 + FM_MIXER, 0xff
+};
+static unsigned char lbus_play_modem[] = {
+ DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff
+};
+static unsigned char lbus_play_i2s[] = {
+ INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff
+};
+static unsigned char lbus_play_out[] = {
+ PDAC2ACLNK, 0xff
+};
+static unsigned char lbus_play_outhp[] = {
+ HNDSPK2ACLNK, 0xff
+};
+static unsigned char lbus_play_noconv1[] = {
+ DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_stereo1[] = {
+ INTER0_IN, DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_mono1[] = {
+ INTERM0_IN, DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_noconv2[] = {
+ DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_stereo2[] = {
+ INTER1_IN, DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_mono2[] = {
+ INTERM1_IN, DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_noconv3[] = {
+ DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_play_stereo3[] = {
+ INTER2_IN, DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_play_mono3[] = {
+ INTERM2_IN, DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_rec_noconv1[] = {
+ LBUS2ARM_FIFO5, 0xff
+};
+static unsigned char lbus_rec_stereo1[] = {
+ DECIM0_IN, LBUS2ARM_FIFO5, 0xff
+};
+static unsigned char lbus_rec_mono1[] = {
+ DECIMM3_IN, LBUS2ARM_FIFO5, 0xff
+};
+
+static unsigned char play_ids[] = { 4, 1, 2, };
+static unsigned char play_sources[] = {
+ ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2,
+};
+static struct lbuspath lbus_play_paths[] = {
+ {
+ .noconv = lbus_play_noconv1,
+ .stereo = lbus_play_stereo1,
+ .mono = lbus_play_mono1,
+ },
+ {
+ .noconv = lbus_play_noconv2,
+ .stereo = lbus_play_stereo2,
+ .mono = lbus_play_mono2,
+ },
+ {
+ .noconv = lbus_play_noconv3,
+ .stereo = lbus_play_stereo3,
+ .mono = lbus_play_mono3,
+ },
+};
+static struct lbuspath lbus_rec_path = {
+ .noconv = lbus_rec_noconv1,
+ .stereo = lbus_rec_stereo1,
+ .mono = lbus_rec_mono1,
+};
+
+#define FIRMWARE_VERSIONS 1
+static union firmware_version firmware_versions[] = {
+ {
+ .firmware.ASIC = 3,.firmware.CODEC = 2,
+ .firmware.AUXDSP = 3,.firmware.PROG = 773,
+ },
+};
+
+static u32 atoh(unsigned char *in, unsigned int len)
+{
+ u32 sum = 0;
+ unsigned int mult = 1;
+ unsigned char c;
+
+ while (len) {
+ c = in[len - 1];
+ if ((c >= '0') && (c <= '9'))
+ sum += mult * (c - '0');
+ else if ((c >= 'A') && (c <= 'F'))
+ sum += mult * (c - ('A' - 10));
+ else if ((c >= 'a') && (c <= 'f'))
+ sum += mult * (c - ('a' - 10));
+ mult *= 16;
+ --len;
+ }
+ return sum;
+}
+
+static int senddata(struct cmdif *cif, unsigned char *in, u32 offset)
+{
+ u32 addr;
+ u32 data;
+ u32 i;
+ unsigned char *p;
+
+ i = atoh(&in[1], 2);
+ addr = offset + atoh(&in[3], 4);
+ if (SEND_SMEM(cif, 0, addr) != 0)
+ return -EACCES;
+ p = in + 9;
+ while (i) {
+ data = atoh(p, 8);
+ if (SEND_WMEM(cif, 2,
+ ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0)
+ >> 4)))
+ return -EACCES;
+ i -= 4;
+ p += 8;
+ }
+ return 0;
+}
+
+static int loadfirmware(struct cmdif *cif, unsigned char *img,
+ unsigned int size)
+{
+ unsigned char *in;
+ u32 laddr, saddr, t, val;
+ int err = 0;
+
+ laddr = saddr = 0;
+ while (size > 0 && err == 0) {
+ in = img;
+ if (in[0] == ':') {
+ t = atoh(&in[7], 2);
+ switch (t) {
+ case DATA_REC:
+ err = senddata(cif, in, laddr + saddr);
+ break;
+ case EXT_SEG_ADDR_REC:
+ saddr = atoh(&in[9], 4) << 4;
+ break;
+ case EXT_LIN_ADDR_REC:
+ laddr = atoh(&in[9], 4) << 16;
+ break;
+ case EXT_GOTO_CMD_REC:
+ val = atoh(&in[9], 8);
+ if (SEND_GOTO(cif, val) != 0)
+ err = -EACCES;
+ break;
+ case EXT_END_OF_FILE:
+ size = 0;
+ break;
+ default:
+ break;
+ }
+ while (size > 0) {
+ size--;
+ if (*img++ == '\n')
+ break;
+ }
+ }
+ }
+ snd_printdd("load firmware return %d\n", err);
+ return err;
+}
+
+static void
+alloclbuspath(struct cmdif *cif, unsigned char source,
+ unsigned char *path, unsigned char *mixer, unsigned char *s)
+{
+ while (*path != 0xff) {
+ unsigned char sink, type;
+
+ sink = *path & (~SPLIT_PATH);
+ if (sink != E2SINK_MAX) {
+ snd_printdd("alloc path 0x%x->0x%x\n", source, sink);
+ SEND_PSEL(cif, source, sink);
+ source = lbusin2out[sink][0];
+ type = lbusin2out[sink][1];
+ if (type == LS_MIXER_IN) {
+ if (mixer)
+ *mixer = sink - DIGITAL_MIXER_IN0;
+ }
+ if (type == LS_SRC_DECIMATORM ||
+ type == LS_SRC_DECIMATOR ||
+ type == LS_SRC_INTERPOLATORM ||
+ type == LS_SRC_INTERPOLATOR) {
+ if (s) {
+ if (s[0] != 0xff)
+ s[1] = sink;
+ else
+ s[0] = sink;
+ }
+ }
+ }
+ if (*path++ & SPLIT_PATH) {
+ unsigned char *npath = path;
+
+ while (*npath != 0xff)
+ npath++;
+ alloclbuspath(cif, source + 1, ++npath, mixer, s);
+ }
+ }
+}
+
+static void
+freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path)
+{
+ while (*path != 0xff) {
+ unsigned char sink;
+
+ sink = *path & (~SPLIT_PATH);
+ if (sink != E2SINK_MAX) {
+ snd_printdd("free path 0x%x->0x%x\n", source, sink);
+ SEND_PCLR(cif, source, sink);
+ source = lbusin2out[sink][0];
+ }
+ if (*path++ & SPLIT_PATH) {
+ unsigned char *npath = path;
+
+ while (*npath != 0xff)
+ npath++;
+ freelbuspath(cif, source + 1, ++npath);
+ }
+ }
+}
+
+static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask)
+{
+ union cmdret rptr = CMDRET_ZERO;
+ unsigned int i = MAX_WRITE_RETRY;
+ int flag = 1;
+
+ SEND_RMEM(cif, 0x02, addr, &rptr);
+ rptr.retlongs[0] &= (~mask);
+
+ while (--i) {
+ SEND_SMEM(cif, 0x01, addr);
+ SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data));
+ SEND_RMEM(cif, 0x02, addr, &rptr);
+ if ((rptr.retlongs[0] & data) == data) {
+ flag = 0;
+ break;
+ } else
+ rptr.retlongs[0] &= ~mask;
+ }
+ snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask,
+ flag);
+ return flag;
+}
+
+static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
+ union cmdret *ret)
+{
+ int i, j;
+ int err;
+ unsigned int time = 0;
+ unsigned long irqflags;
+ struct riptideport *hwport;
+ struct cmdport *cmdport = NULL;
+
+ snd_assert(cif, return -EINVAL);
+
+ hwport = cif->hwport;
+ if (cif->errcnt > MAX_ERROR_COUNT) {
+ if (cif->is_reset) {
+ snd_printk(KERN_ERR
+ "Riptide: Too many failed cmds, reinitializing\n");
+ if (riptide_reset(cif, NULL) == 0) {
+ cif->errcnt = 0;
+ return -EIO;
+ }
+ }
+ snd_printk(KERN_ERR "Riptide: Initialization failed.\n");
+ return -EINVAL;
+ }
+ if (ret) {
+ ret->retlongs[0] = 0;
+ ret->retlongs[1] = 0;
+ }
+ i = 0;
+ spin_lock_irqsave(&cif->lock, irqflags);
+ while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport))
+ udelay(10);
+ if (i >= CMDIF_TIMEOUT) {
+ err = -EBUSY;
+ goto errout;
+ }
+
+ err = 0;
+ for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) {
+ cmdport = &(hwport->port[j % 2]);
+ if (IS_DATF(cmdport)) { /* free pending data */
+ READ_PORT_ULONG(cmdport->data1);
+ READ_PORT_ULONG(cmdport->data2);
+ }
+ if (IS_CMDE(cmdport)) {
+ if (flags & PARM) /* put data */
+ WRITE_PORT_ULONG(cmdport->data2, parm);
+ WRITE_PORT_ULONG(cmdport->data1, cmd); /* write cmd */
+ if ((flags & RESP) && ret) {
+ while (!IS_DATF(cmdport) &&
+ time++ < CMDIF_TIMEOUT)
+ udelay(10);
+ if (time < CMDIF_TIMEOUT) { /* read response */
+ ret->retlongs[0] =
+ READ_PORT_ULONG(cmdport->data1);
+ ret->retlongs[1] =
+ READ_PORT_ULONG(cmdport->data2);
+ } else {
+ err = -ENOSYS;
+ goto errout;
+ }
+ }
+ break;
+ }
+ udelay(20);
+ }
+ if (time == CMDIF_TIMEOUT) {
+ err = -ENODATA;
+ goto errout;
+ }
+ spin_unlock_irqrestore(&cif->lock, irqflags);
+
+ cif->cmdcnt++; /* update command statistics */
+ cif->cmdtime += time;
+ if (time > cif->cmdtimemax)
+ cif->cmdtimemax = time;
+ if (time < cif->cmdtimemin)
+ cif->cmdtimemin = time;
+ if ((cif->cmdcnt) % 1000 == 0)
+ snd_printdd
+ ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n",
+ cif->cmdcnt, cif->cmdtime, cif->cmdtimemin,
+ cif->cmdtimemax, cif->errcnt);
+ return 0;
+
+ errout:
+ cif->errcnt++;
+ spin_unlock_irqrestore(&cif->lock, irqflags);
+ snd_printdd
+ ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n",
+ cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport),
+ flags, cmd, parm, ret ? ret->retlongs[0] : 0,
+ ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport),
+ err);
+ return err;
+}
+
+static int
+setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
+{
+ union cmdret rptr = CMDRET_ZERO;
+ int i = 0;
+
+ snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
+ do {
+ SEND_SDGV(cif, num, num, rval, lval);
+ SEND_RDGV(cif, num, num, &rptr);
+ if (rptr.retwords[0] == lval && rptr.retwords[1] == rval)
+ return 0;
+ } while (i++ < MAX_WRITE_RETRY);
+ snd_printdd("sent mixer failed\n");
+ return -EIO;
+}
+
+static int getpaths(struct cmdif *cif, unsigned char *o)
+{
+ unsigned char src[E2SINK_MAX];
+ unsigned char sink[E2SINK_MAX];
+ int i, j = 0;
+
+ for (i = 0; i < E2SINK_MAX; i++) {
+ getsourcesink(cif, i, i, &src[i], &sink[i]);
+ if (sink[i] < E2SINK_MAX) {
+ o[j++] = sink[i];
+ o[j++] = i;
+ }
+ }
+ return j;
+}
+
+static int
+getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink,
+ unsigned char *a, unsigned char *b)
+{
+ union cmdret rptr = CMDRET_ZERO;
+
+ if (SEND_RSSV(cif, source, sink, &rptr) &&
+ SEND_RSSV(cif, source, sink, &rptr))
+ return -EIO;
+ *a = rptr.retbytes[0];
+ *b = rptr.retbytes[1];
+ snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b);
+ return 0;
+}
+
+static int
+getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate)
+{
+ unsigned char *s;
+ unsigned int p[2] = { 0, 0 };
+ int i;
+ union cmdret rptr = CMDRET_ZERO;
+
+ s = intdec;
+ for (i = 0; i < 2; i++) {
+ if (*s != 0xff) {
+ if (SEND_RSRC(cif, *s, &rptr) &&
+ SEND_RSRC(cif, *s, &rptr))
+ return -EIO;
+ p[i] += rptr.retwords[1];
+ p[i] *= rptr.retwords[2];
+ p[i] += rptr.retwords[3];
+ p[i] /= 65536;
+ }
+ s++;
+ }
+ if (p[0]) {
+ if (p[1] != p[0])
+ snd_printdd("rates differ %d %d\n", p[0], p[1]);
+ *rate = (unsigned int)p[0];
+ } else
+ *rate = (unsigned int)p[1];
+ snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate);
+ return 0;
+}
+
+static int
+setsampleformat(struct cmdif *cif,
+ unsigned char mixer, unsigned char id,
+ unsigned char channels, unsigned char format)
+{
+ unsigned char w, ch, sig, order;
+
+ snd_printdd
+ ("setsampleformat mixer: %d id: %d channels: %d format: %d\n",
+ mixer, id, channels, format);
+ ch = channels == 1;
+ w = snd_pcm_format_width(format) == 8;
+ sig = snd_pcm_format_unsigned(format) != 0;
+ order = snd_pcm_format_big_endian(format) != 0;
+
+ if (SEND_SETF(cif, mixer, w, ch, order, sig, id) &&
+ SEND_SETF(cif, mixer, w, ch, order, sig, id)) {
+ snd_printdd("setsampleformat failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int
+setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate)
+{
+ u32 D, M, N;
+ union cmdret rptr = CMDRET_ZERO;
+ int i;
+
+ snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0],
+ intdec[1], rate);
+ D = 48000;
+ M = ((rate == 48000) ? 47999 : rate) * 65536;
+ N = M % D;
+ M /= D;
+ for (i = 0; i < 2; i++) {
+ if (*intdec != 0xff) {
+ do {
+ SEND_SSRC(cif, *intdec, D, M, N);
+ SEND_RSRC(cif, *intdec, &rptr);
+ } while (rptr.retwords[1] != D &&
+ rptr.retwords[2] != M &&
+ rptr.retwords[3] != N &&
+ i++ < MAX_WRITE_RETRY);
+ if (i == MAX_WRITE_RETRY) {
+ snd_printdd("sent samplerate %d: %d failed\n",
+ *intdec, rate);
+ return -EIO;
+ }
+ }
+ intdec++;
+ }
+ return 0;
+}
+
+static int
+getmixer(struct cmdif *cif, short num, unsigned short *rval,
+ unsigned short *lval)
+{
+ union cmdret rptr = CMDRET_ZERO;
+
+ if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr))
+ return -EIO;
+ *rval = rptr.retwords[0];
+ *lval = rptr.retwords[1];
+ snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
+ return 0;
+}
+
+static void riptide_handleirq(unsigned long dev_id)
+{
+ struct snd_riptide *chip = (void *)dev_id;
+ struct cmdif *cif = chip->cif;
+ struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
+ struct snd_pcm_runtime *runtime;
+ struct pcmhw *data = NULL;
+ unsigned int pos, period_bytes;
+ struct sgd *c;
+ int i, j;
+ unsigned int flag;
+
+ if (!cif)
+ return;
+
+ for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)
+ substream[i] = chip->playback_substream[i];
+ substream[i] = chip->capture_substream;
+ for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) {
+ if (substream[i] &&
+ (runtime = substream[i]->runtime) &&
+ (data = runtime->private_data) && data->state != ST_STOP) {
+ pos = 0;
+ for (j = 0; j < data->pages; j++) {
+ c = &data->sgdbuf[j];
+ flag = le32_to_cpu(c->dwStat_Ctl);
+ if (flag & EOB_STATUS)
+ pos += le32_to_cpu(c->dwSegLen);
+ if (flag & EOC_STATUS)
+ pos += le32_to_cpu(c->dwSegLen);
+ if ((flag & EOS_STATUS)
+ && (data->state == ST_PLAY)) {
+ data->state = ST_STOP;
+ snd_printk(KERN_ERR
+ "Riptide: DMA stopped unexpectedly\n");
+ }
+ c->dwStat_Ctl =
+ cpu_to_le32(flag &
+ ~(EOS_STATUS | EOB_STATUS |
+ EOC_STATUS));
+ }
+ data->pointer += pos;
+ pos += data->oldpos;
+ if (data->state != ST_STOP) {
+ period_bytes =
+ frames_to_bytes(runtime,
+ runtime->period_size);
+ snd_printdd
+ ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ bytes_to_frames(runtime, pos),
+ runtime->period_size);
+ j = 0;
+ if (pos >= period_bytes) {
+ j++;
+ while (pos >= period_bytes)
+ pos -= period_bytes;
+ }
+ data->oldpos = pos;
+ if (j > 0)
+ snd_pcm_period_elapsed(substream[i]);
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_PM
+static int riptide_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_riptide *chip = card->private_data;
+
+ chip->in_suspend = 1;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int riptide_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_riptide *chip = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+ snd_riptide_initialize(chip);
+ snd_ac97_resume(chip->ac97);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ chip->in_suspend = 0;
+ return 0;
+}
+#endif
+
+static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
+{
+ int timeout, tries;
+ union cmdret rptr = CMDRET_ZERO;
+ union firmware_version firmware;
+ int i, j, err, has_firmware;
+
+ if (!cif)
+ return -EINVAL;
+
+ cif->cmdcnt = 0;
+ cif->cmdtime = 0;
+ cif->cmdtimemax = 0;
+ cif->cmdtimemin = 0xffffffff;
+ cif->errcnt = 0;
+ cif->is_reset = 0;
+
+ tries = RESET_TRIES;
+ has_firmware = 0;
+ while (has_firmware == 0 && tries-- > 0) {
+ for (i = 0; i < 2; i++) {
+ WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);
+ WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);
+ }
+ SET_GRESET(cif->hwport);
+ udelay(100);
+ UNSET_GRESET(cif->hwport);
+ udelay(100);
+
+ for (timeout = 100000; --timeout; udelay(10)) {
+ if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))
+ break;
+ }
+ if (timeout == 0) {
+ snd_printk(KERN_ERR
+ "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ IS_READY(cif->hwport), IS_GERR(cif->hwport));
+ return -EIO;
+ } else {
+ snd_printdd
+ ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ IS_READY(cif->hwport), IS_GERR(cif->hwport));
+ }
+
+ SEND_GETV(cif, &rptr);
+ for (i = 0; i < 4; i++)
+ firmware.ret.retwords[i] = rptr.retwords[i];
+
+ snd_printdd
+ ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",
+ firmware.firmware.ASIC, firmware.firmware.CODEC,
+ firmware.firmware.AUXDSP, firmware.firmware.PROG);
+
+ for (j = 0; j < FIRMWARE_VERSIONS; j++) {
+ has_firmware = 1;
+ for (i = 0; i < 4; i++) {
+ if (firmware_versions[j].ret.retwords[i] !=
+ firmware.ret.retwords[i])
+ has_firmware = 0;
+ }
+ if (has_firmware)
+ break;
+ }
+
+ if (chip != NULL && has_firmware == 0) {
+ snd_printdd("Writing Firmware\n");
+ if (!chip->fw_entry) {
+ if ((err =
+ request_firmware(&chip->fw_entry,
+ "riptide.hex",
+ &chip->pci->dev)) != 0) {
+ snd_printk(KERN_ERR
+ "Riptide: Firmware not available %d\n",
+ err);
+ return -EIO;
+ }
+ }
+ err = loadfirmware(cif, chip->fw_entry->data,
+ chip->fw_entry->size);
+ if (err)
+ snd_printk(KERN_ERR
+ "Riptide: Could not load firmware %d\n",
+ err);
+ }
+ }
+
+ SEND_SACR(cif, 0, AC97_RESET);
+ SEND_RACR(cif, AC97_RESET, &rptr);
+ snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]);
+
+ SEND_PLST(cif, 0);
+ SEND_SLST(cif, 0);
+ SEND_DLST(cif, 0);
+ SEND_ALST(cif, 0);
+ SEND_KDMA(cif);
+
+ writearm(cif, 0x301F8, 1, 1);
+ writearm(cif, 0x301F4, 1, 1);
+
+ SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER,
+ MODEM_SPLITTER, MODEM_MIXER);
+ setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff);
+ alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL);
+
+ SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER,
+ FM_MIXER);
+ setmixer(cif, FM_MIXER, 0x7fff, 0x7fff);
+ writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005);
+ writearm(cif, 0x301A8, 0x02, 0x00000002);
+ writearm(cif, 0x30264, 0x08, 0xffffffff);
+ alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL);
+
+ SEND_SSRC(cif, I2S_INTDEC, 48000,
+ ((u32) I2S_RATE * 65536) / 48000,
+ ((u32) I2S_RATE * 65536) % 48000);
+ SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER,
+ I2S_MIXER);
+ SEND_SI2S(cif, 1);
+ alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL);
+ alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL);
+ alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL);
+
+ SET_AIACK(cif->hwport);
+ SET_AIE(cif->hwport);
+ SET_AIACK(cif->hwport);
+ cif->is_reset = 1;
+ if (chip) {
+ for (i = 0; i < 4; i++)
+ chip->firmware.ret.retwords[i] =
+ firmware.ret.retwords[i];
+ }
+
+ return 0;
+}
+
+static struct snd_pcm_hardware snd_riptide_playback = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
+ .formats =
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
+ | SNDRV_PCM_FMTBIT_U16_LE,
+ .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 5500,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (64 * 1024),
+ .period_bytes_min = PAGE_SIZE >> 1,
+ .period_bytes_max = PAGE_SIZE << 8,
+ .periods_min = 2,
+ .periods_max = 64,
+ .fifo_size = 0,
+};
+static struct snd_pcm_hardware snd_riptide_capture = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
+ .formats =
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
+ | SNDRV_PCM_FMTBIT_U16_LE,
+ .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 5500,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (64 * 1024),
+ .period_bytes_min = PAGE_SIZE >> 1,
+ .period_bytes_max = PAGE_SIZE << 3,
+ .periods_min = 2,
+ .periods_max = 64,
+ .fifo_size = 0,
+};
+
+static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream
+ *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+ snd_pcm_uframes_t ret;
+
+ SEND_GPOS(cif, 0, data->id, &rptr);
+ if (data->size && runtime->period_size) {
+ snd_printdd
+ ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n",
+ data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size,
+ bytes_to_frames(runtime, rptr.retlongs[1]),
+ bytes_to_frames(runtime,
+ rptr.retlongs[1]) % runtime->period_size);
+ if (rptr.retlongs[1] > data->pointer)
+ ret =
+ bytes_to_frames(runtime,
+ rptr.retlongs[1] % data->size);
+ else
+ ret =
+ bytes_to_frames(runtime,
+ data->pointer % data->size);
+ } else {
+ snd_printdd("stream not started or strange parms (%d %ld)\n",
+ data->size, runtime->period_size);
+ ret = bytes_to_frames(runtime, 0);
+ }
+ return ret;
+}
+
+static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int i, j;
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+
+ spin_lock(&chip->lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (!(data->state & ST_PLAY)) {
+ SEND_SSTR(cif, data->id, data->sgdlist.addr);
+ SET_AIE(cif->hwport);
+ data->state = ST_PLAY;
+ if (data->mixer != 0xff)
+ setmixer(cif, data->mixer, 0x7fff, 0x7fff);
+ chip->openstreams++;
+ data->oldpos = 0;
+ data->pointer = 0;
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (data->mixer != 0xff)
+ setmixer(cif, data->mixer, 0, 0);
+ setmixer(cif, data->mixer, 0, 0);
+ SEND_KSTR(cif, data->id);
+ data->state = ST_STOP;
+ chip->openstreams--;
+ j = 0;
+ do {
+ i = rptr.retlongs[1];
+ SEND_GPOS(cif, 0, data->id, &rptr);
+ udelay(1);
+ } while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY);
+ if (j >= MAX_WRITE_RETRY)
+ snd_printk(KERN_ERR "Riptide: Could not stop stream!");
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (!(data->state & ST_PAUSE)) {
+ SEND_PSTR(cif, data->id);
+ data->state |= ST_PAUSE;
+ chip->openstreams--;
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (data->state & ST_PAUSE) {
+ SEND_SSTR(cif, data->id, data->sgdlist.addr);
+ data->state &= ~ST_PAUSE;
+ chip->openstreams++;
+ }
+ break;
+ default:
+ spin_unlock(&chip->lock);
+ return -EINVAL;
+ }
+ spin_unlock(&chip->lock);
+ return 0;
+}
+
+static int snd_riptide_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+ unsigned char *lbuspath = NULL;
+ unsigned int rate, channels;
+ int err = 0;
+ snd_pcm_format_t format;
+
+ snd_assert(cif && data, return -EINVAL);
+
+ snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id,
+ runtime->channels, runtime->format, runtime->rate);
+
+ spin_lock_irq(&chip->lock);
+ channels = runtime->channels;
+ format = runtime->format;
+ rate = runtime->rate;
+ switch (channels) {
+ case 1:
+ if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
+ lbuspath = data->paths.noconv;
+ else
+ lbuspath = data->paths.mono;
+ break;
+ case 2:
+ if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
+ lbuspath = data->paths.noconv;
+ else
+ lbuspath = data->paths.stereo;
+ break;
+ }
+ snd_printdd("use sgdlist at 0x%p and buffer at 0x%p\n",
+ data->sgdlist.area, sgbuf);
+ if (data->sgdlist.area && sgbuf) {
+ unsigned int i, j, size, pages, f, pt, period;
+ struct sgd *c, *p = NULL;
+
+ size = frames_to_bytes(runtime, runtime->buffer_size);
+ period = frames_to_bytes(runtime, runtime->period_size);
+ f = PAGE_SIZE;
+ while ((size + (f >> 1) - 1) <= (f << 7) && (f << 1) > period)
+ f = f >> 1;
+ pages = (size + f - 1) / f;
+ data->size = size;
+ data->pages = pages;
+ snd_printdd
+ ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n",
+ size, pages, f, period);
+ pt = 0;
+ j = 0;
+ for (i = 0; i < pages; i++) {
+ c = &data->sgdbuf[i];
+ if (p)
+ p->dwNextLink = cpu_to_le32(data->sgdlist.addr +
+ (i *
+ sizeof(struct
+ sgd)));
+ c->dwNextLink = cpu_to_le32(data->sgdlist.addr);
+ c->dwSegPtrPhys =
+ cpu_to_le32(sgbuf->table[j].addr + pt);
+ pt = (pt + f) % PAGE_SIZE;
+ if (pt == 0)
+ j++;
+ c->dwSegLen = cpu_to_le32(f);
+ c->dwStat_Ctl =
+ cpu_to_le32(IEOB_ENABLE | IEOS_ENABLE |
+ IEOC_ENABLE);
+ p = c;
+ size -= f;
+ }
+ data->sgdbuf[i].dwSegLen = cpu_to_le32(size);
+ }
+ if (lbuspath && lbuspath != data->lbuspath) {
+ if (data->lbuspath)
+ freelbuspath(cif, data->source, data->lbuspath);
+ alloclbuspath(cif, data->source, lbuspath,
+ &data->mixer, data->intdec);
+ data->lbuspath = lbuspath;
+ data->rate = 0;
+ }
+ if (data->rate != rate || data->format != format ||
+ data->channels != channels) {
+ data->rate = rate;
+ data->format = format;
+ data->channels = channels;
+ if (setsampleformat
+ (cif, data->mixer, data->id, channels, format)
+ || setsamplerate(cif, data->intdec, rate))
+ err = -EIO;
+ }
+ spin_unlock_irq(&chip->lock);
+ return err;
+}
+
+static int
+snd_riptide_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct snd_dma_buffer *sgdlist = &data->sgdlist;
+ int err;
+
+ snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id,
+ sgdlist->area, (unsigned long)sgdlist->addr,
+ (int)sgdlist->bytes);
+ if (sgdlist->area)
+ snd_dma_free_pages(sgdlist);
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ sizeof(struct sgd) * (DESC_MAX_MASK + 1),
+ sgdlist)) < 0) {
+ snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n",
+ (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1));
+ return err;
+ }
+ data->sgdbuf = (struct sgd *)sgdlist->area;
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int snd_riptide_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+
+ if (cif && data) {
+ if (data->lbuspath)
+ freelbuspath(cif, data->source, data->lbuspath);
+ data->lbuspath = NULL;
+ data->source = 0xff;
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+
+ if (data->sgdlist.area) {
+ snd_dma_free_pages(&data->sgdlist);
+ data->sgdlist.area = NULL;
+ }
+ }
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data;
+ int index = substream->number;
+
+ chip->playback_substream[index] = substream;
+ runtime->hw = snd_riptide_playback;
+ data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+ data->paths = lbus_play_paths[index];
+ data->id = play_ids[index];
+ data->source = play_sources[index];
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+ data->state = ST_STOP;
+ runtime->private_data = data;
+ return snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data;
+
+ chip->capture_substream = substream;
+ runtime->hw = snd_riptide_capture;
+ data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+ data->paths = lbus_rec_path;
+ data->id = PADC;
+ data->source = ACLNK2PADC;
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+ data->state = ST_STOP;
+ runtime->private_data = data;
+ return snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ int index = substream->number;
+
+ substream->runtime->private_data = NULL;
+ chip->playback_substream[index] = NULL;
+ kfree(data);
+ return 0;
+}
+
+static int snd_riptide_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+
+ substream->runtime->private_data = NULL;
+ chip->capture_substream = NULL;
+ kfree(data);
+ return 0;
+}
+
+static struct snd_pcm_ops snd_riptide_playback_ops = {
+ .open = snd_riptide_playback_open,
+ .close = snd_riptide_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_riptide_hw_params,
+ .hw_free = snd_riptide_hw_free,
+ .prepare = snd_riptide_prepare,
+ .page = snd_pcm_sgbuf_ops_page,
+ .trigger = snd_riptide_trigger,
+ .pointer = snd_riptide_pointer,
+};
+static struct snd_pcm_ops snd_riptide_capture_ops = {
+ .open = snd_riptide_capture_open,
+ .close = snd_riptide_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_riptide_hw_params,
+ .hw_free = snd_riptide_hw_free,
+ .prepare = snd_riptide_prepare,
+ .page = snd_pcm_sgbuf_ops_page,
+ .trigger = snd_riptide_trigger,
+ .pointer = snd_riptide_pointer,
+};
+
+static int __devinit
+snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ if (rpcm)
+ *rpcm = NULL;
+ if ((err =
+ snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1,
+ &pcm)) < 0)
+ return err;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_riptide_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_riptide_capture_ops);
+ pcm->private_data = chip;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, "RIPTIDE");
+ chip->pcm = pcm;
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(chip->pci),
+ 64 * 1024, 128 * 1024);
+ if (rpcm)
+ *rpcm = pcm;
+ return 0;
+}
+
+static irqreturn_t
+snd_riptide_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct snd_riptide *chip = dev_id;
+ struct cmdif *cif = chip->cif;
+
+ if (cif) {
+ chip->received_irqs++;
+ if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
+ IS_EOCIRQ(cif->hwport)) {
+ chip->handled_irqs++;
+ tasklet_hi_schedule(&chip->riptide_tq);
+ }
+ if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
+ chip->handled_irqs++;
+ snd_mpu401_uart_interrupt(irq,
+ chip->rmidi->private_data,
+ regs);
+ }
+ SET_AIACK(cif->hwport);
+ }
+ return IRQ_HANDLED;
+}
+
+static void
+snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
+{
+ struct snd_riptide *chip = ac97->private_data;
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+ int i = 0;
+
+ snd_assert(cif, return);
+
+ snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val);
+ do {
+ SEND_SACR(cif, val, reg);
+ SEND_RACR(cif, reg, &rptr);
+ } while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY);
+ if (i == MAX_WRITE_RETRY)
+ snd_printdd("Write AC97 reg failed\n");
+}
+
+static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+{
+ struct snd_riptide *chip = ac97->private_data;
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+
+ snd_assert(cif, return 0);
+
+ if (SEND_RACR(cif, reg, &rptr) != 0)
+ SEND_RACR(cif, reg, &rptr);
+ snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]);
+ return rptr.retwords[1];
+}
+
+static int snd_riptide_initialize(struct snd_riptide *chip)
+{
+ struct cmdif *cif;
+ unsigned int device_id;
+ int err;
+
+ snd_assert(chip, return -EINVAL);
+
+ cif = chip->cif;
+ if (!cif) {
+ if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ cif->hwport = (struct riptideport *)chip->port;
+ spin_lock_init(&cif->lock);
+ chip->cif = cif;
+ }
+ cif->is_reset = 0;
+ if ((err = riptide_reset(cif, chip)) != 0)
+ return err;
+ device_id = chip->device_id;
+ switch (device_id) {
+ case 0x4310:
+ case 0x4320:
+ case 0x4330:
+ snd_printdd("Modem enable?\n");
+ SEND_SETDPLL(cif);
+ break;
+ }
+ snd_printdd("Enabling MPU IRQs\n");
+ if (chip->rmidi)
+ SET_EMPUIRQ(cif->hwport);
+ return err;
+}
+
+static int snd_riptide_free(struct snd_riptide *chip)
+{
+ struct cmdif *cif;
+
+ snd_assert(chip, return 0);
+
+ if ((cif = chip->cif)) {
+ SET_GRESET(cif->hwport);
+ udelay(100);
+ UNSET_GRESET(cif->hwport);
+ kfree(chip->cif);
+ }
+ if (chip->fw_entry)
+ release_firmware(chip->fw_entry);
+ release_and_free_resource(chip->res_port);
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+ kfree(chip);
+ return 0;
+}
+
+static int snd_riptide_dev_free(struct snd_device *device)
+{
+ struct snd_riptide *chip = device->device_data;
+
+ return snd_riptide_free(chip);
+}
+
+static int __devinit
+snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
+ struct snd_riptide **rchip)
+{
+ struct snd_riptide *chip;
+ struct riptideport *hwport;
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_riptide_dev_free,
+ };
+
+ *rchip = NULL;
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+ if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL)))
+ return -ENOMEM;
+
+ spin_lock_init(&chip->lock);
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ chip->openstreams = 0;
+ chip->port = pci_resource_start(pci, 0);
+ chip->received_irqs = 0;
+ chip->handled_irqs = 0;
+ chip->cif = NULL;
+ tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip);
+
+ if ((chip->res_port =
+ request_region(chip->port, 64, "RIPTIDE")) == NULL) {
+ snd_printk(KERN_ERR
+ "Riptide: unable to grab region 0x%lx-0x%lx\n",
+ chip->port, chip->port + 64 - 1);
+ snd_riptide_free(chip);
+ return -EBUSY;
+ }
+ hwport = (struct riptideport *)chip->port;
+ UNSET_AIE(hwport);
+
+ if (request_irq
+ (pci->irq, snd_riptide_interrupt, SA_INTERRUPT | SA_SHIRQ,
+ "RIPTIDE", chip)) {
+ snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
+ pci->irq);
+ snd_riptide_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+ chip->device_id = pci->device;
+ pci_set_master(pci);
+ if ((err = snd_riptide_initialize(chip)) < 0) {
+ snd_riptide_free(chip);
+ return err;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+ snd_riptide_free(chip);
+ return err;
+ }
+
+ *rchip = chip;
+ return 0;
+}
+
+static void
+snd_riptide_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_riptide *chip = entry->private_data;
+ struct pcmhw *data;
+ int i;
+ struct cmdif *cif = NULL;
+ unsigned char p[256];
+ unsigned short rval = 0, lval = 0;
+ unsigned int rate;
+
+ if (!chip)
+ return;
+
+ snd_iprintf(buffer, "%s\n\n", chip->card->longname);
+ snd_iprintf(buffer, "Device ID: 0x%x\nReceived IRQs: (%ld)%ld\nPorts:",
+ chip->device_id, chip->handled_irqs, chip->received_irqs);
+ for (i = 0; i < 64; i += 4)
+ snd_iprintf(buffer, "%c%02x: %08x",
+ (i % 16) ? ' ' : '\n', i, inl(chip->port + i));
+ if ((cif = chip->cif)) {
+ snd_iprintf(buffer,
+ "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d",
+ chip->firmware.firmware.ASIC,
+ chip->firmware.firmware.CODEC,
+ chip->firmware.firmware.AUXDSP,
+ chip->firmware.firmware.PROG);
+ snd_iprintf(buffer, "\nDigital mixer:");
+ for (i = 0; i < 12; i++) {
+ getmixer(cif, i, &rval, &lval);
+ snd_iprintf(buffer, "\n %d: %d %d", i, rval, lval);
+ }
+ snd_iprintf(buffer,
+ "\nARM Commands num: %d failed: %d time: %d max: %d min: %d",
+ cif->cmdcnt, cif->errcnt,
+ cif->cmdtime, cif->cmdtimemax, cif->cmdtimemin);
+ }
+ snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams);
+ for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) {
+ if (chip->playback_substream[i]
+ && chip->playback_substream[i]->runtime
+ && (data =
+ chip->playback_substream[i]->runtime->private_data)) {
+ snd_iprintf(buffer,
+ "stream: %d mixer: %d source: %d (%d,%d)\n",
+ data->id, data->mixer, data->source,
+ data->intdec[0], data->intdec[1]);
+ if (!(getsamplerate(cif, data->intdec, &rate)))
+ snd_iprintf(buffer, "rate: %d\n", rate);
+ }
+ }
+ if (chip->capture_substream
+ && chip->capture_substream->runtime
+ && (data = chip->capture_substream->runtime->private_data)) {
+ snd_iprintf(buffer,
+ "stream: %d mixer: %d source: %d (%d,%d)\n",
+ data->id, data->mixer,
+ data->source, data->intdec[0], data->intdec[1]);
+ if (!(getsamplerate(cif, data->intdec, &rate)))
+ snd_iprintf(buffer, "rate: %d\n", rate);
+ }
+ snd_iprintf(buffer, "Paths:\n");
+ i = getpaths(cif, p);
+ while (i--) {
+ snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
+ i--;
+ }
+ snd_iprintf(buffer, "\n");
+}
+
+static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
+{
+ struct snd_info_entry *entry;
+
+ if (!snd_card_proc_new(chip->card, "riptide", &entry))
+ snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read);
+}
+
+static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
+{
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ int err = 0;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_riptide_codec_write,
+ .read = snd_riptide_codec_read,
+ };
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ ac97.scaps = AC97_SCAP_SKIP_MODEM;
+
+ if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
+ return err;
+
+ chip->ac97_bus = pbus;
+ ac97.pci = chip->pci;
+ if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0)
+ return err;
+ return err;
+}
+
+#ifdef SUPPORT_JOYSTICK
+static int have_joystick;
+static struct pci_dev *riptide_gameport_pci;
+static struct gameport *riptide_gameport;
+
+static int __devinit
+snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
+{
+ static int dev;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ if (joystick_port[dev]) {
+ riptide_gameport = gameport_allocate_port();
+ if (riptide_gameport) {
+ if (!request_region
+ (joystick_port[dev], 8, "Riptide gameport")) {
+ snd_printk(KERN_WARNING
+ "Riptide: cannot grab gameport 0x%x\n",
+ joystick_port[dev]);
+ gameport_free_port(riptide_gameport);
+ riptide_gameport = NULL;
+ } else {
+ riptide_gameport_pci = pci;
+ riptide_gameport->io = joystick_port[dev];
+ gameport_register_port(riptide_gameport);
+ }
+ }
+ }
+ dev++;
+ return 0;
+}
+
+static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
+{
+ if (riptide_gameport) {
+ if (riptide_gameport_pci == pci) {
+ release_region(riptide_gameport->io, 8);
+ riptide_gameport_pci = NULL;
+ gameport_unregister_port(riptide_gameport);
+ riptide_gameport = NULL;
+ }
+ }
+}
+#endif
+
+static int __devinit
+snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct snd_riptide *chip;
+ unsigned short addr;
+ int err = 0;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (card == NULL)
+ return -ENOMEM;
+ if ((err = snd_riptide_create(card, pci, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ card->private_data = chip;
+ if ((err = snd_riptide_pcm(chip, 0, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if ((err = snd_riptide_mixer(chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, LEGACY_ENABLE_ALL
+ | (opl3_port[dev] ? LEGACY_ENABLE_FM : 0)
+#ifdef SUPPORT_JOYSTICK
+ | (joystick_port[dev] ? LEGACY_ENABLE_GAMEPORT :
+ 0)
+#endif
+ | (mpu_port[dev]
+ ? (LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU) :
+ 0)
+ | ((chip->irq << 4) & 0xF0));
+ if ((addr = mpu_port[dev]) != 0) {
+ pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, addr);
+ if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
+ addr, 0, chip->irq, 0,
+ &chip->rmidi)) < 0)
+ snd_printk(KERN_WARNING
+ "Riptide: Can't Allocate MPU at 0x%x\n",
+ addr);
+ else
+ chip->mpuaddr = addr;
+ }
+ if ((addr = opl3_port[dev]) != 0) {
+ pci_write_config_word(chip->pci, PCI_EXT_FM_Base, addr);
+ if ((err = snd_opl3_create(card, addr, addr + 2,
+ OPL3_HW_RIPTIDE, 0,
+ &chip->opl3)) < 0)
+ snd_printk(KERN_WARNING
+ "Riptide: Can't Allocate OPL3 at 0x%x\n",
+ addr);
+ else {
+ chip->opladdr = addr;
+ if ((err =
+ snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL)) < 0)
+ snd_printk(KERN_WARNING
+ "Riptide: Can't Allocate OPL3-HWDEP\n");
+ }
+ }
+#ifdef SUPPORT_JOYSTICK
+ if ((addr = joystick_port[dev]) != 0) {
+ pci_write_config_word(chip->pci, PCI_EXT_Game_Base, addr);
+ chip->gameaddr = addr;
+ }
+#endif
+
+ strcpy(card->driver, "RIPTIDE");
+ strcpy(card->shortname, "Riptide");
+#ifdef SUPPORT_JOYSTICK
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
+ card->shortname, chip->port, chip->irq, chip->mpuaddr,
+ chip->opladdr, chip->gameaddr);
+#else
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x",
+ card->shortname, chip->port, chip->irq, chip->mpuaddr,
+ chip->opladdr);
+#endif
+ snd_riptide_proc_init(chip);
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+}
+
+static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+ .name = "RIPTIDE",
+ .id_table = snd_riptide_ids,
+ .probe = snd_card_riptide_probe,
+ .remove = __devexit_p(snd_card_riptide_remove),
+#ifdef CONFIG_PM
+ .suspend = riptide_suspend,
+ .resume = riptide_resume,
+#endif
+};
+
+#ifdef SUPPORT_JOYSTICK
+static struct pci_driver joystick_driver = {
+ .name = "Riptide Joystick",
+ .id_table = snd_riptide_joystick_ids,
+ .probe = snd_riptide_joystick_probe,
+ .remove = __devexit_p(snd_riptide_joystick_remove),
+};
+#endif
+
+static int __init alsa_card_riptide_init(void)
+{
+ int err;
+ if ((err = pci_register_driver(&driver)) < 0)
+ return err;
+#if defined(SUPPORT_JOYSTICK)
+ if (pci_register_driver(&joystick_driver) < 0) {
+ have_joystick = 0;
+ snd_printk(KERN_INFO "no joystick found\n");
+ } else
+ have_joystick = 1;
+#endif
+ return 0;
+}
+
+static void __exit alsa_card_riptide_exit(void)
+{
+ pci_unregister_driver(&driver);
+#if defined(SUPPORT_JOYSTICK)
+ if (have_joystick)
+ pci_unregister_driver(&joystick_driver);
+#endif
+}
+
+module_init(alsa_card_riptide_init);
+module_exit(alsa_card_riptide_exit);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 1957d29c119e..0f171dd1377b 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2333,6 +2333,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
{ .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
{ .subvendor = 0x1019, .subdevice = 0xa101, .action = VIA_DXS_SRC },
+ { .subvendor = 0x1019, .subdevice = 0xaa01, .action = VIA_DXS_SRC }, /* ECS K8T890-A */
{ .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
{ .subvendor = 0x1025, .subdevice = 0x0046, .action = VIA_DXS_SRC }, /* Acer Aspire 1524 WLMi */
{ .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
@@ -2373,6 +2374,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
{ .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+ { .subvendor = 0x1695, .subdevice = 0x300c, .action = VIA_DXS_SRC }, /* EPoX EP-8KRAI */
{ .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */
{ .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */
{ .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 77caf43a3109..adfdce7499d1 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -57,18 +57,12 @@ static struct snd_card *card_list[SNDRV_CARDS];
/*
* prototypes
*/
-static void pdacf_config(dev_link_t *link);
+static int pdacf_config(struct pcmcia_device *link);
static void snd_pdacf_detach(struct pcmcia_device *p_dev);
-static void pdacf_release(dev_link_t *link)
+static void pdacf_release(struct pcmcia_device *link)
{
- if (link->state & DEV_CONFIG) {
- /* release cs resources */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
- }
+ pcmcia_disable_device(link);
}
/*
@@ -76,7 +70,7 @@ static void pdacf_release(dev_link_t *link)
*/
static int snd_pdacf_free(struct snd_pdacf *pdacf)
{
- dev_link_t *link = &pdacf->link;
+ struct pcmcia_device *link = pdacf->p_dev;
pdacf_release(link);
@@ -96,10 +90,9 @@ static int snd_pdacf_dev_free(struct snd_device *device)
/*
* snd_pdacf_attach - attach callback for cs
*/
-static int snd_pdacf_attach(struct pcmcia_device *p_dev)
+static int snd_pdacf_probe(struct pcmcia_device *link)
{
int i;
- dev_link_t *link; /* Info for cardmgr */
struct snd_pdacf *pdacf;
struct snd_card *card;
static struct snd_device_ops ops = {
@@ -139,7 +132,7 @@ static int snd_pdacf_attach(struct pcmcia_device *p_dev)
pdacf->index = i;
card_list[i] = card;
- link = &pdacf->link;
+ pdacf->p_dev = link;
link->priv = pdacf;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -156,13 +149,7 @@ static int snd_pdacf_attach(struct pcmcia_device *p_dev)
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
- /* Chain drivers */
- link->next = NULL;
-
- link->handle = p_dev;
- pdacf_config(link);
-
- return 0;
+ return pdacf_config(link);
}
@@ -209,9 +196,8 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq
/*
* snd_pdacf_detach - detach callback for cs
*/
-static void snd_pdacf_detach(struct pcmcia_device *p_dev)
+static void snd_pdacf_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "pdacf_detach called\n");
@@ -230,13 +216,11 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void pdacf_config(dev_link_t *link)
+static int pdacf_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct snd_pdacf *pdacf = link->priv;
tuple_t tuple;
cisparse_t *parse = NULL;
- config_info_t conf;
u_short buf[32];
int last_fn, last_ret;
@@ -244,7 +228,7 @@ static void pdacf_config(dev_link_t *link)
parse = kmalloc(sizeof(*parse), GFP_KERNEL);
if (! parse) {
snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
- return;
+ return -ENOMEM;
}
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
@@ -252,71 +236,51 @@ static void pdacf_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.ConfigIndex = 0x5;
kfree(parse);
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
- link->dev = &pdacf->node;
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ link->dev_node = &pdacf->node;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ pcmcia_disable_device(link);
+ return -ENODEV;
}
#ifdef CONFIG_PM
-static int pdacf_suspend(struct pcmcia_device *dev)
+static int pdacf_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "SUSPEND\n");
- link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
snd_pdacf_suspend(chip, PMSG_SUSPEND);
}
- snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
return 0;
}
-static int pdacf_resume(struct pcmcia_device *dev)
+static int pdacf_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "RESUME\n");
- link->state &= ~DEV_SUSPEND;
-
- snd_printdd(KERN_DEBUG "CARD_RESET\n");
- if (DEV_OK(link)) {
- snd_printdd(KERN_DEBUG "requestconfig...\n");
- pcmcia_request_configuration(link->handle, &link->conf);
+ if (pcmcia_dev_present(link)) {
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
snd_pdacf_resume(chip);
@@ -343,7 +307,7 @@ static struct pcmcia_driver pdacf_cs_driver = {
.drv = {
.name = "snd-pdaudiocf",
},
- .probe = snd_pdacf_attach,
+ .probe = snd_pdacf_probe,
.remove = snd_pdacf_detach,
.id_table = snd_pdacf_ids,
#ifdef CONFIG_PM
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 2744f189a613..9a14a4f64bd3 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -116,7 +116,7 @@ struct snd_pdacf {
void *pcm_area;
/* pcmcia stuff */
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
};
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 66900d20a42f..7e0cda2b6ef9 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -59,15 +59,9 @@ static unsigned int card_alloc;
/*
*/
-static void vxpocket_release(dev_link_t *link)
+static void vxpocket_release(struct pcmcia_device *link)
{
- if (link->state & DEV_CONFIG) {
- /* release cs resources */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
- }
+ pcmcia_disable_device(link);
}
/*
@@ -132,9 +126,9 @@ static struct snd_vx_hardware vxp440_hw = {
/*
* create vxpocket instance
*/
-static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
+static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl,
+ struct pcmcia_device *link)
{
- dev_link_t *link; /* Info for cardmgr */
struct vx_core *chip;
struct snd_vxpocket *vxp;
static struct snd_device_ops ops = {
@@ -154,7 +148,7 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
vxp = (struct snd_vxpocket *)chip;
- link = &vxp->link;
+ vxp->p_dev = link;
link->priv = chip;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -167,7 +161,6 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
link->irq.Instance = chip;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -215,9 +208,8 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void vxpocket_config(dev_link_t *link)
+static int vxpocket_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct vx_core *chip = link->priv;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
tuple_t tuple;
@@ -229,24 +221,24 @@ static void vxpocket_config(dev_link_t *link)
parse = kmalloc(sizeof(*parse), GFP_KERNEL);
if (! parse) {
snd_printk(KERN_ERR "vx: cannot allocate\n");
- return;
+ return -ENOMEM;
}
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
/* redefine hardware record according to the VERSION1 string */
tuple.DesiredTuple = CISTPL_VERS_1;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) {
snd_printdd("VX-pocket is detected\n");
} else {
@@ -257,67 +249,50 @@ static void vxpocket_config(dev_link_t *link)
strcpy(chip->card->driver, vxp440_hw.name);
}
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
- chip->dev = &handle_to_dev(link->handle);
+ chip->dev = &handle_to_dev(link);
snd_card_set_dev(chip->card, chip->dev);
if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
- link->dev = &vxp->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &vxp->node;
kfree(parse);
- return;
+ return 9;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
kfree(parse);
+ return -ENODEV;
}
#ifdef CONFIG_PM
-static int vxp_suspend(struct pcmcia_device *dev)
+static int vxp_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct vx_core *chip = link->priv;
snd_printdd(KERN_DEBUG "SUSPEND\n");
- link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
snd_vx_suspend(chip, PMSG_SUSPEND);
}
- snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int vxp_resume(struct pcmcia_device *dev)
+static int vxp_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct vx_core *chip = link->priv;
snd_printdd(KERN_DEBUG "RESUME\n");
- link->state &= ~DEV_SUSPEND;
-
- snd_printdd(KERN_DEBUG "CARD_RESET\n");
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
- snd_printdd(KERN_DEBUG "requestconfig...\n");
- pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
snd_vx_resume(chip);
@@ -333,7 +308,7 @@ static int vxp_resume(struct pcmcia_device *dev)
/*
*/
-static int vxpocket_attach(struct pcmcia_device *p_dev)
+static int vxpocket_probe(struct pcmcia_device *p_dev)
{
struct snd_card *card;
struct snd_vxpocket *vxp;
@@ -358,7 +333,7 @@ static int vxpocket_attach(struct pcmcia_device *p_dev)
return -ENOMEM;
}
- vxp = snd_vxpocket_new(card, ibl[i]);
+ vxp = snd_vxpocket_new(card, ibl[i], p_dev);
if (! vxp) {
snd_card_free(card);
return -ENODEV;
@@ -368,20 +343,13 @@ static int vxpocket_attach(struct pcmcia_device *p_dev)
vxp->index = i;
card_alloc |= 1 << i;
- /* Chain drivers */
- vxp->link.next = NULL;
-
- vxp->link.handle = p_dev;
- vxp->link.state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- p_dev->instance = &vxp->link;
- vxpocket_config(&vxp->link);
+ vxp->p_dev = p_dev;
- return 0;
+ return vxpocket_config(p_dev);
}
-static void vxpocket_detach(struct pcmcia_device *p_dev)
+static void vxpocket_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct snd_vxpocket *vxp;
struct vx_core *chip;
@@ -413,7 +381,7 @@ static struct pcmcia_driver vxp_cs_driver = {
.drv = {
.name = "snd-vxpocket",
},
- .probe = vxpocket_attach,
+ .probe = vxpocket_probe,
.remove = vxpocket_detach,
.id_table = vxp_ids,
#ifdef CONFIG_PM
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index 67efae3f6c8d..27ea002294c0 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -42,7 +42,7 @@ struct snd_vxpocket {
int index; /* card index */
/* pcmcia stuff */
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
};
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index aa09ebd9ffb8..46eebf5610e3 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -255,7 +255,7 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip)
#ifdef CONFIG_KMOD
if (current->fs->root)
- request_module("i2c-keywest");
+ request_module("i2c-powermac");
#endif /* CONFIG_KMOD */
mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 1146dd882bb1..70e4ebc70260 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1313,7 +1313,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
#ifdef CONFIG_KMOD
if (current->fs->root)
- request_module("i2c-keywest");
+ request_module("i2c-powermac");
#endif /* CONFIG_KMOD */
mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 8d08b34a1cb5..ce86283ee0fa 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -306,8 +306,8 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
cval->res = 1;
if (val < cval->min)
return 0;
- else if (val > cval->max)
- return (cval->max - cval->min) / cval->res;
+ else if (val >= cval->max)
+ return (cval->max - cval->min + cval->res - 1) / cval->res;
else
return (val - cval->min) / cval->res;
}
@@ -670,6 +670,36 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
}
if (cval->res == 0)
cval->res = 1;
+
+ /* Additional checks for the proper resolution
+ *
+ * Some devices report smaller resolutions than actually
+ * reacting. They don't return errors but simply clip
+ * to the lower aligned value.
+ */
+ if (cval->min + cval->res < cval->max) {
+ int last_valid_res = cval->res;
+ int saved, test, check;
+ get_cur_mix_value(cval, minchn, &saved);
+ for (;;) {
+ test = saved;
+ if (test < cval->max)
+ test += cval->res;
+ else
+ test -= cval->res;
+ if (test < cval->min || test > cval->max ||
+ set_cur_mix_value(cval, minchn, test) ||
+ get_cur_mix_value(cval, minchn, &check)) {
+ cval->res = last_valid_res;
+ break;
+ }
+ if (test == check)
+ break;
+ cval->res *= 2;
+ }
+ set_cur_mix_value(cval, minchn, saved);
+ }
+
cval->initialized = 1;
}
return 0;
@@ -695,7 +725,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
if (! cval->initialized)
get_min_max(cval, 0);
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = (cval->max - cval->min) / cval->res;
+ uinfo->value.integer.max =
+ (cval->max - cval->min + cval->res - 1) / cval->res;
}
return 0;
}
diff --git a/usr/Makefile b/usr/Makefile
index e2129cb570bb..19d74e6f2685 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -1,65 +1,48 @@
+#
+# kbuild file for usr/ - including initramfs image
+#
-obj-y := initramfs_data.o
-
-hostprogs-y := gen_init_cpio
+klibcdirs:;
-clean-files := initramfs_data.cpio.gz initramfs_list
+# Generate builtin.o based on initramfs_data.o
+obj-y := initramfs_data.o
# initramfs_data.o contains the initramfs_data.cpio.gz image.
# The image is included using .incbin, a dependency which is not
# tracked automatically.
$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
-ifdef CONFIG_INITRAMFS_ROOT_UID
-gen_initramfs_args += -u $(CONFIG_INITRAMFS_ROOT_UID)
-endif
-
-ifdef CONFIG_INITRAMFS_ROOT_GID
-gen_initramfs_args += -g $(CONFIG_INITRAMFS_ROOT_GID)
-endif
-
-# The $(shell echo $(CONFIG_INITRAMFS_SOURCE)) is to remove the
-# gratuitous begin and end quotes from the Kconfig string type.
-# Internal, escaped quotes in the Kconfig string will loose the
-# escape and become active quotes.
-quotefixed_initramfs_source := $(shell echo $(CONFIG_INITRAMFS_SOURCE))
-
-filechk_initramfs_list = $(CONFIG_SHELL) \
- $(srctree)/scripts/gen_initramfs_list.sh $(gen_initramfs_args) $(quotefixed_initramfs_source)
-
-$(obj)/initramfs_list: $(obj)/Makefile FORCE
- $(call filechk,initramfs_list)
-
-quiet_cmd_cpio = CPIO $@
- cmd_cpio = ./$< $(obj)/initramfs_list > $@
-
-
-# Check if the INITRAMFS_SOURCE is a cpio archive
-ifneq (,$(findstring .cpio,$(quotefixed_initramfs_source)))
-
-# INITRAMFS_SOURCE has a cpio archive - verify that it's a single file
-ifneq (1,$(words $(quotefixed_initramfs_source)))
-$(error Only a single file may be specified in CONFIG_INITRAMFS_SOURCE (="$(quotefixed_initramfs_source)") when a cpio archive is directly specified.)
-endif
-# Now use the cpio archive directly
-initramfs_data_cpio = $(quotefixed_initramfs_source)
-targets += $(quotefixed_initramfs_source)
-
-else
-
-# INITRAMFS_SOURCE is not a cpio archive - create one
-$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio \
- $(initramfs-y) $(obj)/initramfs_list FORCE
- $(call if_changed,cpio)
-
-targets += initramfs_data.cpio
-initramfs_data_cpio = $(obj)/initramfs_data.cpio
-
+#####
+# Generate the initramfs cpio archive
+
+hostprogs-y := gen_init_cpio
+initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
+ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
+ $(CONFIG_INITRAMFS_SOURCE),-d)
+ramfs-args := \
+ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
+ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
+ $(ramfs-input)
+
+# .initramfs_data.cpio.gz.d is used to identify all files included
+# in initramfs and to detect if any files are added/removed.
+# Removed files are identified by directory timestamp being updated
+# The dependency list is generated by gen_initramfs.sh -l
+ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),)
+ include $(obj)/.initramfs_data.cpio.gz.d
endif
-
-$(obj)/initramfs_data.cpio.gz: $(initramfs_data_cpio) FORCE
- $(call if_changed,gzip)
-
-targets += initramfs_data.cpio.gz
+quiet_cmd_initfs = GEN $@
+ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
+
+targets := initramfs_data.cpio.gz
+$(deps_initramfs): klibcdirs
+# We rebuild initramfs_data.cpio.gz if:
+# 1) Any included file is newer then initramfs_data.cpio.gz
+# 2) There are changes in which files are included (added or deleted)
+# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz
+# 4) arguments to gen_initramfs.sh changes
+$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
+ $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
+ $(call if_changed,initfs)
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 33dbcbf77c5b..83acd6cc0b3c 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -471,6 +471,7 @@ int main (int argc, char *argv[])
"ERROR: incorrect format, could not locate file type line %d: '%s'\n",
line_nr, line);
ec = -1;
+ break;
}
if ('\n' == *type) {
@@ -506,7 +507,8 @@ int main (int argc, char *argv[])
line_nr, line);
}
}
- cpio_trailer();
+ if (ec == 0)
+ cpio_trailer();
exit(ec);
}